为什么Python类定义不能为自己分配闭包变量?

时间:2009-09-18 15:17:37

标签: python closures

为什么以下不能在Python中工作?

def make_class(a):
    class A(object):
        a=a
    return A

4 个答案:

答案 0 :(得分:9)

工作正常:

>>> def make_class(a):
    class A(object):
        _a=a
    return A

>>> make_class('df')
<class '__main__.A'>
>>> make_class('df')._a
'df'

btw,function不是Python中的保留关键字。

答案 1 :(得分:6)

让我们使用一个更简单的例子来解决同样的问题:

a = 'something'
def boo():
    a = a
boo()

这会失败,因为python中的赋值没有附带的globalnonlocal语句,意味着指定的名称是当前作用域的本地名称。这不仅发生在函数中,也发生在类定义中。

这意味着您不能对全局变量和局部变量使用相同的名称并同时使用它们。您可以使用Aaron Digulia的答案中的解决方法,或使用其他名称:

def make_class(_a):
    class A(object):
        a = _a
    return A

答案 2 :(得分:2)

两者似乎都运行良好(至少在Python 2.5中):

>>> def make_class(a):
...     class A(object):
...             _a = a
...     return A
... 
>>> make_class(10)._a
10
>>> def make_class(b):
...     class B(object):
...             def get_b(self):
...                     return b
...     return B
... 
>>> make_class(10)().get_b()
10

答案 3 :(得分:2)

尝试

def make_class(a):
    class A(object): pass
    A.a=a
    return A

您得到的错误(NameError: name 'a' is not defined)是因为类中的名称a会影响函数的参数a;因此,当您在代码中尝试“a = a”时,没有定义a。换句话说,右侧a 来自a的{​​{1}};相反,Python在类def中查找它,因为在作业的左侧已经提到了A

使用功能变得更加干净:

a

显然,第一次打印应该打印2而不是1,因此x = 1 def a(x): print 'a:',x x = 3 def b(): print 'b:',x b() a(2) def c(): x = x 的参数x必须遮蔽全局变量axb被称为x的参数的范围内定义,因此打印效果正常。

但是,如果尝试调用a,则会得到c,因为Python不会自动绑定全局变量。要解决此问题,您必须在分配前添加UnboundLocalError: local variable 'x' referenced before assignment

你的案子看起来更像是这样:

global x

虽然在上面的示例中打印x = 1 def a(x): print 'a:',x x = 3 def b(): x = x print 'b:',x b() a(2) ,但分配不起作用。这是一种安全措施,可确保变量不会泄漏。解决方案是使用默认参数将变量“复制”到x的范围:

b

要解决您的问题,您需要告诉Python“在x = 1 def a(x): print 'a:',x x = 3 def b(x=x): x = x print 'b:',x b() a(2) 中显示a make_class的参数”,您需要在尝试分配之前执行此操作该类的字段A。这在Python中是不可能的。如果可以使a可见,则赋值将更改参数,而不是字段,因为Python无法区分这两者。

由于您无法将其显示,因此无法读取a,因此a

有关Python中名称范围的解释,请参阅here