我第一次看到Python,我被困在这里:
class A:
def __init__(self):
a = foo("baa")
class B(A):
b = foo("boo")
def foo(string):
return string
此时我加载了上面的文件(名为classes
),发生了这种情况:
$ python
Python 2.6.1 (r261:67515, Jun 24 2010, 21:47:49)
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from classes import *
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "classes.py", line 5, in <module>
class B(A):
File "classes.py", line 6, in B
b = foo("boo")
NameError: name 'foo' is not defined
注意错误在B类中的情况,其中foo
是直接调用而不是__init__
。另请注意我尚未实例化类B
。
第一个问题:
继续前进。通过将foo()
的定义移到上面几行来解决“问题”:
def foo(string):
return string
class A:
def __init__(self):
a = foo("baa")
class B(A):
b = foo("boo")
现在我可以做到
>>> x = B()
>>> x.b
'boo'
但我做不到
>>> y = A()
>>> y.a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: A instance has no attribute 'a'
进一步的问题:
__init__
没有理解的是什么? 我不认为这与forward declaration相同,因此我希望这个问题不重复。
另一方面,我的目标是实现DSL,但这主要是让自己学习python的借口。
答案 0 :(得分:6)
首先,在类B
中,函数foo()
在声明之前被调用。 A
没有此问题,因为foo()
仅在实例化类时调用 - 在定义函数foo之后。
对于你的第二个问题,y.a将无效,因为你没有说self.a = foo('stirng')
。 a = foo('stirng')
仅在__ init __
范围内创建变量a。
理想的__ init __
函数将变量分配给实例self
。
答案 1 :(得分:1)
你对__init__
没有理解的事情是它只在你实例化(即创建一个)类A
的实例时被调用。因为你的代码中没有任何地方你实际上创建了这个类的实例,所以你永远不会调用它的初始化器,因此永远不会遇到前向声明。
一般来说,前向声明在Python中不是问题,因为只有在调用必要的函数时才会计算引用。这里的问题是类定义是在define-time 执行的。更具体地说,这是Python解释器遇到class
语句时发生的情况:
__dict__
。当然,你不需要知道定义一个类;你只需要记住,在第一次定义类时,将会执行类定义中的任何内容! (这很少是一个问题,因为类级变量首先不常见,通常不需要在定义时动态设置。)
这个问题也出现在函数定义中:当你做
时def foo(x=bar()): pass
然后bar
会在定义foo
时调用一次,而不会再次调用。{/ p>
尝试运行以下代码,看看它是否澄清了事情:
class A():
def __init__(self):
self.a = foo()
a = A()
def foo():
pass
答案 2 :(得分:1)
class A:
def __init__(self):
a = foo("baa")
class B(A):
b = foo("boo")
a是一个实例属性 - 每个A都有自己的变量,只有在创建A对象时才会评估foo(“baa”)。
b是一个类属性 - 每个B对象共享b的相同副本,并且在定义类时评估foo(“boo”)。
一般情况下,只要在评估引用之前定义,就可以引用尚不存在的函数和类,即在您实际尝试之前调用函数。)