簡體   English   中英

Python內部函數的前向聲明

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM