为什么 getter/setter 方法的名称必须与原始 属性 的名称相同?
Why do getter/setter methods have to have the same name(s) as name of original property?
我不明白为什么 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 和删除方法创建了 属性 的副本,更改方法的名称就像修改不同 属性 的属性。就像做:models = model.setter(models).
但是我不确定我是否理解正确
简而言之:他们不必,但建议这样做。
如果我对你的问题的理解正确,你想知道为什么命名是个好习惯
class Car(object):
def __init__(self, color='blue', model='Opel'):
self.color = color
self._current_model = model
@property
def model(self): #THIS FUNCTION...
return self._current_model
@model.setter
def model(self, new_model): #...LIKE THIS FUNCTION
if new_model == 'Audi':
raise ValueError ('NO AUDI ALLOWED')
else:
self._current_model = new_model
这样做是个好主意,因为它避免了混淆,并且与第二种定义属性的方式一致。考虑这个片段:
class Car:
def __init__(self, color='blue', model='Opel'):
self.color = color
self._current_model = model
def g(self):
print('Getting value')
return self._current_model
def s(self, model):
print('Setting value')
self._current_model = model
def d(self):
print('Deleting value')
del self._current_model
prop = property(g, s, d)
您为获取、设置、删除等定义一个单独的函数,并使用它们创建 属性 class 的实例。您现在可以通过
这些函数修改您的隐藏变量
my_car = Car();
my_car.prop = 'BMW' #call the setter
print(my_car.prop) #call the getter
del my_car.prop #call the deleter
这很干净,你知道你正在使用的变量。作为反例,请看这个片段:
class Car:
def __init__(self, color='blue', model='Opel'):
self.color = color
self._current_model = model
@property
def g(self):
print('Getting value')
return self._current_model
@g.setter
def s(self, model):
print('Setting value')
self._current_model = model
@g.deleter # this could be s.deleter as well
def d(self):
print('Deleting value')
del self._current_model
如您所见,与 属性 相比,您可能对设置器和删除器使用了不同的名称。如果您尝试做与以前相同的事情,您最终会得到难以理解的代码:
mycar = Car();
mycar.s = 'BMW'
print(mycar.g)
del mycar.d
你好像用了3个属性来修改隐藏变量。这会不必要地污染命名空间,通常不推荐使用。因此,坚持使用一个名称是有意义的,这与以前的 属性 定义一致。
函数名称需要相同,因为 @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
语句绑定的名称(model
)改为绑定到model.setter
的结果。如果您使用不同的名称,那么您已经更改了 属性.
的名称
最简单的方法是同时提供 getter(以及可选的 setter 和删除器):
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):
...
我不明白为什么 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 和删除方法创建了 属性 的副本,更改方法的名称就像修改不同 属性 的属性。就像做:models = model.setter(models).
但是我不确定我是否理解正确
简而言之:他们不必,但建议这样做。
如果我对你的问题的理解正确,你想知道为什么命名是个好习惯
class Car(object):
def __init__(self, color='blue', model='Opel'):
self.color = color
self._current_model = model
@property
def model(self): #THIS FUNCTION...
return self._current_model
@model.setter
def model(self, new_model): #...LIKE THIS FUNCTION
if new_model == 'Audi':
raise ValueError ('NO AUDI ALLOWED')
else:
self._current_model = new_model
这样做是个好主意,因为它避免了混淆,并且与第二种定义属性的方式一致。考虑这个片段:
class Car:
def __init__(self, color='blue', model='Opel'):
self.color = color
self._current_model = model
def g(self):
print('Getting value')
return self._current_model
def s(self, model):
print('Setting value')
self._current_model = model
def d(self):
print('Deleting value')
del self._current_model
prop = property(g, s, d)
您为获取、设置、删除等定义一个单独的函数,并使用它们创建 属性 class 的实例。您现在可以通过
这些函数修改您的隐藏变量my_car = Car();
my_car.prop = 'BMW' #call the setter
print(my_car.prop) #call the getter
del my_car.prop #call the deleter
这很干净,你知道你正在使用的变量。作为反例,请看这个片段:
class Car:
def __init__(self, color='blue', model='Opel'):
self.color = color
self._current_model = model
@property
def g(self):
print('Getting value')
return self._current_model
@g.setter
def s(self, model):
print('Setting value')
self._current_model = model
@g.deleter # this could be s.deleter as well
def d(self):
print('Deleting value')
del self._current_model
如您所见,与 属性 相比,您可能对设置器和删除器使用了不同的名称。如果您尝试做与以前相同的事情,您最终会得到难以理解的代码:
mycar = Car();
mycar.s = 'BMW'
print(mycar.g)
del mycar.d
你好像用了3个属性来修改隐藏变量。这会不必要地污染命名空间,通常不推荐使用。因此,坚持使用一个名称是有意义的,这与以前的 属性 定义一致。
函数名称需要相同,因为 @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
语句绑定的名称(model
)改为绑定到model.setter
的结果。如果您使用不同的名称,那么您已经更改了 属性.
最简单的方法是同时提供 getter(以及可选的 setter 和删除器):
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):
...