python散装笔记——144: 属性访问
1: 使用点符号进行基本属性访问
我们先来看一个示例类。
class Book:
def __init__(self, title, author):
self.title = title
self.author = author
book1 = Book(title="Right Ho, Jeeves", author="P.G. Wodehouse")
在Python中,你可以使用点符号访问类的属性title。
>>> book1.title
'P.G. Wodehouse'
如果属性不存在,Python会抛出一个错误:
>>> book1.series
Traceback (most recent call last):
File "", line 1, in
AttributeError: 'Book' object has no attribute 'series'
2: 设置器、获取器和属性
为了实现数据封装,有时你希望有一个属性,其值来自其他属性,或者其值需要在那一刻计算得出。处理这种情况的标准方法是创建一个方法,称为获取器(getter)或设置器(setter)。
class Book:
def __init__(self, title, author):
self.title = title
self.author = author
在上面的例子中,很容易看出,如果我们创建一本包含标题和作者的新书,会发生什么。如果我们要添加到图书馆的所有书籍都有作者和标题,那么我们可以跳过获取器和设置器,直接使用点符号。然而,假设我们有一些书籍没有作者,我们希望将作者设置为“Unknown”。或者如果它们有多个作者,我们计划返回一个作者列表。
在这种情况下,我们可以为author属性创建一个获取器和一个设置器。
class Book:
def __init__(self,title,author):
self.title = title
self.setAuthor(author)
def getAuthor(self):
return self.author
def setAuthor(self, author):
if not author:
self.author = "Unknown"
else:
self.author = author
这种方案不推荐。
原因之一是存在一个陷阱:假设我们设计类时使用了公共属性,而没有方法。人们已经大量使用了它,并且他们编写了如下代码:
>>> book = Book(title="Ancient Manuscript", author="Some Guy")
>>> book.author = "" # 这将覆盖掉作者 Some Guy!
现在我们遇到了问题。因为author不是一个属性!Python提供了一个名为属性(properties)的解决方案来解决这个问题。通过在方法头部之前使用@property装饰器来获取属性。我们希望作为设置器的方法在之前使用@attributeName.setter装饰。
记住这一点,我们现在有了我们更新后的新类。
class Book:
def __init__(self, title, author):
self.title = title
self.author = author
@property
def author(self):
return self.__author
@author.setter
def author(self, author):
if not author:
self.__author = "Unknown"
else:
self.__author = author
注意,通常Python不允许你有多个同名但参数数量不同的方法。然而,在这种情况下,Python允许这样做是因为使用了装饰器。
如果我们测试代码:
>>> book = Book(title="Ancient Manuscript", author="Some Guy")
>>> book.author = "" #Cos Some Guy didn't write this one!
>>> book.author
Unknown
属性封装:
- 使用@property装饰器可以将方法伪装成属性,从而在访问属性时执行特定的逻辑。
- 使用@attributeName.setter装饰器可以定义设置属性时的行为。
私有属性:
- 在Book类中,__author是一个私有属性,只能通过author属性访问和修改。这有助于封装数据,防止直接访问内部实现。
默认值处理:
- 在设置器中,如果传入的author为空,则自动设置为"Unknown",这提供了一种默认值处理机制。
通过使用属性(properties),你可以更灵活地控制属性的访问和设置,同