考虑以下代码:
class Bar(object): pass
class Foo(object):
def bar(self): return Bar()
f = Foo()
def Bar(): pass
print(f.bar())
打印None
。但是那个可怜的家伙bar
并不期望Bar
成为后来的成就!
我的问题是,我可以在Foo
(希望不会污染外部范围)内写出“最好”(最优雅,最有效,最恐怖,无论如何)的代码,这些代码将确保 bar
可以引用声明时定义的Bar
而不是调用?
(并不是我无法提出任何解决方案,而是因为我不知道正确的解决方案是什么。)
答案 0 :(得分:2)
To"静态绑定"在创建函数/方法时的名称,您可以使用默认参数:
class Bar(object):
pass
class Foo(object):
def bar(self, Bar=Bar):
return Bar()
每this famous Python "gotcha",默认参数值仅评估一次。
在这种情况下,它并不是非常有用,因为将一个函数命名为一个类就是你自己的愚蠢错误(随后的错误会为你提供有用的信息);绑定名称只会使例如更难稍后嘲笑课程。但是,根据this question。
解决嵌套函数中的后期绑定问题可能很有用每ShadowRanger's comment,如果你正在使用Python 3.x,你可以将*,
添加到参数列表(bar(self, *, Bar=Bar)
),以防止调用者意外地破坏默认值传递太多的位置论点;任何其他参数都会引发TypeError
。
答案 1 :(得分:0)
回答我自己的问题,但答案是将所有内容都放在封闭中:
def static_define(locals, super, tuple): # All arguments are bound STATICALLY
# Anything defined here will be exported externally
class Foo(tuple):
def __new__(cls, *args):
return super(Foo, cls).__new__(cls, args)
return locals()
# The following line "exports" all the returned locals into the current global namespace
(lambda f, bi: (lambda g: g.pop(f.__name__) and bi.None or g.update((lambda args: (lambda l: bi.reduce(lambda l, v: l.pop(v, bi.None) and bi.None or l, args, l))(f(*bi.map(lambda v: bi.eval(v, g), args))))(bi.__import__('inspect').getargspec(f).args)))(f.__globals__))(static_define, __builtins__)
super = None # tamper!
print Foo() # unaffected by tampering