Online Book Reader

Home Category

Learning Python - Mark Lutz [430]

By Root 1861 0

If a subclass inherits from a superclass without a __slots__, the __dict__ attribute of the superclass will always be accessible, making a __slots__ in the subclass meaningless.

If a class defines the same slot name as a superclass, the version of the name defined by the superclass slot will be accessible only by fetching its descriptor directly from the superclass.

Because the meaning of a __slots__ declaration is limited to the class in which it appears, subclasses will have a __dict__ unless they also define a __slots__.

In terms of listing instance attributes generically, slots in multiple classes might require manual class tree climbs, dir usage, or a policy that treats slot names as a different category of names altogether:

>>> class E:

... __slots__ = ['c', 'd'] # Superclass has slots

...

>>> class D(E):

... __slots__ = ['a', '__dict__'] # So does its subclass

...

>>> X = D()

>>> X.a = 1; X.b = 2; X.c = 3 # The instance is the union

>>> X.a, X.c

(1, 3)

>>> E.__slots__ # But slots are not concatenated

['c', 'd']

>>> D.__slots__

['a', '__dict__']

>>> X.__slots__ # Instance inherits *lowest* __slots__

['a', '__dict__']

>>> X.__dict__ # And has its own an attr dict

{'b': 2}

>>> for attr in list(getattr(X, '__dict__', [])) + getattr(X, '__slots__', []):

... print(attr, '=>', getattr(X, attr))

...

b => 2 # Superclass slots missed!

a => 1

__dict__ => {'b': 2}

>>> dir(X) # dir() includes all slot names

[...many names omitted... 'a', 'b', 'c', 'd']

When such generality is possible, slots are probably best treated as class attributes, rather than trying to mold them to appear the same as normal instance attributes. For more on slots in general, see the Python standard manual set. Also watch for an example that allows for attributes based on both __slots__ and __dict__ storage in the Private decorator discussion of Chapter 38.

For a prime example of why generic programs may need to care about slots, see the lister.py display mix-in classes example in the multiple inheritance section of the prior chapter; a note there describes the example’s slot concerns. In such a tool that attempts to list attributes generically, slot usage requires either extra code or the implementation of policies regarding the handling of slot-based attributes in general.

Class Properties

A mechanism known as properties provides another way for new-style classes to define automatically called methods for access or assignment to instance attributes. At least for specific attributes, this feature is an alternative to many current uses of the __getattr__ and __setattr__ overloading methods we studied in Chapter 29. Properties have a similar effect to these two methods, but they incur an extra method call for any accesses to names that require dynamic computation. Properties (and slots) are based on a new notion of attribute descriptors, which is too advanced for us to cover here.

In short, a property is a type of object assigned to a class attribute name. A property is generated by calling the property built-in with three methods (handlers for get, set, and delete operations), as well as a docstring; if any argument is passed as None or omitted, that operation is not supported. Properties are typically assigned at the top level of a class statement [e.g., name = property(...)]. When thus assigned, accesses to the class attribute itself (e.g., obj.name) are automatically routed to one of the accessor methods passed into the property. For example, the __getattr__ method allows classes to intercept undefined attribute references:

>>> class classic:

... def __getattr__(self, name):

... if name == 'age':

... return 40

... else:

... raise AttributeError

...

>>> x = classic()

>>> x.age # Runs __getattr__

40

>>> x.name # Runs __getattr__

AttributeError

Here is the same example, coded with properties instead (note that properties are available for all classes but require the new-style object derivation in 2.6 to work properly for intercepting attribute assignments):

>>> class newprops(object):

Return Main Page Previous Page Next Page

®Online Book Reader