Chapter 24. Creating or Extending Data Types
When we use an operator, like + or *, what happens depends on the
types of the objects involved. When we say c*2
, the value
depends on the type of c
. If c
is
numeric, then 2 may have to be converted to the same type as
c
, and the answer will be a number. If, however,
c
is a sequence, the result is a new sequence.
>>>
c=8.0
>>>
c*2
16.0
>>>
c="8.0"
>>>
c*2
'8.08.0'
>>>
c=(8,0)
>>>
c*2
(8, 0, 8, 0)
The selection of appropriate behavior is accomplished by the
relatively simple mechanism of “special method names” within
Python. Each class of objects, either built-in or created by a programmer,
can provide the required special method names to create the intimate
relationship between the class, the built-in functions and the
mathematical operators.
If you provide special methods, you can make your class behave like
a built-in class. Your class can participate seamlessly with built-in
Python functions like str
, len
,
repr
. Your class can also participate with the usual
mathematical operators like +
and *
.
Additionally, your class could also use the collection operators in a
manner similar to a map
or
list
.
The special method names are similar in principle to operator
overloading provided in C++. Similar considerations apply: you should make
the operator behave in way that parallels the mathematical sense of the
symbol.
Additionally, we can extend built-in classes. We do this by
extending some of the special methods to do additional or different
things.
Semantics of Special Methods
Python has a number of language features that interact with the
built-in data types. For example, objects of all built-in types can be
converted to strings. You can use the built-in str
function to perform these conversions. The str
function invokes the __str__
special method of
the given object. In effect, str(a)
is evaluated as
a.__str__()
.
When you create your own class, however, a built-in function like
str
or cmp
can't easily
determine how to perform these functions on your new class. Your class
must supply the specially-named method function that the built-in
str
function can use to successfully convert your
classes values to strings.
In the section called “Special Method Names” we introduced a few
special method names. We looked at __init__
,
which is evaluated implicitly when an object is created. We looked at
__str__
, which is used by the
str
function and __cmp__
,
which is evaluated by the cmp
function.
A huge number of Python features work through these special method
names. When you provide appropriate special methods for your class, it
behaves more like a built-in class.
You may be suspicious that the special method name
__str__
matches the built-in function
str
. There is no simple, obvious rule. Many of the
built-in functions invoke specially-named methods of the class that are
similar. The operators and other special symbols, however, can't have a
simple rule for pairing operators with special methods. You'll have to
actually read the documentation for built-in functions
(Library Reference, section 2.1) and special
method names (Language Reference, section 3.3) to
understand all of the relationships.
Categories of Special Method Names. The special methods fall into several broad categories. The
categories are defined by the kind of behavior your class should
exhibit.
-
Basic Object Behaviors
-
A number of special method names make your object behave
like oher built-in objects. These special methods make your class
respond to str
, repr
,
cmp
and comparison operators. This also
includes methods that allow your object to respond to the
hash
function, which allows instances of your
class to be a key to a mapping.
-
Numeric Behaviors
-
These special methods allow your class to respond to the
artithmetic operators: +, -, *, /, %, **, <<, >>,
and
,
or
and
not
. When you implement these special methods,
your class will behave like the built-in numeric types.
-
Container Behaviors
-
If your new class is a container or collection, there are a
number of methods required so that your class can behave like the
built-in collection types (sequence, set, mapping).
-
Iterator Behavior
-
An iterator has a unique protcol. The
for
statement requires an __iter__
method to
locate an iterator for an object. It then requires a
next
method on the iterator.
-
Attribute Handling Behavior
-
Some special methods customize how your class responds to
the .
operator for manpulating attributes. For
example, when you evaluate object.attr
. This is
commonly used when attribute manipulation is more complex than
simply locating an attribute that was defined by
__init__
.
-
Function Behavior
-
You can make your object behave like a function. When you
define the method __call__
, your object
is callable, and can be used as if it was a
function.
-
Statement Interaction
-
There are a few special methods required by statements. The
for
statement requires an
__iter__
method to locate an iterator for
an object. It then requires a next
method
on the iterator. The
with
statement requires
__enter__
and
__exit__
methods.