如何调用Python类描述符对象上的方法?
我使用 __get__()
、__set__()
和方法 to_db()
创建了一个 class String()
;但是,当我执行 name = String()
时,我无法执行 self.name.to_db()
因为它正在调用 to_db()
位于 __get__()
返回的值上,而不是对象“name
”。
class String(object):
def __init__(self, value=None):
if value:
self.value = str(value)
def __get__(self, instance, owner):
return self.value
def __set__(self, instance, value):
self.value = str(value)
def to_db(self):
return {'type':'string', 'value': self.value}
class Example(object):
name = String()
age = Integer()
def __init__(self,name,age):
self.name = name
self.age = age
def save():
data = dict(name=self.name.to_db(), age=self.age.to_db())
db.save(data)
处理此问题的一种方法是不直接调用 self.name.to_db() ,而是在 instance
中设置标志并在 __get__() 中创建条件
来检查它,如果它是 True
则调用 to_db()
,但这看起来很混乱。有更好的办法吗?
另外,我对描述符很陌生 - 使用 instance
和/或 instance.__dict__
存储状态与将其存储在 self 中的优点/缺点是什么?
I created a class String()
with __get__()
, __set__()
, and a method to_db()
; however, when I do name = String()
, I can't do self.name.to_db()
because it's calling to_db()
on the value returned by __get__()
, not the object "name
".
class String(object):
def __init__(self, value=None):
if value:
self.value = str(value)
def __get__(self, instance, owner):
return self.value
def __set__(self, instance, value):
self.value = str(value)
def to_db(self):
return {'type':'string', 'value': self.value}
class Example(object):
name = String()
age = Integer()
def __init__(self,name,age):
self.name = name
self.age = age
def save():
data = dict(name=self.name.to_db(), age=self.age.to_db())
db.save(data)
One way to deal with this is to not call self.name.to_db()
directly and instead set a flag in instance
and create a conditional in __get__()
to check for it and call to_db()
if it's True
, but this seems kludgy. Is there a better way?
Also, I'm new to descriptors -- what are the pros/cons of using instance
and/or instance.__dict__
to store state vs storing it in self
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这非常简单 - 只需让您的描述符使用您想要的额外方法返回字符串的子类即可。
It's pretty easy - just have your descriptor return a subclass of string with the extra method(s) you want.
描述符用于描述“它是什么”或“它如何工作”。
例如,我们可以在
__get__()
或__set__()
中添加一些限制。根据您的问题,我认为您想将自己的方法添加到
type
中,而不是描述如何设置或获取实例。因此,您可以使用下面的代码来表达您想要做的事情。
Descriptors are used to describe "what is it" or "how it works".
For example, we can put some restriction in the
__get__()
or the__set__()
.According to your question, I think you want to add your own method into
type<str>
, not to describe how to set or get the instance.So you may use thee code below to express what you want to do.
这是一个允许您绕过类中定义的任何描述符的解决方案:
请注意,它并不完美 - 您始终必须调用
real_fieldname.method()
而不是fieldname.method()
并且您必须对需要访问此字段的所有类使用元类AllowBypassableDescriptors。话又说回来,这是一个非常兼容的解决方案,可以避免对描述符包装的对象进行猴子修补。也就是说,我不确定描述符是您想要做的事情的最佳解决方案(写入数据库?)。
Here's a solution that allows you to bypass any descriptors defined in the class:
Note that it's not perfect - you'll always have to call
real_fieldname.method()
instead offieldname.method()
and you'll have to use the metaclass AllowBypassableDescriptors for all your classes which need to access this field. Then again, it's a pretty compatible solution that avoids monkey-patching the object wrapped by the descriptor.That said, I'm not sure that descriptors are the best solution for what you're trying to do (writing to a database?).
在方法 to_db 中,您可以通过以下方式直接访问值
,或者,如果您仅使用新样式类,
由于您使用的是魔术属性,因此访问魔术
__dict__
是完全合理的。__setattr__
[1] 的文档中也提到了这一点(抱歉,__set__
中没有直接引用__dict__
,但这是同样的问题域)[1] http://docs.python.org/ 2/reference/datamodel.html#customizing-attribute-access
Inside method to_db you may access directly the value via
or, if you are using new style classes only,
Since you are using magic attributes, accessing the magic
__dict__
is perfectly reasonable.This is also referred in the documentation for
__setattr__
[1] (sorry, there is no direct reference to__dict__
in__set__
but it's the same problem domain)[1] http://docs.python.org/2/reference/datamodel.html#customizing-attribute-access