如何在Python类描述符对象上调用方法?

esp*_*eed 4 python descriptor

我创建了一个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\n
self.__dict__[\'value\'] # value as key is not ideal, but that\'s what OP used\n
Run Code Online (Sandbox Code Playgroud)\n\n

或者,如果您仅使用新样式类,

\n\n
object.__set__(self, name, value)\n
Run Code Online (Sandbox Code Playgroud)\n\n

既然你使用的是魔法属性,那么访问魔法__dict__是完全合理的。

\n\n

[1]的文档中也提到了这一点__setattr__(抱歉,没有直接引用,__dict____set__它是相同的问题域)

\n\n
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).\n
Run Code Online (Sandbox Code Playgroud)\n\n

[1] http://docs.python.org/2/reference/datamodel.html#customizing-attribute-access

\n