2017-08-04 184 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'