我有一种方法可以在DB中保存数据,还有一个装饰器来管理连接,但我无法弄清楚如何使它工作。
保存方法:
class DA_Row(DABase):
@DABase.connectAndDisconnect
def save(self):
"""
Guarda el spin en la base de datos
"""
self.__cursor.callproc('sp_insert_row', (
"value 1",
"value 2"
)
)
我在这里有一个带有函数装饰器的继承类,它不起作用。
class DABase():
def __init__(self):
self.__cursor = None
@staticmethod
def connectAndDisconnect(func):
def deco(*args):
returnValue = None
self.DBconnect()
try:
self.__cursor = self.db.cursor()
returnValue = func(*args)
finally:
self.desconectarDB()
return returnValue
return deco
....
显示这个......
如何从装饰器中重新定义DABase.__cursor
?
如果不可能,如何以不同的方式解决这个问题?
感谢您的时间!
答案 0 :(得分:4)
self
就像其他一切一样,它并不像Java的this
那样神奇地出现。您需要将它添加到装饰器中。试试这个:
@staticmethod
def connectAndDisconnect(func):
# deco will be a method, so it needs self (ie a DA_Row instance)
def deco(self, *args):
returnValue = None
self.DBconnect()
try:
self.__cursor = self.db.cursor()
# func was supposed to be a method to, so it needs self
returnValue = func(self, *args)
finally:
self.desconectarDB()
return returnValue
return deco
答案 1 :(得分:2)
如果您显示出错误,那将会有所帮助。但是,我可以猜一猜......
装饰课程的方法很难。 connectAndDisconnect
如何知道self
应该是什么? connectAndDisconnect
是基类的静态方法,在创建派生类时,在派生类的任何实例创建之前很久就会调用它。 / p>
有一个技巧可以让装饰者找出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__
将无法确定实例应该是什么。