Было бы полезно, если бы вы показали ошибку, которую вы получаете.Однако, я могу предположить ...
Сложно описать метод класса.Как connectAndDisconnect
должен знать, что self
должно быть?connectAndDisconnect
- это статический метод базового класса, который вызывается при создании производного класса задолго до создания экземпляров производного класса.
Есть хитрость, которая позволяет декоратору выяснить, каким должен быть self
, но это сложный взлом и хрупкий способ, который я объясню в конце.Хитрость заключается в том, чтобы использовать класс в качестве декоратора и сделать этот класс дескриптором (т.е. определить __get__
), чтобы дать вам возможность определить, каким должен быть self
.В вашем случае это выглядело бы примерно так:
class DABase(object):
def __init__(self):
self.__cursor = None
class connectAndDisconnect(object):
def __init__(self, method):
self._method = method # method is the thing being decorated
# note that it's an *unbound* method
self._instance = None # no way to know what the instance is yet
def __get__(self, instance, owner):
'This will be called when the decorated method is accessed'
self._instance = instance
return self
def __call__(self, *args):
'This is where the actual decoration takes place'
returnValue = None
# 'self' is the connectAndDisconnect object. 'self._instance' is the decorated object.
self._instance.DBConnect()
try:
self._instance.__cursor = self._instance.db.cursor()
# Since self._method is unbound, we have to pass the instance explicitly
returnValue = self._method(self._instance, *args)
finally:
self._instance.desconectarDB()
return returnValue
Производный класс не изменился:
class DA_Row(DABase):
@DABase.connectAndDisconnect
def save(self):
# ...
Теперь DA_Row.save
фактически является экземпляром класса connectAndDisconnect
.Если d
является DA_Row
объектом и кто-то вызывает d.save()
, первое, что происходит, это то, что connectAndDisconnect.__get__
вызывают, потому что кто-то пытался получить доступ к d.save
.Это устанавливает переменную _instance
равной d
.Затем вызывается connectAndDisconnect.__call__
и происходит фактическое оформление.
В большинстве случаев это работает.Но это хрупко. только работает, если вы вызываете save
«обычным» способом, то есть через экземпляр.Если вы попытаетесь сделать такие забавные вещи, как, например, вызов DA_Row.save(d)
, , он не будет работать , потому что connectAndDisconnect.__get__
не сможет понять, каким должен быть экземпляр.