5.8. 介绍类属性

您已经了解了数据属性,它是属于某个类的特定实例的变量。 Python 还支持类属性,它是属于类本身的变量。

示例 5.17. 介绍类属性


class MP3FileInfo(FileInfo):
    "store ID3v1.0 MP3 tags"
    tagDataMap = {"title"   : (  3,  33, stripnulls),
                  "artist"  : ( 33,  63, stripnulls),
                  "album"   : ( 63,  93, stripnulls),
                  "year"    : ( 93,  97, stripnulls),
                  "comment" : ( 97, 126, stripnulls),
                  "genre"   : (127, 128, ord)}
>>> import fileinfo
>>> fileinfo.MP3FileInfo            1
<class fileinfo.MP3FileInfo at 01257FDC>
>>> fileinfo.MP3FileInfo.tagDataMap 2
{'title': (3, 33, <function stripnulls at 0260C8D4>), 
'genre': (127, 128, <built-in function ord>), 
'artist': (33, 63, <function stripnulls at 0260C8D4>), 
'year': (93, 97, <function stripnulls at 0260C8D4>), 
'comment': (97, 126, <function stripnulls at 0260C8D4>), 
'album': (63, 93, <function stripnulls at 0260C8D4>)}
>>> m = fileinfo.MP3FileInfo()      3
>>> m.tagDataMap
{'title': (3, 33, <function stripnulls at 0260C8D4>), 
'genre': (127, 128, <built-in function ord>), 
'artist': (33, 63, <function stripnulls at 0260C8D4>), 
'year': (93, 97, <function stripnulls at 0260C8D4>), 
'comment': (97, 126, <function stripnulls at 0260C8D4>), 
'album': (63, 93, <function stripnulls at 0260C8D4>)}
1 MP3FileInfo 是类本身,而不是该类的任何特定实例。
2 tagDataMap 是一个类属性:字面上是类的属性。它在创建类的任何实例之前就可用。
3 类属性可以通过直接引用类和通过类的任何实例来访问。
Note
Java 中,静态变量(在 Python 中称为类属性)和实例变量(在 Python 中称为数据属性)都在类定义之后立即定义(一个使用 static 关键字,一个不使用)。在 Python 中,只有类属性可以在这里定义;数据属性在 __init__ 方法中定义。

类属性可以用作类级别的常量(这就是您在 MP3FileInfo 中使用它们的方式),但它们并不是真正的常量。您也可以更改它们。

Note
Python 中没有常量。如果您足够努力,一切都可以改变。这符合 Python 的一个核心原则:应该阻止不良行为,但不应该禁止。如果您真的想更改 None 的值,您可以这样做,但是当您的代码无法调试时,不要来找我。

示例 5.18. 修改类属性

>>> class counter:
...     count = 0                     1
...     def __init__(self):
...         self.__class__.count += 1 2
...     
>>> counter
<class __main__.counter at 010EAECC>
>>> counter.count                     3
0
>>> c = counter()
>>> c.count                           4
1
>>> counter.count
1
>>> d = counter()                     5
>>> d.count
2
>>> c.count
2
>>> counter.count
2
1 countcounter 类的类属性。
2 __class__ 是每个类实例(每个类)的内置属性。它是对 self 所属类的引用(在本例中为 counter 类)。
3 因为 count 是一个类属性,所以它可以通过直接引用类来访问,在您创建类的任何实例之前。
4 创建类的实例会调用 __init__ 方法,该方法将类属性 count 增加 1。这会影响类本身,而不仅仅是新创建的实例。
5 创建第二个实例将再次增加类属性 count。请注意类属性是如何由类和类的所有实例共享的。