2017-08-04 186 views
-1

Python是否具有類構造函數的機制,即每當首次引用類時(而不是在創建該對象的實例時)調用的函數?我知道這存在於其他一些語言中,但我還沒有在Python中遇到過。Python類構造函數(靜態)

基本上,我想初始化該函數中的一些靜態屬性。我在下面展示了我期望的一個例子。當然,該示例返回None,但我希望它返回'foo'。

class T: 
    arg = None 
    def __class_constructor__(): 
     T.arg = 'foo' 

print(T.arg) # returns None 

爲了避免混淆:我深知對象構造的,但是這不是我想要的,因爲一旦被創建的第一個對象時,它纔會被調用,而不是之前:

class T: 
    arg = None 
    def __init__(self): 
     type(self).arg = 'foo' 

print(T.arg) # returns None 
obj = T() 
print(T.arg) # returns 'foo' 
+4

爲什麼不'T類中聲明,當它初始化類變量:ARG =「foo'' ...? 'class'關鍵字*是「類構造函數」。 – deceze

+0

我想分配的實際值比'foo'稍微複雜一些,所以不幸的是它不能像這樣分配 –

+2

除非值在您定義類的時候依賴於不可用的信息,否則沒有你不能這樣做的原因。請詳述一些細節? – deceze

回答

2

你可以使用類裝飾:

def add_arg(cls): 
    if not hasattr(cls, "arg"): 
     cls.arg = 'foo' 
    return cls 

@add_arg 
class T(object): 
    pass 

或自定義的元類:

class WithArg(type): 
    def __new__(meta, name, bases, attrs): 
     cls = type.__new__(meta, name, bases, attrs) 
     if not hasattr(cls, "arg"): 
      cls.arg = "foo" 
     return cls 

# python 2 
class T(object): 
    __metaclass__ = WithArg 

# python 3 
class T(metaclass=WithArg): 
    pass 

但正如其他人已經提到的,這不會給你更多的東西在類聲明中明確地設置類屬性。

注意:如果你想在類本身就是一個計算屬性,你必須將它設置爲一個自定義元類的屬性

class WithProp(type): 
    @property 
    def arg(cls): 
     return "foo" 

class T(object): 
    __metaclass__ = WithProp 

T.arg 
=> 'foo' 

arg將只提供類對象本身,而不是它的實例:

T().arg 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: 'T' object has no attribute 'arg' 

或寫自己的自定義描述:

class ArgDescriptor(object): 
    def __get__(self, obj, cls=None): 
     return 42 

class T(object): 
    arg = ArgDescriptor() 

T.arg 
=> 42 
T().arg 
=> 42 
+0

這些都沒有激活「當班級第一次引用」... – deceze

+0

是的,我剛剛編輯了我的答案。問題在於「什麼時候第一次參考」並不意味着太多。 –

+0

我忘了提及一個重要的細節......屬性應該是類本身的一個實例。但現在我已經整理出來了......我只是首先定義類,然後設置屬性(因爲否則,類不知道自己) –

1

您只需類

class T: 
    arg = 'foo' #this initialises the class instance 

    def __init__(self): 
     self.arg = 'bar' #this initialises the object instance 

print(T.arg) # class instance returns 'foo' 
obj = T() 
print(T.arg) # class instance still returns 'foo' 
print(obj.arg) # object instance returns 'bar'