Python 中的 getter 和 setter 如何工作?
How do getters and setters work in Python?
我正在学习 getters 和 setters ,我的理解是它们的使用使得没有人可以直接改变对象的属性。在例子中
class Person:
def __init__(self, name, age):
self._name = name
self._age = age
def get_age(self):
return self._age
def set_age(self, new_age):
if isinstance(new_age, int) & new_age>0 & new_age<120:
self._age = new_age
def get_name(self):
return self._name
def __str__(self):
return 'Person[' + self._name + '] is ' + str(self._age)
p1 = Person("Sandeep", 49)
我创建了一个对象 p1
,我将年龄设置为 49。因为我已经创建了一个 set_age
函数,所以我希望我们可以通过 [=13] 更改 p1
的年龄=] 只是,不是通过常规方式。但这并没有发生,我也可以通过 p1
更改 p1
的年龄,例如 p1._age = 35
。那么,如果我仍然能够直接访问属性,那么使 set_age
函数有什么好处呢?
我想,我遗漏了一些东西,请帮忙。
what I understand is that they are used so that no one could change the object's attributes directly.
你的理解有误。没有神奇的规则告诉 python 解释器 oh, this class has a setter, so direct access to the fields aren't allowed any more
.
换句话说:这仅仅是“按惯例工作”。当你看到一个有setter方法的pythonclass时,你知道你不应直接访问字段,尽管您仍然可以这样做。
注意:python 对此类事情大多相当宽容。很多事情只是“按照惯例”。这只是 python 的“本质”:您可以做很多其他语言,尤其是像 Java 这样的静态类型语言不允许做的事情。
您需要告诉 python 如何将 getter 和 setter 与实际变量名称相关联。为此,您可以使用内置的 property
函数,如下所示:
class Person
def __init__(self, name, age):
self._name = name
self._age = age
def get_age(self):
return self._age
def set_age(self, new_age):
if isinstance(new_age, int) & new_age>0 & new_age<120:
self._age = new_age
def get_name(self):
return self._name
name = property(get_name)
age = property(get_age, set_age)
def __str__(self):
return 'Person[' + self.name + '] is ' + str(self.age)
p1 = Person("Sandeep", 49)
然后不要引用 _name
和 _age
使用 name
和 age
现在我意识到我问了一个愚蠢的问题。使用 setters
的原因很明显,创建用于设置值的函数是对其应用约束的一种非常方便的方法。在上面的例子中,约束是人的年龄应该是正数并且小于 120。如果没有 setters
.
是不可能实现这样的约束的
使用 getter 和 setter 的原因是,如果您想做一些比使用 foo.bar
设置和属性更复杂的事情。在你的例子中,set_age
有一个
isinstance(new_age, int) & new_age>0 & new_age<120
检查,这是不可能用原始属性做的。 (Side-note:你应该使用 and
而不是 &
。)
是的,有人仍然可以做到 p1._age = -1
,然后他们的代码将无法工作,但他们为什么会这样?这只会让他们的代码无法工作。
您的 get_name
功能不如 age
有用。它基本上使 name
read-only,这可能有用也可能没用。
在Python中创建setter和getter时,通常使用@property
装饰器。这意味着可以像调用属性一样调用函数,因此您可以只执行 p1.name
而不是 p1.get_name()
。同样 p1.set_age(3)
变成 p1.age = 3
.
您可能想在 __init__
中使用年龄 setter,因为 Person
的年龄在创建时会被验证。
这是一个进行了这些更改的版本(以及其他一些可读性改进)。
class Person:
def __init__(self, name, age):
self._name = name
self.age = age
@property
def age(self):
return self._age
@age.setter
def age(self, new_age):
if isinstance(new_age, int) and 0 < new_age < 120:
self._age = new_age
@property
def name(self):
return self._name
def __str__(self):
return f"Person[{self.name}] is {self.age}"
p1 = Person("Sandeep", 49)
我正在学习 getters 和 setters ,我的理解是它们的使用使得没有人可以直接改变对象的属性。在例子中
class Person:
def __init__(self, name, age):
self._name = name
self._age = age
def get_age(self):
return self._age
def set_age(self, new_age):
if isinstance(new_age, int) & new_age>0 & new_age<120:
self._age = new_age
def get_name(self):
return self._name
def __str__(self):
return 'Person[' + self._name + '] is ' + str(self._age)
p1 = Person("Sandeep", 49)
我创建了一个对象 p1
,我将年龄设置为 49。因为我已经创建了一个 set_age
函数,所以我希望我们可以通过 [=13] 更改 p1
的年龄=] 只是,不是通过常规方式。但这并没有发生,我也可以通过 p1
更改 p1
的年龄,例如 p1._age = 35
。那么,如果我仍然能够直接访问属性,那么使 set_age
函数有什么好处呢?
我想,我遗漏了一些东西,请帮忙。
what I understand is that they are used so that no one could change the object's attributes directly.
你的理解有误。没有神奇的规则告诉 python 解释器 oh, this class has a setter, so direct access to the fields aren't allowed any more
.
换句话说:这仅仅是“按惯例工作”。当你看到一个有setter方法的pythonclass时,你知道你不应直接访问字段,尽管您仍然可以这样做。
注意:python 对此类事情大多相当宽容。很多事情只是“按照惯例”。这只是 python 的“本质”:您可以做很多其他语言,尤其是像 Java 这样的静态类型语言不允许做的事情。
您需要告诉 python 如何将 getter 和 setter 与实际变量名称相关联。为此,您可以使用内置的 property
函数,如下所示:
class Person
def __init__(self, name, age):
self._name = name
self._age = age
def get_age(self):
return self._age
def set_age(self, new_age):
if isinstance(new_age, int) & new_age>0 & new_age<120:
self._age = new_age
def get_name(self):
return self._name
name = property(get_name)
age = property(get_age, set_age)
def __str__(self):
return 'Person[' + self.name + '] is ' + str(self.age)
p1 = Person("Sandeep", 49)
然后不要引用 _name
和 _age
使用 name
和 age
现在我意识到我问了一个愚蠢的问题。使用 setters
的原因很明显,创建用于设置值的函数是对其应用约束的一种非常方便的方法。在上面的例子中,约束是人的年龄应该是正数并且小于 120。如果没有 setters
.
使用 getter 和 setter 的原因是,如果您想做一些比使用 foo.bar
设置和属性更复杂的事情。在你的例子中,set_age
有一个
isinstance(new_age, int) & new_age>0 & new_age<120
检查,这是不可能用原始属性做的。 (Side-note:你应该使用 and
而不是 &
。)
是的,有人仍然可以做到 p1._age = -1
,然后他们的代码将无法工作,但他们为什么会这样?这只会让他们的代码无法工作。
您的 get_name
功能不如 age
有用。它基本上使 name
read-only,这可能有用也可能没用。
在Python中创建setter和getter时,通常使用@property
装饰器。这意味着可以像调用属性一样调用函数,因此您可以只执行 p1.name
而不是 p1.get_name()
。同样 p1.set_age(3)
变成 p1.age = 3
.
您可能想在 __init__
中使用年龄 setter,因为 Person
的年龄在创建时会被验证。
这是一个进行了这些更改的版本(以及其他一些可读性改进)。
class Person:
def __init__(self, name, age):
self._name = name
self.age = age
@property
def age(self):
return self._age
@age.setter
def age(self, new_age):
if isinstance(new_age, int) and 0 < new_age < 120:
self._age = new_age
@property
def name(self):
return self._name
def __str__(self):
return f"Person[{self.name}] is {self.age}"
p1 = Person("Sandeep", 49)