我创建了一个class String()与__get__(),__set__(),和的方法to_db(); 但是,当我这样做时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)
Run Code Online (Sandbox Code Playgroud)
解决这个问题的一种方法是不self.name.to_db()直接调用,而是设置一个标志instance并创建一个条件__get__()来检查它并调用to_db()它True,但这似乎是kludgy.有没有更好的办法?
此外,我是描述符的新手 - 使用instance和/或instance.__dict__存储状态与存储它的优点/缺点是什么self?
小智 6
这很简单 - 让你的描述符返回一个字符串的子类,并带有你想要的额外方法.
def __get__(self, instance, owner):
class TaggedString(str):
def to_db(self):
return {'type':'string', 'value': self}
return TaggedString(self.value)`
Run Code Online (Sandbox Code Playgroud)
Ric*_*lli -1
内部方法to_db中,您可以通过以下方式直接访问该值
\n\nself.__dict__[\'value\'] # value as key is not ideal, but that\'s what OP used\nRun Code Online (Sandbox Code Playgroud)\n\n或者,如果您仅使用新样式类,
\n\nobject.__set__(self, name, value)\nRun Code Online (Sandbox Code Playgroud)\n\n既然你使用的是魔法属性,那么访问魔法__dict__是完全合理的。
[1]的文档中也提到了这一点__setattr__(抱歉,没有直接引用,__dict__但__set__它是相同的问题域)
If __setattr__() wants to assign to an instance attribute, it should not \nsimply execute self.name = value \xe2\x80\x94 this would cause a recursive call to itself. \nInstead, it should insert the value in the dictionary of instance attributes, e.g., \nself.__dict__[name] = value. For new-style classes, rather than accessing the instance \ndictionary, it should call the base class method with the same name, for example, \nobject.__setattr__(self, name, value).\nRun Code Online (Sandbox Code Playgroud)\n\n[1] http://docs.python.org/2/reference/datamodel.html#customizing-attribute-access
\n