__dict__
__getattribute__
__getattr__
__setattr__
__delattr__
dir
getattr
setattr
hasattr
delattr
def __get__(self, instance, owner): ...
def __set__(self, instance, value): ...
def __delete__(self, instance): ...
class B:
def __get__(self, instance, owner):
return "You came to the wrong neighborhood, motherflower!"
def __set__(self, instance, value):
print("What!? You think you can change my personality just like that!?")
def __delete__(self, instance):
print("Can't touch me!")
class A:
foo = B()
a = A()
print(a.foo)
a.foo = 'bar'
del a.foo
>>> increment = (1).__add__
>>> map(increment, [0, 1, 2, 3])
[1, 2, 3, 4]
class MyMethod:
def __init__(self, func):
self.func = func
def __get__(self, instance, owner):
if instance:
return lambda: self.func(instance)
else:
return lambda explicit_instance: self.func(explicit_instance)
class Python:
name = 'Monty'
greet = MyMethod(lambda self: 'My name issss %s' % self.name)
snake = Python()
snake.greet() # 'My name issss Monty'
snake.name = 'Nagini'
Python.greet() # TypeError: <lambda>() takes exactly 1 argument (0 given)
Python.greet(snake) # 'My name issss Nagini'
Редът за обхождане на базови класове
class A(int): pass
class B: pass
class C(A, B, int): pass
C.__mro__
# <class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>,
# <class 'int'>, <class 'object'>
за пълната информация...
Как бихме могли да имплементираме клас Pair, наследник на tuple?
class FaultyPair(tuple):
def __init__(self, a, b):
self[0] = a
self[1] = b
class FaultierPair(tuple):
def __init__(self, a, b):
self = (a, b)
Помните ли как ви казахме, че __init__ е конструктора на всеки клас?
class KindaFaultyPair(tuple):
def __new__(klass, x, y):
return (x, y)
type(KindaFaultyPair(1, 2)) # tuple
Но ние не искахме точно това...
class Pair(tuple):
def __new__(klass, x, y):
return tuple.__new__(klass, (x, y))
type(Pair(1, 2)) # Pair
Помните ли как ви казахме, че type може само да връща типа на обект?
В Пайтън type значи няколко неща
Класовете са просто инстанции на type.
type(name, bases, dict)
Foo = type('Foo', (A, B, C), {'x':1, 'y':2})
Долното е синтактична захар за горното...
class Foo(A, B, C):
x = 1
y = 2
class metacls(type):
def __new__(mcs, name, bases, dict):
dict['foo'] = 'metacls was here'
return type.__new__(mcs, name, bases, dict)
Foo = metacls('Foo', (A, B, C), {'x':1, 'y':2})
type(Foo) # metacls
class Foo(A, B, C, metaclass=metacls):
x = 1
y = 2
class R(metaclass=ReverseNames):
def forward(self):
print('forward')
>>> r = R()
>>> r.forward()
AttributeError: 'R' object has no attribute 'forward'
>>> r.drawrof()
forward
class ReverseNames(type):
def __new__(klass, name, bases, _dict):
reversed = [(k[::-1], v) for k, v in _dict.items()]
return type.__new__(klass, name, bases, dict(reversed))
[Metaclasses] are deeper magic than 99% of the users should ever worry about. If you wonder whether you need them, you don't (the people who actually need them know with certainty that they need them, and don't need an explanation about why).
— Tim Peters
Не съм сигурен, че искаме да ви говорим за това