2010-01-09 26 views
14

對於遞歸函數,我們可以這樣做:蟒蛇:如何引用的類從它內部(如遞歸函數)

def f(i): 
    if i<0: return 
    print i 
    f(i-1) 

f(10) 

但是有沒有辦法做以下的事情嗎?

class A: 
    # do something 
    some_func(A) 
    # ... 
+1

不清楚你想要什麼或意思。 'A類:'不會創建一個對象,所以沒有'A'來引用。請參閱爲可能的事情提供的解決方案,你可能意味着... – 2010-01-09 23:50:28

+8

@Andrew __class A:__創建一個_class object_作爲Python中的類是第一類 – 2010-01-10 02:00:48

回答

4

如果你想指的是同一個對象,只是用「自我」:

class A: 
    def some_func(self): 
     another_func(self) 

如果你想創建相同類的新對象,只要做到這一點:

class A: 
    def some_func(self): 
     foo = A() 

如果你想有機會獲得 元類 類對象(最有可能不是你想要的),再一次,只是做:

class A: 
    def some_func(self): 
     another_func(A) # note that it reads A, not A() 
+2

只是一個澄清:在你的最後一個例子中,引用「A」被稱爲「類對象」,而不是「元類」,這是一個完全不同的概念。在你的例子中A的元類將是'類型。ClassType'(或'type',如果使用新式類或python3) – Crast 2010-01-09 23:55:20

-1

該類中的大部分代碼都在方法定義內,在這種情況下,您可以簡單地使用名稱A

+1

-1他非常具體地詢問在類的主體中調用A,而不是從它的方法中調用A. – 2010-01-10 02:53:08

0

你想實現什麼?可以使用元類訪問類來調整其定義,但不推薦使用它。

您的代碼示例可以簡單地寫爲:

class A(object): 
    pass 
some_func(A) 
1

沒有辦法做到這一點的類範圍內,不除非A被定義爲別的第一(然後some_func(A )會做一些與你期望的完全不同的東西)

除非你正在做某種類型的堆棧檢查來向類中添加位,否則爲什麼你會這樣做。爲什麼不只是:

class A: 
    # do something 
    pass 

some_func(A) 

也就是說,在A之後運行some_func。或者,如果您想以某種方式修改類A,則可以使用類裝飾器(它在2.6中添加的語法)或元類。你能否澄清你的用例?

0

沒有。它在一個函數中工作,因爲函數內容是在調用時執行的。但是課程內容是在定義時間執行的,此時課程還不存在。

它通常不是問題,因爲你可以定義後攻入進一步成員到類,這樣你就可以定義一個類分成多個部分:

class A(object): 
    spam= 1 

some_func(A) 

A.eggs= 2 

def _A_scramble(self): 
    self.spam=self.eggs= 0 
A.scramble= _A_scramble 

它,然而,相當不尋常的希望在自己定義的中間調用類的函數。目前還不清楚你想要做什麼,但有機會,你會更好用decorators(或相對較新的class decorators)。

0

如果它實際上在範圍內,那麼可以在其正文內引用該類的名稱(如內部方法定義);如果它在頂層定義,它會是什麼。 (在其他情況下可能不會,由於Python範圍的怪癖!)。

有關作用域疑難雜症的插圖,嘗試實例富:

class Foo(object): 
    class Bar(object): 
     def __init__(self): 
      self.baz = Bar.baz 
     baz = 15 
    def __init__(self): 
     self.bar = Foo.Bar() 

(這將抱怨全局名稱「欄」沒有被定義)


而且,東西告訴我你可能想看看類方法:docs on the classmethod function(用作裝飾器),a relevant SO question編輯:好的,所以這個建議可能根本不適合......這只是我在閱讀你的問題時想到的第一件事情,就像替代構造函數等。如果更簡單的東西適合你的需求,請避開@classmethod怪異。 :-)

5

你不能用你描述的特定語法來評估它們。示例函數給出的原因是函數體內調用f(i-1)是因爲名稱分辨率爲f直到實際調用該函數纔會執行。此時f存在於執行範圍內,因爲該函數已經被評估。在類示例的情況下,在類定義仍在評估期間,會查找對類名的引用。因此,它在當地範圍內還不存在。

備選地,期望的行爲可以使用元類像這樣來完成:

class MetaA(type): 

    def __init__(cls): 
     some_func(cls) 

class A(object): 
    __metaclass__=MetaA 
    # do something 
    # ... 

使用這種方法可以在該類被評估時執行的類對象上的任意操作。

+1

這是解釋*爲什麼不能完成的唯一答案(函數體不是僅僅根據定義來執行,而是類體)。感謝您的澄清。 – Dubslow 2017-10-30 08:37:06

1

如果你想要做的一點點事情哈克做

class A(object): 
    ... 
some_func(A) 

如果你想要做一些更復雜,你可以使用元類。元類負責在完全創建之前操作類對象。模板應該是:

class AType(type): 
    def __new__(meta, name, bases, dct): 
     cls = super(AType, meta).__new__(meta, name, bases, dct) 
     some_func(cls) 
     return cls 

class A(object): 
    __metaclass__ = AType 
    ... 

type是默認的元類。元類的實例是類,因此__new__返回(在本例中)A的修改實例。

有關元類的更多信息,請參閱http://docs.python.org/reference/datamodel.html#customizing-class-creation

14

在Python中,您不能在類體中引用該類,儘管在像Ruby這樣的語言中您可以這樣做。

在Python中,您可以使用類裝飾器,但一旦類初始化後就會調用它。另一種方法可能是使用元類,但它取決於你想要實現的。

+0

爲什麼?在這方面,什麼使得類定義體與函數體不同?鑑於函數和類都是頭等對象,他們身體的差異對我而言並不是很明顯。 編輯:正如下面的另一個答案指出的那樣,函數體不是在執行定義本身時執行的,而類體是作爲類定義執行的一部分執行的。 – Dubslow 2017-10-30 08:33:09

+0

你如何使用類裝飾器和元類來實現這一點?一個例子會很棒。 – 2017-12-17 10:56:04