По большому счету в питоне все объекты хранятся в словарях(dict).Словарь — есть список объектов, которому противопоставлен ключ, уникальный на весь словарь.
class A(): i=1; s='string'
print dir(A)
> ['__doc__', '__module__', 'i', 's']
Это свойство, позволяет «вытворять» с классами и экземплярами классов разнообразные вещи. Например:
class A(): v0=1
class B(A):
v1=2
def __init__(self):
self.v2 = 3
b=B()
print b.v2, b.v1, b.v0
> 3 2 1
Когда Python пытался достать v2 все ясно — оно получено из словаря экземпляра b. Далее интересней, свойство v1, уже не содержит элемент b, его содержит словарь B — питон взял его оттуда. И, наконец, при поиске элемента v0 обращаемся к словарю родителю B-A, и достаем его оттуда. Понятно что если определить в пределах b свойство v0, то его значение будет получено оттуда, не поднимаясь на более высокие уровни.
def __init__(self):
print self
class A(): pass
setattr(A, '__init__', __init__)
a=A()
> <__main__.A instance at 0x009E9EB8>
В этом примере, мы переместили функцию __init__ в пределы класса A(мы могли переместить функцию с любым другим именем, __init__ приведена для наглядности). Декларация класса A эквивалентна:
class A():
def __init__(self):
print self
Классы в питоне есть экземпляры метаклассов. Это, есть неожиданность, потому как теперь вам позволено «на лету» определять классы, а не только их экземляры.
def __init__(self):
print self
B = type('B', (), {})
setattr(B, '__init__', __init__)
b = B()
> <__main__.B object at 0x009E7CD0>
Заметьте, что функция определена лишь для экземпляров класса, вызвать её для самого класса A нельзя. С другой стороны, что нам мешает эту возможность добавить.
def Omd(obj):
print obj
B = type('B', (), {})
setattr(B, 'c', classmethod(Omd))
setattr(B, 'o', Omd)
b = B()
b.c(), b.o()
> <class '__main__.B'>
> <__main__.B object at 0x009E7D50>
Весело правда?! Определили фукнцию, которая печатает первый свой аргумент. Далее создали класс, на основе метакласса (можно было его определить и стандартно, как
class A(type): pass). Дальше классу, добавили статическую функцию «с», под которой скрывается наша, и функцию «о» для вызова её от экземпляра класса B. Смотрим, что получается, первым мы видим что печатается класс, а после него экземпляр. Вот такая вот у них любовь.
