Classes:-
Compared with other programming languages, Python’s class mechanism adds classes with a minimum of new syntax and semantics. It is a mixture of the class mechanisms found in C++ and Modula-3. Python classes provide all the standard features of Object Oriented Programming: the class inheritance mechanism allows multiple base classes, a derived class can override any methods of its base class or classes, and a method can call the method of a base class with the same name. Objects can contain arbitrary amounts and kinds of data. As is true for modules, classes partake of the dynamic nature of Python: they are created at runtime, and can be modified further after creation.Python Scopes and Namespaces:-
A namespace is a mapping from names to objects. Most namespaces are currently implemented as Python dictionaries, but that’s normally not noticeable in any way (except for performance), and it may change in the future. Examples of namespaces are: the set of built-in names (containing functions such asabs()
, and
built-in exception names); the global names in a module; and the local names in
a function invocation. In a sense the set of attributes of an object also form
a namespace. The important thing to know about namespaces is that there is
absolutely no relation between names in different namespaces; for instance, two
different modules may both define a function maximize
without confusion —
users of the modules must prefix it with the module name.A scope is a textual region of a Python program where a namespace is directly accessible. “Directly accessible” here means that an unqualified reference to a name attempts to find the name in the namespace.
Although scopes are determined statically, they are used dynamically. At any time during execution, there are at least three nested scopes whose namespaces are directly accessible:
- the innermost scope, which is searched first, contains the local names
- the scopes of any enclosing functions, which are searched starting with the nearest enclosing scope, contains non-local, but also non-global names
- the next-to-last scope contains the current module’s global names
- the outermost scope (searched last) is the namespace containing built-in names.
Class Definition Syntax:-
The simplest form of class definition looks like this:class ClassName:
<statement-1>
.
.
.
<statement-N>
def
statements) must be
executed before they have any effect. (You could conceivably place a class
definition in a branch of an if
statement, or inside a function.)In practice, the statements inside a class definition will usually be function definitions, but other statements are allowed, and sometimes useful — we’ll come back to this later. The function definitions inside a class normally have a peculiar form of argument list, dictated by the calling conventions for methods — again, this is explained later.
When a class definition is entered, a new namespace is created, and used as the local scope — thus, all assignments to local variables go into this new namespace. In particular, function definitions bind the name of the new function here.
When a class definition is left normally (via the end), a class object is created. This is basically a wrapper around the contents of the namespace created by the class definition; we’ll learn more about class objects in the next section. The original local scope (the one in effect just before the class definition was entered) is reinstated, and the class object is bound here to the class name given in the class definition header (
ClassName
in the
example).Class Objects
Class objects support two kinds of operations: attribute references and instantiation.Attribute references use the standard syntax used for all attribute references in Python:
obj.name
. Valid attribute names are all the names that were in
the class’s namespace when the class object was created. So, if the class
definition looked like this:class MyClass:
"""A simple example class"""
i = 12345
def f(self):
return 'hello world'
MyClass.i
and MyClass.f
are valid attribute references, returning
an integer and a function object, respectively. Class attributes can also be
assigned to, so you can change the value of MyClass.i
by assignment.
__doc__
is also a valid attribute, returning the docstring belonging to
the class: "A simple example class"
.Class instantiation uses function notation. Just pretend that the class object is a parameterless function that returns a new instance of the class. For example (assuming the above class):
x = MyClass()
x
.The instantiation operation (“calling” a class object) creates an empty object. Many classes like to create objects with instances customized to a specific initial state. Therefore a class may define a special method named
__init__()
, like this:def __init__(self):
self.data = []
__init__()
method, class instantiation
automatically invokes __init__()
for the newly-created class instance. So
in this example, a new, initialized instance can be obtained by:x = MyClass()
__init__()
method may have arguments for greater
flexibility. In that case, arguments given to the class instantiation operator
are passed on to __init__()
. For example,>>> class Complex:
... def __init__(self, realpart, imagpart):
... self.r = realpart
... self.i = imagpart
...
>>> x = Complex(3.0, -4.5)
>>> x.r, x.i
(3.0, -4.5)
Instance Objects
Now what can we do with instance objects? The only operations understood by instance objects are attribute references. There are two kinds of valid attribute names, data attributes and methods.data attributes correspond to “instance variables” in Smalltalk, and to “data members” in C++. Data attributes need not be declared; like local variables, they spring into existence when they are first assigned to. For example, if
x
is the instance of MyClass
created above, the following piece of
code will print the value 16
, without leaving a trace:x.counter = 1
while x.counter < 10:
x.counter = x.counter * 2
print x.counter
del x.counter
Valid method names of an instance object depend on its class. By definition,
all attributes of a class that are function objects define corresponding
methods of its instances. So in our example,
x.f
is a valid method
reference, since MyClass.f
is a function, but x.i
is not, since
MyClass.i
is not. But x.f
is not the same thing as MyClass.f
— it
is a method object, not a function object.Inheritance
Of course, a language feature would not be worthy of the name “class” without supporting inheritance. The syntax for a derived class definition looks like this:class DerivedClassName(BaseClassName):
<statement-1>
.
.
.
<statement-N>
BaseClassName
must be defined in a scope containing the
derived class definition. In place of a base class name, other arbitrary
expressions are also allowed. This can be useful, for example, when the base
class is defined in another module:class DerivedClassName(modname.BaseClassName):
There’s nothing special about instantiation of derived classes:
DerivedClassName()
creates a new instance of the class. Method references
are resolved as follows: the corresponding class attribute is searched,
descending down the chain of base classes if necessary, and the method reference
is valid if this yields a function object.Derived classes may override methods of their base classes. Because methods have no special privileges when calling other methods of the same object, a method of a base class that calls another method defined in the same base class may end up calling a method of a derived class that overrides it. (For C++ programmers: all methods in Python are effectively
virtual
.)An overriding method in a derived class may in fact want to extend rather than simply replace the base class method of the same name. There is a simple way to call the base class method directly: just call
BaseClassName.methodname(self,
arguments)
. This is occasionally useful to clients as well. (Note that this
only works if the base class is accessible as BaseClassName
in the global
scope.)Python has two built-in functions that work with inheritance:
- Use
isinstance()
to check an instance’s type:isinstance(obj, int)
will beTrue
only ifobj.__class__
isint
or some class derived fromint
. - Use
issubclass()
to check class inheritance:issubclass(bool, int)
isTrue
sincebool
is a subclass ofint
. However,issubclass(unicode, str)
isFalse
sinceunicode
is not a subclass ofstr
(they only share a common ancestor,basestring
).
9.5.1. Multiple Inheritance
Python supports a limited form of multiple inheritance as well. A class definition with multiple base classes looks like this:class DerivedClassName(Base1, Base2, Base3):
<statement-1>
.
.
.
<statement-N>
DerivedClassName
, it is searched in
Base1
, then (recursively) in the base classes of Base1
, and
only if it is not found there, it is searched in Base2
, and so on.(To some people breadth first — searching
Base2
and Base3
before the base classes of Base1
— looks more natural. However, this
would require you to know whether a particular attribute of Base1
is
actually defined in Base1
or in one of its base classes before you can
figure out the consequences of a name conflict with an attribute of
Base2
. The depth-first rule makes no differences between direct and
inherited attributes of Base1
.)For new-style classes, the method resolution order changes dynamically to support cooperative calls to
super()
. This approach is known in some
other multiple-inheritance languages as call-next-method and is more powerful
than the super call found in single-inheritance languages.With new-style classes, dynamic ordering is necessary because all cases of multiple inheritance exhibit one or more diamond relationships (where at least one of the parent classes can be accessed through multiple paths from the bottommost class). For example, all new-style classes inherit from
object
, so any case of multiple inheritance provides more than one path
to reach object
. To keep the base classes from being accessed more
than once, the dynamic algorithm linearizes the search order in a way that
preserves the left-to-right ordering specified in each class, that calls each
parent only once, and that is monotonic (meaning that a class can be subclassed
without affecting the precedence order of its parents). Taken together, these
properties make it possible to design reliable and extensible classes with
multiple inheritance. For more detail, see
https://www.python.org/download/releases/2.3/mro/.9.6. Private Variables and Class-local References
“Private” instance variables that cannot be accessed except from inside an object don’t exist in Python. However, there is a convention that is followed by most Python code: a name prefixed with an underscore (e.g._spam
) should
be treated as a non-public part of the API (whether it is a function, a method
or a data member). It should be considered an implementation detail and subject
to change without notice.Since there is a valid use-case for class-private members (namely to avoid name clashes of names with names defined by subclasses), there is limited support for such a mechanism, called name mangling. Any identifier of the form
__spam
(at least two leading underscores, at most one trailing underscore)
is textually replaced with _classname__spam
, where classname
is the
current class name with leading underscore(s) stripped. This mangling is done
without regard to the syntactic position of the identifier, as long as it
occurs within the definition of a class.Name mangling is helpful for letting subclasses override methods without breaking intraclass method calls. For example:
class Mapping:
def __init__(self, iterable):
self.items_list = []
self.__update(iterable)
def update(self, iterable):
for item in iterable:
self.items_list.append(item)
__update = update # private copy of original update() method
class MappingSubclass(Mapping):
def update(self, keys, values):
# provides new signature for update()
# but does not break __init__()
for item in zip(keys, values):
self.items_list.append(item)
Notice that code passed to
exec
, eval()
or execfile()
does not
consider the classname of the invoking class to be the current class; this is
similar to the effect of the global
statement, the effect of which is
likewise restricted to code that is byte-compiled together. The same
restriction applies to getattr()
, setattr()
and delattr()
, as well
as when referencing __dict__
directly.
No comments:
Post a Comment