05. Метапрограмиране
13 март 2013
Метапрограмиране
Metaprogramming is the writing of computer programs that write or manipulate other programs (or themselves) as their data, or that do part of the work at compile time that would otherwise be done at runtime.
Метапрограмиране
- Зората на времето - asm
- Малко след зората на времето - Lisp
- C - макроси (далеч не толкова мощни)
- C++ - templates
- Python?
Мета-обектен протокол
В Python ще го срещнете като data model
Какво знаем до тук?
- Всичко е обект.
- Всеки обект си има уникален номер, който можем да видим с id()
- Сравнението дали две имена сочат към един и същи обкет става с оператора is
- Всеки обект си има тип, който можем да проверим с type()
- Типовете са в йерархия
- Някои обекти могат да бъдат променяни, а други - не.
- Някои обекти могат да бъдат извикване, а други - не.
Време е да обясним как точно работят всички тези неща.
Дъндъри
Както знаете, всеки обект има такива неща, които са със специално значение за него.
__class__
- Всяко нещо в езика е обект
- Всеки обект си има тип/клас
- Тази информация се пази в `__class__`
- Класът на този клас също си има __class__ (тъй като също е обект)
- Стойността на __class__ може да се променя
Разни
- __bases__
- __slots__
- __doc__
__dict__
- Всеки обект в езика се държи като речник/hash/dict.
- Когато сетваме/достъпваме даден атрибут, Python рови в речника на този обект.
- Този речник е достъпен чрез
__dict__
атрибута.
- Вградените типове (тези, за които има литерали) нямат такъв.
def spam(): pass
spam.foo = 8
print(spam.__dict__)
spam.__dict__['bar'] = 2
print(spam.bar)
Методи, обекти, класове и имена
- Функциите са обекти
- Методите са обекти
- Методите са атрибути на класа
- Това обяснява защо именованото пространство на променливи, функции и класове е едно и също.
Aтрибути
- getattr(obj, 'name')
- setattr(obj, 'name', value)
- del obj.name
Достъпване на атрибути
- Когато се опитате да достъпите атрибут на даден обект, се вика `__getattribute__`.
- `__getattribute__` проверява в `__dict__` на текущия обект и на неговите родители.
- Ако този атрибут не съществува в никое от тези места, се вика `__getattr__`.
- Очевидно, те могат да се предефинират.
- Счита се, че не е особено добра идея да се предефинира `__getattribute__`.
class Foo:
bar = 1
def __getattribute__(self, name):
if name == 'foo':
return 8
return super().__getattribute__(name)
def __getattr__(self, name):
return name
foo = Foo()
print(foo.bar)
print(foo.foo)
print(foo.baba)
Други операции с атрибути
__setattr__
__delattr__