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

问题描述

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