2016-07-02 8 views
0

Скажем, я хотел бы создать строфу интроспекции, которая отображает доступные детали функции.
Что-то вроде нижней части следующего кода:Как напечатать имя атрибута Python?

def sample(_range=4): 
    """ produce a range of integers """ 
    for i in range(_range): 
     yield i 

f = sample 
for i in (f.__name__, f.__doc__, f.__dict__, f.__code__, f.__defaults__, f.__globals__, f.__closure__): 
    print("XXX", i) 

То, что я не в состоянии достигнуть меняется XXX к чему-то, что бы напечатать имя атрибута, например, вместо

XXX sample 
XXX produce a range of integers 
XXX {} 
XXX <code object sample at 0xfff15890, file "/tmp/tmp.py", line 1> 
XXX (4,) 
XXX {'__loader__': <_frozen_importlib.SourceFileLoader object at 0xfff13b30>, '__package__': None, '__file__': '/tmp/tmp.py', '__cached__': None, 'i': {...}, 'f': <function sample at 0xfff5b1e0>, '__builtins__': <module 'builtins' (built-in)>, '__doc__': None, '__spec__': None, '__name__': '__main__', 'sample': <function sample at 0xfff5b1e0>} 
XXX None 

Я d хотел бы иметь

__name__ sample 
__doc__ produce a range of integers 
__dict__ {} 
__code__ <code object sample at 0xfff15890, file "/tmp/tmp.py", line 1> 
__defaults__ (4,) 
f.__globals__ {'__loader__': <_frozen_importlib.SourceFileLoader object at 0xfff13b30>, '__package__': None, '__file__': '/tmp/tmp.py', '__cached__': None, 'i': {...}, 'f': <function sample at 0xfff5b1e0>, '__builtins__': <module 'builtins' (built-in)>, '__doc__': None, '__spec__': None, '__name__': '__main__', 'sample': <function sample at 0xfff5b1e0>} 
__closure__ None 

Что вы предложите заменить XXX?

+0

Вы можете использовать словарь? Имена как ключи и значения как атрибуты –

+2

Почему бы не перебрать имена вместо них? 'для имени в ['__name__', '__doc__', ...]: ...'. – jonrsharpe

+0

@MosesKoledoye под капотом, это именно то, что является объектом 'sample'! – jonrsharpe

ответ

2

Если, как в вашем примере, вы знаете имена атрибутов, которые вы хотите, это будет работать:

for fn in ('__name__', '__doc__', '__dict__', '__code__', '__defaults__', '__globals__', '__closure__'): 
    print(fn, getattr(f, fn)) 

Если вы спрашиваете, как получить имя, когда все у вас есть функция, то Я считаю, что вам не повезло; имя не является свойством функции, а скорее как оно ссылается, так как вы не можете спросить, какое имя переменной, содержащее номер 3, просто из числа. (Мысль: какое имя было бы для функции, которая является частью трех разных объектов, под другим именем?)

Я полагаю, если бы вы хотели имя функции в определенном объекте, вы могли бы выполнять итерацию над атрибутами этого объекта, ищем вашу функцию; когда вы его найдете, имя, с которым вы ссылались, будет тем, что вы хотите.

+0

Это должно быть 'getattr (f, fn)' – jonrsharpe

+0

'def foo(): pass' фактически дает объекту функции имя' foo'. Таким образом, функции могут и имеют имя; это просто переменная, имя которой вы не можете получить. – poke

1

Поскольку у вас уже есть список атрибутов, можно использовать getattr:

for name in ['__name__', '__doc__', '__dict__', '__code__', '__defaults__', '__globals__', '__closure__']: 
    print('{} -> {}'.format(name, getattr(f, name)))