PART I
in new-style class, implicit attribute fetch starts at class instead of instance.
X[I]
is equivalent to X.__getitem__(I)
in old-style class.
X[I]
is equivalent to type(X).__getitem__(X, I)
in new-style class.
Rationale for this:
metaclasses are the type for classes and classes are instances of metaclasses.
metaclass A
class B is an instance of A, if B wants to call a method, this skip of instance attribute will directly call the method from metaclass B. Because the methods defined in B aim for the use from its own instance. So the introduction of metaclass needs this change.
this impacts proxy class
, which embeds other objects which implement operator overloading.
>>> class A:
... data = 'spam'
... def __getattr__(self, name):
... print(name)
... return getattr(self.data, name)
...
>>> x = A()
>>> x[0]
__getitem__
's'
>>> print(x)
__str__
spam
>>> class B(object):
... data = 'spam'
... def __getattr__(self, name):
... print(name)
... return getattr(self.data, name)
...
>>> y = B()
>>> y[0]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'B' object does not support indexing
>>> print(y)
<__main__.B object at 0x7f061c41b950>
>>> y.__getitem__(0)
__getitem__
's'
__getattr__(self, item)
is used when fetching attribute item
while the instance does’t have this one, this method will be called. So for class level attribute fetch, this method will never be called.
thus y[0]
: the implicit call to __getitem__
will skip the instance level and start to find __getitem__
in class B
.
Notice that the explicit class succeeded.
In other words, only built-in operation in new style class starts at class level while explicit fetches run correctly.
for delegation class, needs to redefine all names accessed by built-in operations.
>>> class C(object):
... data = 'spam'
... def __getattr__(self, name):
... print('getattr: ' + name)
... return getattr(self.data, name)
... def __getitem__(self, i):
... print('getitem: ' + str(i))
... return self.data[i]
... def __add__(self, other):
... print('add: ' + other)
... return self.data + other
... def __str__(self):
... return self.data
PART II
classes
and types
please refer to http://www.cs.utexas.edu/~cannata/cs345/Class%20Notes/15%20Python%20Types%20and%20Objects.pdf
the type of an instance is its class, and the type of a user-defined class is the same as the type of a built-in object type.
classes are types
types are classes
how to determine if two objects are of the same type in both python2.x and python 3.x?
# python2
>>> class A(): pass
...
>>> class B(): pass
...
>>> a = A()
>>> b = B()
>>> type(a)
<type 'instance'>
>>> type(b)
<type 'instance'>
>>> type(a) == type(b)
True
>>> a.__class__ == b.__class__
False
# python3
>>> class A(): pass