python - 为什么 getter/setter 方法必须与原始属性的名称相同?

标签 python python-3.x properties setter getter

我不明白为什么 getter/setter 方法的名称必须与属性具有相同的名称。

我试过阅读 Aaron Hall 的回答 here , 但我仍然找不到(或错过)关于为什么我们必须使用各自名称的解释。

class Car(object):
    def __init__(self, color='blue'):
        self.color = color
        self.current_model = 'Opel'

    @property
    def model(self, new_model):
        return self.current_model 


    @model.setter
    def model(self, new_model): 
        if new_model == 'Audi':
            raise ValueError ('NO AUDI ALLOWED')
        else:
            self.current_model = new_model

    # model = model.setter(models) but doing this works

    @model.getter
    def model(self):
        return self.current_model 

编辑: 我感到困惑的是,如果我将我的方法重命名为:

@model.setter
def model_new(self, new_model): 
    if new_model == 'Audi':
        raise ValueError ('NO AUDI ALLOWED')
    else:
        self.current_model = new_model

然后我尝试运行:

audi = Car()
audi.model = 'BMW' # will get AttributeError: can't set attribute

我预计这不会起作用,因为 getter、setter 和 deleter 方法会创建属性的副本,并且更改方法的名称就像修改不同属性的属性一样。这就像做:models = model.setter(models)。

但我不确定我是否理解正确

最佳答案

函数名称需要相同,因为 @model.setter 不会更新现有属性;它用基于现有属性的新属性替换它。当您将属性方法用作装饰器时,属性的名称是最后装饰的函数的名称。

记住,

@model.setter
def model(self, new_model): 
    if new_model == 'Audi':
        raise ValueError ('NO AUDI ALLOWED')
    else:
        self.current_model = new_model

大致相当于

def tmp(self, new_model): 
    if new_model == 'Audi':
        raise ValueError ('NO AUDI ALLOWED')
    else:
        self.current_model = new_model

model = model.setter(tmp)

也就是说,由def 语句绑定(bind)的名称(model)改为绑定(bind)到model.setter 的结果。如果您使用不同的名称,那么您已经更改了属性的名称。


最直接的方法是同时提供 getter(以及可选的 setter 和 deleter):

def foo_get(self):
    ...

def foo_set(self, v):
    ...

foo = property(foo_get, foo_set)

由于创建属性只需要 getter,您可以单独指定它,然后将旧属性与 setter 组合起来创建一个新属性。

foo = property(foo_get)
foo = foo.setter(foo_set)

装饰器语法允许您跳过显式命名 getter 和 setter:

# Instead of foo = property(foo_get), define a function named foo,
# pass it to property, and rebind the name foo to the new property
@property
def foo(self):
    ...

# Instead of foo.setter(foo_set), define *another* function named foo,
# pass it too foo.setter, and rebind the name foo to the new, augmented property. Note that this works because Python will evaluate `@foo.setter` to
# get a reference to the bound property method
# before it evaluates the following def statement.
@foo.setter
def foo(self, v):
    ...

关于python - 为什么 getter/setter 方法必须与原始属性的名称相同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57658859/

相关文章:

python - 等待 shutil.copyfile 完成

python - 递归函数转换字符

python - 有没有理由使用 "is"?

python-3.x - 在Python 3中从给定集合中查找给定长度的所有可能序列

python - 如何以及在哪里计算 python 中的派生实例变量

python - 需要让我的 python web 应用程序像守护进程一样 self 监控(保持事件状态)

python - Python类之间如何通信?

python - Celery 不使用 Redis 在 Kubernetes 中处理任务

c# - 如何定义属性

objective-c - 更改 UIPageViewController 自己的关于点颜色的 PageController