AnC*_*AnC 4 python metaprogramming
是否可以在Python中动态确定变量的名称?
例如,我有时会遇到以下情况:
name = foo if bar else baz
type = alpha or bravo
D = {
"name": name,
"type": type
}
Run Code Online (Sandbox Code Playgroud)
如果可以通过类似的方式减少重复,那将是很好的D = makedict(name, type)
.
有点相关,函数有时会知道自己的名字:
class Item(object):
def item_create(self, item):
dispatch("create", item)
def item_delete(self, item):
dispatch("delete", item)
Run Code Online (Sandbox Code Playgroud)
这里可以通过传递诸如__methodname__
而不是分别明确地重复"创建"和"删除"之类的东西来减少重复.(我假设装饰师可以用于此,但这看起来有点过分.)
Ale*_*lli 10
在一般情况下,您不能从值中推断出名称(可能没有名称,可能有多个名称等); 当你打电话给你的假设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
Run Code Online (Sandbox Code Playgroud)
如果你热衷于通过内省来挖掘命名空间,而不是让调用者干净地指定它们,请查看inspect.getouterframes - 但我建议你重新考虑.
你提出的第二个问题是完全不同的(虽然你可以inspect
再次使用函数来内省调用者的名字,或者函数自己的名字 - 这是一个多么奇怪的想法!).这两种情况的共同之处在于,您使用极其强大且危险的机器来完成更简单的工作(更容易确保正确性,更容易调试任何问题,更容易测试等等) - -远远没有装饰是"杀鸡用牛刀",他们远远比你提出的内省更简单,更清晰.如果您拥有所有形式的无数方法:
def item_blah(self, item):
dispatch("blah", item)
Run Code Online (Sandbox Code Playgroud)
创建它们的最简单方法可能是:
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))
Run Code Online (Sandbox Code Playgroud)
避免重复是一个很好的想法,但运行时内省通常不是实现该想法的最佳方式,Python提供了许多这种实现的替代方法.
归档时间: |
|
查看次数: |
4107 次 |
最近记录: |