__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__ не можем да постигнем нищо
Помните ли как ви повторихме няколко пъти, че __init__
не е точно конструктора на всеки клас?
__new__
е истинският конструктор__init__
class LessFaultyPair(tuple):
def __new__(klass, x, y):
return (x, y)
type(LessFaultyPair(1, 2)) # tuple
Но ние не искахме точно това...
__new__
се имплементира от object
и се наследява от другите типове__new__
на базовия типclass Pair(tuple):
def __new__(klass, x, y):
return tuple.__new__(klass, (x, y))
type(Pair(1, 2)) # Pair
type
Помните ли как ви казахме, че type
може само да връща типа на обект?
В Python type
значи няколко неща
type(x)
връща типа на xtype
type
Класовете са просто инстанции на type
.
type(name, bases, dict)
name
- име на новия класbases
- tuple с базовите му класовеdict
- речник с полетата му (не по-различно от __dict__
)Foo = type('Foo', (A, B, C), {'x':1, 'y':2})
Долното е синтактична захар за горното...
class Foo(A, B, C):
x = 1
y = 2
type
е тип и си има конструкторtype
може да бъде наследен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
Metaprogramming is the language feature that helps you write code that you won't be able to understand once the cocaine wears off.
— Bryan O'Sullivan (@bos31337) May 4, 2010