【发布时间】:2009-09-18 15:17:37
【问题描述】:
为什么以下在 Python 中不起作用?
def make_class(a):
class A(object):
a=a
return A
【问题讨论】:
为什么以下在 Python 中不起作用?
def make_class(a):
class A(object):
a=a
return A
【问题讨论】:
工作得很好:
>>> def make_class(a):
class A(object):
_a=a
return A
>>> make_class('df')
<class '__main__.A'>
>>> make_class('df')._a
'df'
顺便说一句,function 不是 Python 中的保留关键字。
【讨论】:
让我们用一个更简单的例子来解决同样的问题:
a = 'something'
def boo():
a = a
boo()
这会失败,因为 python 中的赋值,没有伴随的 global 或 nonlocal 语句,意味着分配的名称是当前作用域的本地名称。这不仅发生在函数中,还发生在类定义中。
这意味着您不能对全局变量和局部变量使用相同的名称并同时使用它们。您可以使用 Aaron Digulia 的回答中的解决方法,或使用其他名称:
def make_class(_a):
class A(object):
a = _a
return A
【讨论】:
两者似乎都可以正常工作(至少在 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
【讨论】:
试试
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 不是来自def 的a;相反,Python 在 A 类中查找它,因为在作业的左侧已经提到了 a。
这通过函数变得更加简洁:
x = 1
def a(x):
print 'a:',x
x = 3
def b():
print 'b:',x
b()
a(2)
def c():
x = x
显然,第一次打印应该打印 2,而不是 1,所以a 的参数x 必须遮蔽全局变量x。 b 是在x 被称为a 的参数的范围内定义的,因此打印工作正常。
但是,如果您尝试调用 c,则会得到 UnboundLocalError: local variable 'x' referenced before assignment,因为 Python 不会自动绑定全局变量。要解决此问题,您必须在分配前添加 global x。
您的案例看起来更像这样:
x = 1
def a(x):
print 'a:',x
x = 3
def b():
x = x
print 'b:',x
b()
a(2)
虽然在上面的示例中打印 x 有效,但分配不起作用。这是确保变量不泄漏的安全措施。解决方案是使用默认参数将变量“复制”到b 的作用域中:
x = 1
def a(x):
print 'a:',x
x = 3
def b(x=x):
x = x
print 'b:',x
b()
a(2)
要解决您的问题,您需要告诉 Python“使 make_class 的参数 a 在 A 中可见”,您需要在尝试分配字段 a 之前执行此操作班级。这在 Python 中是不可能的。如果您可以使a 可见,则赋值将更改参数,而不是字段,因为 Python 无法区分两者。
由于您无法使其可见,因此没有可读取的 a,因此是 NameError。
请参阅here,了解 Python 中名称范围的说明。
【讨论】: