用于刷新光标实例的 Python 装饰器
我有一种在数据库中保存数据的方法,还有一个装饰器来管理连接,但我不知道如何使其工作。
保存方法:
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 ?
如果不可能,如何以不同的方式解决这个问题?
谢谢您的宝贵时间!
I have a method to save data in DB, and a decorator to manage the connection, but I can't figure out how to make it work.
method to save:
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"
)
)
and I have here the inherited class with a function decorator that does not work.
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
....
Shown this...
How can I redefine DABase.__cursor
from a decorator?
If is not possible, how to solve this problem in a different way?
Thank you for your time!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果您显示您收到的错误,这将会有所帮助。但是,我可以猜测...
装饰类的方法很困难。
connectAndDisconnect
应该如何知道self
应该是什么?connectAndDisconnect
是基类的一个静态方法,在创建派生类时调用该方法,早于派生类的任何实例获得创建的。有一个技巧可以让装饰器弄清楚 self 应该是什么,但这是一个复杂的技巧,而且很脆弱,我将在最后解释。诀窍是,使用类作为装饰器,并使该类成为描述符(即定义
__get__
),以便您有机会确定self 应该是。在您的情况下,它看起来像:
派生类未更改:
现在 DA_Row.save 实际上是 connectAndDisconnect 类的实例。如果
d
是一个DA_Row
对象并且有人调用d.save()
,首先发生的事情是connectAndDisconnect.__get__< /code> 被调用,因为有人尝试访问 d.save。这会将
_instance
变量设置为等于d
。然后调用 connectAndDisconnect.__call__ 并进行实际的装饰。大多数时候这都是有效的。但它很脆弱。 仅如果您以“正常”方式(即通过实例)调用
save
,它才有效。如果您尝试做一些有趣的事情,例如调用DA_Row.save(d)
,它不会工作,因为connectAndDisconnect.__get__
不会能够弄清楚实例应该是什么。It would help if you showed the error that you're getting. However, I can take a guess...
Decorating a method of a class is hard. How is
connectAndDisconnect
supposed to know whatself
should be?connectAndDisconnect
is a static method of the base class, which gets called when the derived class gets created, long before any instances of the derived class get created.There's a trick which lets the decorator figure out what
self
should be, but it's a complicated hack and fragile in a way that I'll explain at the end. The trick is, use a class as the decorator, and make that class an descriptor (i.e. define__get__
) to give you a chance to determine whatself
should be. In your case it would look something like:The derived class is unchanged:
Now
DA_Row.save
is actually an instance of theconnectAndDisconnect
class. Ifd
is aDA_Row
object and someone callsd.save()
, the first thing that happens is thatconnectAndDisconnect.__get__
gets called because someone tried to accessd.save
. This sets the_instance
variable to equald
. ThenconnectAndDisconnect.__call__
gets called and the actual decoration takes place.This works, most of the time. But it's fragile. It only works if you call
save
in the "normal" way, i.e. through an instance. If you try to do funny stuff like callingDA_Row.save(d)
instead, it won't work becauseconnectAndDisconnect.__get__
won't be able to figure out what the instance should be.self
只是一个像其他东西一样的名称,它并不像 Java 的this
那样神奇地出现。您需要将其添加到您的装饰器中。试试这个:self
is just a name like everything else, it does not magically appear like Java'sthis
. You need to add it to your decorator. Try this: