Pythonic方式如何初始化属性或特性?
Python支持类属性、实例属性和属性。
from time import ctime, sleep
class MyClass(object):
A = ctime() # class attribute
def __init__(self):
self.B = ctime() # instance attribute
self._C = None
@property
def C(self): # property
if self._C is None:
self._C = ctime()
return self._C
@C.setter
def C(self, c):
self._C
对于一个不了解MyClass实现的人来说,A、B和C表现得很相似:
sleep(2)
myObject = MyClass()
sleep(2)
print myObject.A # prints time module was initialized
print myObject.B # prints time instance was created, 2 sec later
print myObject.C # prints time this line was called, 2 sec later
myObject.A = 'foo' # myObject.A is now an instance attribute
myObject.B = 'foo' # myObject.B is still an instance attribute
myObject.C = 'foo' # myObject.C is still an (instance) property
print myObject.A # prints 'foo'
print myObject.B # prints 'foo'
print myObject.C # prints 'foo'
根据我在这里得到的回答,我明白了以下几点:第一次打印myObject.A
时,myObject.A
等于myObject.__Class__.A
,也就是MyClass.A
。第二次打印myObject.A
时,它就不再是myObject.__Class__.A
了。明白了。
在上面的例子中,ctime()
只是用来说明A、B和C之间的区别。现在假设我们使用一个不可变的常量来代替:
class MyClass(object):
A = 'bar' # class attribute
def __init__(self):
self.B = 'meta' # instance attribute
self._C = None
@property
def C(self): # property
if self._C is None:
self._C = 'foobar'
return self._C
@C.setter
def C(self, c):
self._C = c
myObject = MyClass()
myObject.A
仍然是类属性MyClass.A
,而myObject.B
是实例属性,myObject.C
是一个属性。它们都完全符合我的需求。它们都有一个默认值,我也可以给它们赋其他值。那么我应该使用哪种风格,A、B还是C呢?
3 个回答
看起来有两种方式来创建简单的属性或特性。
其实这根本不是“方式”,只是做了一件事:赋值。
它们的效果是不同的。
在Python中,逻辑规则是这样的:在class
块中声明的东西属于这个类。因此,A
是这个类的一个属性(大致相当于在C++、Java或C#中声明的static
属性)。而B
是每个实例的一个属性,当实例运行__init__
时会自动生成。
至于你的更新,我不太明白你想问什么。试着用真实的名字,而不是'A',并解释一下你的使用场景(也就是你为什么想要做这个)。
这要看你希望什么时候进行初始化,以及你想要什么样的实例。
- 如果你希望这个属性只有一个实例(也就是一个值),并且这个值在所有类的实例之间共享,那就用类属性。
- 如果你希望每个类的实例都有一个不同的属性值,那就用实例属性。
顺便提一下,你的代码示例中使用的是属性,而不是特性。
我不太明白你对问题的更新。你可能需要退一步,解释一下你根本的问题是什么。
初始化一个常量类属性的最佳方式是在类定义的时候直接设置。
从问题中的代码来看,似乎对如何通过实例对象访问类属性有些困惑。
需要注意的是,在实例对象中,你可以通过名字来访问类属性,因为当在内部字典中找不到某个属性时,系统会继续在类的字典中查找。也就是说,如果instance.A
不存在,系统会返回instance.__class__.A
,前提是它存在。
不过,当在对象实例中创建了一个属性时,这个类属性就会被遮蔽。也就是说,instance.A = <value>
会创建一个新的实例属性,下次你访问instance.A
时,就会返回<value>
。不过,你仍然可以通过instance.__class__.A
来获取类属性。