събота, 17 януари 2009 г.

Метакласове в Python

„ Програмиране с 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

Няма коментари:

Публикуване на коментар