目录
在Python中,对象属性和方法通常是public的。
直接访问
class Duck:
def __init__(self, input_name):
self.name = input_name
if __name__ == "__main__":
fowl = Duck('Daffy')
print(fowl.name)
fowl.name = 'Daphne'
print(fowl.name)
# ======输出======= #
Daffy
Daphne
如果希望对属性设置一些私密性,可以使用下面方法:
Getters和Setters
对于面向对象中一些私有对象属性,是不能由类外访问的,程序员需要写一些读取属性或设定属性的函数。
Python并没有私有属性,但是可以写getters和setters来实现私有。
class Duck:
def __init__(self, input_name):
self.hidden_name = input_name
def get_name(self):
print("Inside the getter.")
return self.hidden_name
def set_name(self, input_name):
print("Inside the setter.")
self.hidden_name = input_name
if __name__ == "__main__":
fowl = Duck('Daffy')
print(fowl.get_name())
fowl.set_name("Daphne")
print(fowl.get_name())
# ======输出======= #
Inside the getter.
Daffy
Inside the setter.
Inside the getter.
Daphne
property()
class Duck:
def __init__(self, input_name):
self.hidden_name = input_name
def get_name(self):
print("Inside the getter.")
return self.hidden_name
def set_name(self, input_name):
print("Inside the setter.")
self.hidden_name = input_name
name = property(get_name, set_name)
if __name__ == "__main__":
fowl = Duck('Daffy')
print(fowl.get_name())
fowl.set_name("Daphne")
print(fowl.get_name(), '\n')
don = Duck('Donald')
print(don.name)
don.name = 'Donna'
print(don.name)
# ======输出======= #
Inside the getter.
Daffy
Inside the setter.
Inside the getter.
Daphne
Inside the getter.
Donald
Inside the setter.
Inside the getter.
Donna
@property
class Duck:
def __init__(self, input_name):
self.hidden_name = input_name
@property
def name(self):
print("Inside the getter.")
return self.hidden_name
@name.setter
def name(self, input_name):
print("Inside the setter.")
self.hidden_name = input_name
if __name__ == "__main__":
fowl = Duck('Daffy')
print(fowl.name)
fowl.name = "Daphne"
print(fowl.name)
# ======输出======= #
Inside the getter.
Daffy
Inside the setter.
Inside the getter.
Daphne
也可以用于计算数值,可以像类有radius属性一样以属性方式调用diameter函数。且当我们改变radius属性后,diameter也会跟着改变。如果没有指定属性的setter property,就不能在外部设定值。
class Circle():
def __init__(self, radius):
self.radius = radius
@property
def diameter(self):
return 2 * self.radius
if __name__ == "__main__":
c = Circle(5)
print(c.radius)
print(c.diameter)
c.radius = 7
print(c.radius)
print(c.diameter)
c.diameter = 20
# =====输出===== #
5
10
7
14
Error: .... can't set attribute
对直接属性访问,使用property的另一个好处是,如果改变了属性的定义,只需要更改类定义中的代码,不用修改所有函数中的属性。
私有属性__name
Python对于类定义外不可见的属性命名有一个传统,即__name(双下划线在前)。
class Duck():
def __init__(self, input_name):
self.__name = input_name
@property
def name(self):
print("Inside the getter.")
return self.__name
@name.setter
def name(self, input_name):
print("Inside the setter.")
self.__name = input_name
if __name__ == '__main__':
fowl = Duck('Howard')
print(fowl.name)
fowl.name = 'Donald'
print(fowl.name)
print(fowl._Duck__name) # 还是能打印出来的
print(fowl.__name)
# =====输出===== #
Inside the getter.
Howard
Inside the setter.
Inside the getter.
Donald
Donald
Error: ...
尽管这个命名传统并不是使属性完全private,但Python让属性名不太可能被外部代码改变。
类属性和对象属性
可以给类属性赋值,这个值会被对象继承。
如果改变对象的属性值,不会影响类的属性值。
如果后续改变了类的属性值,不会影响已经存在的对象的属性值,但是会影响新建的对象属性值。