# Dive Into Python

Python for experienced programmers

Find:

## 3.8. Class attributes

You already know about data attributes, which are variables owned by a specific instance of a class. Python also supports class attributes, which are variables owned by the class itself.

### Example 3.18. Introducing class attributes

    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
    <class fileinfo.MP3FileInfo at 01257FDC>
    >>> fileinfo.MP3FileInfo.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>)}
    >>> m = fileinfo.MP3FileInfo()
    >>> 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>)}

| `MP3FileInfo` is the class itself, not any particular instance of the class.
| `tagDataMap` is a class attribute: literally, an attribute of the class. It is available before creating any instances of the class.
| Class attributes are available both through direct reference to the class and through any instance of the class.

In Java, both static variables (called class attributes in Python) and instance variables (called data attributes in Python) are defined immediately after the class definition (one with the `static` keyword, one without). In Python, only class attributes can be defined here; data attributes are defined in the `__init__` method.

Class attributes can be used as class-level constants (which is how we use them in `MP3FileInfo`), but they are not really constants.[4] You can also change them.

### Example 3.19. Modifying class attributes

    >>> class counter:
    ...     count = 0
    ...     def __init__(self):
    ...         self.__class__.count += 1
    ...
    >>> counter
    <class __main__.counter at 010EAECC>
    >>> counter.count
    0
    >>> c = counter()
    >>> c.count
    1
    >>> counter.count
    1
    >>> d = counter()
    >>> d.count
    2
    >>> c.count
    2
    >>> counter.count
    2

| `count` is a class attribute of the `counter` class.
| `__class__` is a built-in attribute of every class instance (of every class). It is a reference to the class that `self` is an instance of (in this case, the `counter` class).
| Because `count` is a class attribute, it is available through direct reference to the class, before we have created any instances of the class.
| Creating an instance of the class calls the `__init__` method, which increments the class attribute `count` by `1`. This affects the class itself, not just the newly created instance.
| Creating a second instance will increment the class attribute `count` again. Notice how the class attribute is shared by the class and all instances of the class.

### Footnotes

[4] There are no constants in Python. Everything can be changed if you try hard enough. This fits with one of the core principles of Python: bad behavior should be discouraged but not banned. If you really want to change the value of `None`, you can do it, but don’t come running to me when your code is impossible to debug.