„ Програмиране с Python“, ФМИ
Стефан Кънев & Николай Бачийски
11.04.2007г.
Метакласове
Метакласовете са инструмент, който ще ползвате в много малко случаи и клиента на вашия код винаги ще е друг програмист. Те помагат за създаване на по-устойчиви и използваеми абстракции, а не решават проблеми директно. Въпреки това, те имат големи възможности и можете да постигнете с тях много неща по елегантен начин. Имайте предвид, че всичко което можете да постигнете с метакласове може да стане и със стандартни способи.
Концепцията
Метакласовете представляват "типове" на класовете. Тези типове определят механиката и правилата на които класът се подчинява. Пример биха могли да бъдат класовете нов и стар стил, които работят по различни правила. Но като нищо може да си измислим и наши типове класове. Например:
* singleton-и
* класове, чиито методи при грешка просто връщат None
* класове, чиито методи получават self неявно
Singleton
class DatabaseConnector(object):
self = None
def __new__(cls):
if not DatabaseConnector.self:
DatabaseConnector.self = object.__new__(cls)
return DatabaseConnector.self
class Mailer(object):
self = None
def __new__(cls):
if not Mailer.self:
Mailer.self = object.__new__(cls)
return Mailer.self
mailer1 = Mailer()
mailer2 = Mailer()
print mailer1 is mailer2 # True
Същото, но с метакласове
class singleton(type):
def __new__(cls, name, bases, classDict):
def getInstance(klass):
if not klass.self:
klass.self = object.__new__(klass)
return klass.self
classDict['self'] = None
classDict['__new__'] = getInstance
return type.__new__(cls, name, bases, classDict)
class Mailer(object):
__metaclass__ = singleton
mailer1 = Mailer()
mailer2 = Mailer()
print mailer1 is mailer2
Класове, чиито методи не хвърлят грешки
def silent(func):
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except:
return None
return wrapper
class Something(object):
@silent
def foo(self): assert false
@silent
def bar(self): print belch
@silent
def omgTooMuchDecorators(self): pass
something = Something()
something.foo()
Отново, с метакласове
def silent(func):
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except:
return None
return wrapper
class silentType(type):
def __new__(cls, name, bases, classDict):
for name, attr in classDict.items():
if callable(attr):
classDict[name] = silent(attr)
return type.__new__(cls, name, bases, classDict)
class Something(object):
__metaclass__ = silentType
def foo(self): assert false
def bar(self): print belch
def omgTooMuchDecorators(self): pass
something = Something()
something.foo()
something.bar()
Класове без self
class Person(object):
__metaclass__ = selfless
def __init__(name, age):
self.name = name
self.age = age
def __repr__():
return "Person(%s, %d)" % (repr(self.name), self.age)
def sayHi():
print "Hello, I'm %s and I'm %d years old" % (self.name, self.age)
def rename(newName):
self.name = newName
Класове без self (2)
from types import FunctionType
class selfless(type):
def __new__(cls, name, bases, classDict):
for attr in classDict:
if not isinstance(classDict[attr], FunctionType): continue
classDict[attr] = selflessWrapper(classDict[attr])
return type.__new__(cls, name, bases, classDict)
def selflessWrapper(func):
def wrapper(self, *args, **kwargs):
hadSelf, oldSelf = func.func_globals.has_key('self'),
func.func_globals.get('self')
func.func_globals['self'] = self
returnValue = func(*args, **kwargs)
if hadSelf:
func.func_globals['self'] = oldSelf
else:
del func.func_globals['self']
return returnValue
wrapper.func_name = func.func_name + "_wrapper"
return wrapper
Няма коментари:
Публикуване на коментар