I am new to Python having come from mainly Java programming.
I am currently pondering over how classes in Python are instantiated.
I understand that __ini
This answer pertains to new-style Python classes, which subclass object
. New-style classes were added in 2.2, and they're the only kind of class available in PY3.
>>> print object.__doc__
The most base type
The class itself is an instance of a metaclass, which is usually type
:
>>> print type.__doc__
type(object) -> the object's type
type(name, bases, dict) -> a new type
Per the above docstring, you can instantiate the metaclass directly to create a class:
>>> Test = type('Test', (object,), {'__doc__': 'Test class'})
>>> isinstance(Test, type)
True
>>> issubclass(Test, object)
True
>>> print Test.__doc__
Test class
Calling a class is handled by the metaclass __call__
method, e.g. type.__call__
. This in turn calls the class __new__
constructor (typically inherited) with the call arguments in order to create an instance. Then it calls __init__
, which may set instance attributes.
Most objects have a __dict__
that allows setting and deleting attributes dynamically, such as self.value = 10
or del self.value
. It's generally bad form to modify an object's __dict__
directly, and actually disallowed for a class (i.e. a class dict is wrapped to disable direct modification). If you need to access an attribute dynamically, use the built-in functions getattr
, setattr
, and delattr
.
The data model defines the following special methods for customizing attribute access: __getattribute__
, __getattr__
, __setattr__
, and __delattr__
. A class can also define the descriptor protocol methods __get__
, __set__
, and __delete__
to determine how its instances behave as attributes. Refer to the descriptor guide.
When looking up an attribute, object.__getattribute__
first searches the object's class and base classes using the C3 method resolution order of the class:
>>> Test.__mro__
(, )
Note that a data descriptor defined in the class (e.g. a property
or a member
for a slot) takes precedence over the instance dict. On the other hand, a non-data descriptor (e.g. a function) or a non-descriptor class attribute can be shadowed by an instance attribute. For example:
>>> Test.x = property(lambda self: 10)
>>> inspect.isdatadescriptor(Test.x)
True
>>> t = Test()
>>> t.x
10
>>> t.__dict__['x'] = 0
>>> t.__dict__
{'x': 0}
>>> t.x
10
>>> Test.y = 'class string'
>>> inspect.isdatadescriptor(Test.y)
False
>>> t.y = 'instance string'
>>> t.y
'instance string'
Use super to proxy attribute access for the next class in the method resolution order. For example:
>>> class Test2(Test):
... x = property(lambda self: 20)
...
>>> t2 = Test2()
>>> t2.x
20
>>> super(Test2, t2).x
10