2010-04-24 103 views
8

這裏是什麼,我試圖繞過一個很簡單的例子:類__init__(不是實例__init__)

class Test(object): 
    some_dict = {Test: True} 

的問題是,它仍然被定義,而我不能參考試驗

通常,我只是這樣做:

class Test(object): 
    some_dict = {} 
    def __init__(self): 
     if self.__class__.some_dict == {}: 
      self.__class__.some_dict = {Test: True} 

但我從來沒有創建這個類的實例。這真的只是一個容器,以便容納一組相關的功能和數據(我有幾個這些類的,我繞過它們的引用,所以它必要的測試是它自己的類)

所以我問題是,如何在定義時引用Test,或者在類定義後立即調用__init__?如果可能,我希望self.some_dict = {Test: True}保留在類定義中。這是我知道如何做到這一點,到目前爲止的唯一途徑:

class Test(object): 
    @classmethod 
    def class_init(cls): 
     cls.some_dict = {Test: True} 
Test.class_init() 
+0

「問題在於,當它仍在被定義時,我無法引用測試」。所以?在定義期間,你需要什麼樣的參考**?標準答案是None:類定義是穩定的,一致的和不變的。 **行爲**可以改變。定義不應該改變。你想用這個「變化的定義」業務做什麼? – 2010-04-24 22:37:53

+0

定義不變。我只需要對類的引用,並且爲了組織的目的,我更喜歡在定義類時設置該引用。 – Ponkadoodle 2010-04-24 22:44:17

+0

我明白你想要做什麼,但我不明白你爲什麼試圖這樣做,以及你想要完成什麼。你能詳細說一下嗎?看起來更像是一個架構,然後是「我怎麼把蟒蛇變成......?」問題給我。 – Aea 2010-04-24 22:51:47

回答

12

該類實際上在定義時並不存在。 class語句的工作方式是語句的主體作爲一個代碼塊在單獨的名稱空間中執行。在執行結束時,該名稱空間被傳遞給元類(例如type),並且元類使用名稱空間作爲屬性空間創建類。

從您的描述中可以看出,不是 Test是一個班級所必需的聲音。這聽起來應該是模塊some_dict是一個全球性的 - 即使它是一個類屬性,你的程序中只有一個這樣的屬性,所以它不比擁有全局性更好 - 而且你在課堂上的任何classmethods都可以是函數。

如果你真的希望它是一類,你有三種選擇:設置字典定義的類後:

class Test: 
    some_dict = {} 
Test.some_dict[Test] = True 

使用類裝飾(在Python 2.6或更高版本):

def set_some_dict(cls): 
    cls.some_dict[cls] = True 

@set_some_dict 
class Test: 
    some_dict = {} 

或者使用元類:

class SomeDictSetterType(type): 
    def __init__(self, name, bases, attrs): 
     self.some_dict[self] = True 
     super(SomeDictSetterType, self).__init__(name, bases, attrs) 

class Test(object): 
    __metaclass__ = SomeDictSetterType 
    some_dict = {} 
+0

+1得到詳細答案 – 2010-04-24 22:49:17

+0

它*可能*是一個模塊,但我更喜歡它是一個類。如果它在一個單獨的模塊中,我不得不做一些重新安排來防止循環導入。另外,如果所有這些類都在不同的文件中,編輯我的項目時需要打開20個選項卡。無論如何,謝謝你告訴我關於Metaclasses。 – Ponkadoodle 2010-04-24 22:53:44

+0

裝飾者是一種很酷的方法 – 2010-04-25 00:34:45

4

你可以在主類定義後添加some_dict屬性。

class Test(object): 
    pass 
Test.some_dict = {Test: True} 
+0

這是要做到這一點的方法。 – PaulMcG 2010-04-24 22:42:04

+0

同意 - 這是正確的答案。 – 2010-04-25 00:33:45

0

您還可以使用元類(此功能,但也有其他的方法) :

def Meta(name, bases, ns): 
    klass = type(name, bases, ns) 
    setattr(klass, 'some_dict', { klass: True }) 
    return klass 

class Test(object): 
    __metaclass__ = Meta 

print Test.some_dict 
0

托馬斯的第一個例子是非常好的,但是這裏有更多的Pythonic做同樣的事情。

class Test: 
    x = {} 
    @classmethod 
    def init(cls): 
     # do whatever setup you need here 
     cls.x[cls] = True 
Test.init() 
1

我試圖以這種方式在過去使用類,它很快變得醜陋(例如,所有的方法都必須是類方法或靜態方法,你可能會發現最終你想要定義某些特殊的方法,你將不得不開始使用元類)。如果您只是使用類實例,它可以使事情變得簡單 - 沒有任何缺點。

A(看起來怪怪的)替代別人的建議:你可以使用__new__

class Test(object): 
    def __new__(cls): 
     cls.some_dict = {cls: True} 

Test() 

你甚至可以有__new__參考返回類,並使用一個裝飾來稱呼它:

def instantiate(cls): 
    return cls() 

@instantiate 
class Test(object): 
    def __new__(cls): 
     cls.some_dict = {cls: True} 
     return cls