В общем случае вы не можете вывести имя из значения (не может быть имени, могут быть несколько и т. Д.); когда вы звоните в свою гипотетическую makedict(name)
, значение из name
- это то, что makedict
получает, поэтому (опять же, в общем случае) он не может различить, какое имя (если есть). Вы могли бы исследовать пространства имен ваших вызывающих лиц, чтобы убедиться, что вам повезло, чтобы попасть в специальный случай, когда значение позволяет вам вывести имя (например, вы получаете 23
, и есть только одно имя на всех интересующих пространствах имен, которое имеет значение 23
!), но это явно хрупкая и неудобная архитектура. Кроме того, в вашем первом примере случае абсолютно гарантируется, что произойдет специальный случай , а не - значение в name
точно такое же, как в foo
или baz
, так что он на 100% уверен, что имя для этого значения будет безнадежно двусмысленный.
Вы могли бы принять совершенно другой подход, например, вызов makedict('name type', locals())
(прохождение locals()
явно может быть устранен с темной и глубокой магией самоанализа, но это не самый твердый выбор в целом) - передать в имен (и пространства имен, я предлагаю!) и имеют makedict
вывод значений, что, очевидно, гораздо более прочное предложение (так как каждое имя имеет ровно одно значение, но не наоборот). То есть:
def makedict(names, *namespaces):
d = {}
for n in names.split():
for ns in namespaces:
if n in ns:
d[n] = ns[n]
break
else:
d[n] = None # or, raise an exception
Если вы заинтересованы в выкапывания пространств имен интроспекции, а не иметь их чисто указанный абонент, посмотрите на inspect.getouterframes - но я предлагаю вам пересмотреть.
Вторая проблема, которую вы поднимаете, совсем другая (хотя вы могли бы снова использовать функции inspect
, чтобы исследовать имя вызывающего абонента или собственное имя функции - какая своеобразная идея!). Что общего в двух случаях, так это то, что вы используете чрезвычайно мощный и опасный механизм для выполнения работы, которая может быть выполнена гораздо проще (проще обеспечить правильность, проще отладить любые проблемы, проще протестировать и т. Д.) - - далекие от того, чтобы декораторы были «излишними», они далеки проще и яснее, чем предполагаемая интроспекция. Если у вас есть методы мильона все формы:
def item_blah(self, item):
dispatch("blah", item)
самый простой способ их создания может быть:
class Item(object): pass
def _makedispcall(n):
def item_whatever(self, item):
dispatch(n, item)
item_whatever.__name__ = 'item_' + n
return item_whatever
for n in 'create delete blah but wait theres more'.split():
setattr(Item, 'item_' + n, _makedispcall(n))
избежать повторения это отличная идея, но во время выполнения самоанализ обычно не лучший способ для реализации этой идеи, а Python предлагает множество альтернативных способов такой реализации.
Спасибо, это очень проницательно. Я ожидал, что не будет простого решения, и в конечном итоге согласен, что это не стоит проблем. – AnC