微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

函数如何像描述符一样工作?

如何解决函数如何像描述符一样工作?

def typed_property(name,expected_type):
    storage_name = '_' + name

    @property
    def prop(self):
        return getattr(self,storage_name)

    @prop.setter
    def prop(self,value):
        if not isinstance(value,expected_type):
            raise TypeError('{} must be a {}'.format(name,expected_type))
        setattr(self,storage_name,value)
    return prop


class Person:
    name = typed_property('name',str)
    age = typed_property('age',int)
    def __init__(self,name,age):
        self.name = name
        self.age = age

函数 typed_property() 就像一个描述符。为什么在执行这行代码时会调用 prop() (name = typed_property('name',str))?

解决方法

我不知道您所说的“描述符”是什么意思。 typed_property 允许属性调用函数进行额外处理。执行您提到的行时不会调用 prop()。它在执行 self.name = name 时被调用。 @prop.setter 使得对象可以响应这样的属性调用。

,

当您调用 typed_property 来设置类属性 nameage 的值时,您实际上是在将它们定义为用于访问实例值 {{1} } 和 self.name。这与下面为简单起见省略年龄相同:

self.age

这将 class Person: def __init__(self,name): self.name = name @property def name(self): print("=== ACESSING") return self.name @name.setter def name(self,name): print("=== MUTATING") self.name = name 方法标记为 name(self) 的访问器,将 self.name 标记为修改器。每当您尝试更改(变异)其分配的属性的值时,都会调用 mutator,在本例中为 name(self,val)。这包括您在 self.name 方法中调用它的时间。但是,使用上面定义的类将导致无限递归,因为我是从 mutator 内部调用 mutator。所以“=== MUTATING”将以递归错误结尾。所以需要一个小的调整:

__init__

既然底层属性是 name class Person: def __init__(self,name): self._name = name @property def name(self): print("=== ACCESSING") return self._name @name.setter def name(self,val): print("=== MUTATING") self._name = val 而不是 _name,mutator 将设置 name 的值而不是将其设置为 _name 并无限循环到自身。例如,使用上面定义的类:

name

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。