[英]Python forward-declaration of functions inside classes
我第一次看到了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__
理解是什么? 我不認為這與前瞻性聲明相同,因此我希望這個問題不重復。
另外,我的目標是實現DSL,但這主要是讓自己學習python的借口。
首先,在B
類中,函數foo()
在聲明之前被調用。 A
沒有這個問題,因為只有在實例化類時才調用foo()
- 在定義函數foo之后。
對於你的第二個問題,你不會工作,因為你沒有說self.a = foo('stirng')
。 a = foo('stirng')
僅在__ init __
的范圍內創建變量a。
理想的__ init __
函數將變量分配給實例self
。
你對__init__
沒有理解的是它只在你實例化(即做一個實例) A
類時被調用。 因為你的代碼中沒有任何地方你實際上已經創建了這個類的實例,所以你永遠不會調用它的初始化器,因此永遠不會遇到前向聲明。
通常,前向聲明在Python中不是問題,因為只有在調用必要的函數時才會計算引用。 這里的問題是類定義是在define-time執行的 。 更具體地說,這是Python解釋器遇到class
聲明時發生的情況:
__dict__
。 當然,你不需要知道定義一個類; 你只需要記住,在第一次定義類時,將會執行類定義中的任何內容! (這很少是一個問題,因為類級變量首先不常見,通常不需要在定義時動態設置。)
這個問題也出現在函數定義中:當你這樣做時
def foo(x=bar()): pass
然后bar
將被調用一次,在定義foo
,並且永遠不會再次調用。
嘗試運行以下代碼,看看它是否澄清了一些事情:
class A():
def __init__(self):
self.a = foo()
a = A()
def foo():
pass
class A:
def __init__(self):
a = foo("baa")
class B(A):
b = foo("boo")
a是實例屬性 - 每個A都有自己的變量,只有在創建A對象時才會評估foo(“baa”)。
b是一個類屬性 - 每個B對象共享b的相同副本,並且在定義類時評估foo(“boo”)。
通常, 只要在評估引用之前定義它們(即在實際嘗試調用函數之前),就可以引用尚不存在的函數和類。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.