Files
Python_CookBook_repo/8.类与对象/6.创建可管理的属性.py

105 lines
3.0 KiB
Python
Raw Permalink Normal View History

2025-09-10 16:12:45 +08:00
# 如果需要自定义对属性的访问,最好的办法就是将属性定义为一个property
# 在这个类中,我们将first_name的getter方法作为一个property
# 在初始化调用时,其实调用了setter方法,跳过了first_name直接访问了_first_name
class Person:
def __init__(self, first_name):
self.first_name = first_name
@property
def first_name(self):
return self._first_name
@first_name.setter
def first_name(self, first_name):
if not isinstance(first_name, str):
raise TypeError('First name must be str')
self._first_name = first_name
@first_name.deleter
def first_name(self):
raise AttributeError('First name cannot be deleted')
# property的重要特性就是根据访问的不同形式,自动触发getter setter deleter
p = Person("Susan")
print(p.first_name)
p.first_name = "blyet"
print(p.first_name)
# del p.first_name
# 对于已经存在的get和set方法,也可以使用property变成内置形式
class Person2:
def __init__(self, first_name):
self.set_first_name(first_name)
def get_first_name(self):
return self._first_name
def set_first_name(self, first_name):
if not isinstance(first_name, str):
raise TypeError('First name must be str')
self._first_name = first_name
def delete_first_name(self):
raise AttributeError('First name cannot be deleted')
name = property(get_first_name, set_first_name, delete_first_name)
p = Person2("Susan")
print(p.name)
p.name = "blyet"
print(p.name)
# del p.name
# 这种方法一般用于确定要在访问属性的时候对它进行一些额外操作的时候,其他场景下尽量不要这么做,这会让程序变慢
# property也可以用来做一些类似懒加载的实时计算属性
import math
class Circle:
def __init__(self, radius):
self.radius = radius
@property
def area(self):
return math.pi * self.radius ** 2
@property
def perimeter(self):
return 2 * self.radius
c = Circle(5)
print(c.radius)
print(c.area)
print(c.perimeter)
# 虽然这样确实很优雅但是在Python被大型程序集成的时候还是使用传统getter和setter好
# 另外不要在类里写大量的property这会让代码膨胀且可读性变差会变得难以维护像下面这样
class Person3:
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
@property
def first_name(self):
return self._first_name
@first_name.setter
def first_name(self, first_name):
if not isinstance(first_name, str):
raise TypeError('First name must be str')
self._first_name = first_name
# 不要这样重复写property
@property
def last_name(self):
return self._last_name
@last_name.setter
def last_name(self, last_name):
if not isinstance(last_name, str):
raise TypeError('Last name must be str')
self._last_name = last_name