@property
- 是一个装饰器,相当于 getter 装饰器
- 可以使用 @property 来创建只读属性,将一个实例方法变成一个相同名称的只读实例属性,这样可以防止属性被修改
代码栗子
# @property class PoloBlog: def __init__(self, name): self.__name = name @property def name(self): return self.__name blog = PoloBlog("小菠萝") print(blog.name) blog.name = "test" # 输出结果 小菠萝 blog.name = "test" AttributeError: can't set attribute
name 是一个只读属性,不可写,相当于 __name 私有属性只有 getter 方法,没有 setter 方法
等价写法
class PoloBlog: def __init__(self, name): self.__name = name def getName(self): return self.__name name = property(getName) blog = PoloBlog("小菠萝") print(blog.name)
那想给 __name 设置值怎么办呢?
setter 装饰器
语法格式
@方法名.setter
def 方法名(self, value):
self.__value = value
...
代码栗子
# @setter class PoloBlog: def __init__(self, name): self.__name = name @property def name(self): return self.__name @name.setter def name(self, name): self.__name = name blog = PoloBlog("小菠萝") # 打印属性值 print(blog.name) # 修改属性 blog.name = "新的小菠萝" print(blog.name) # 输出结果 小菠萝 新的小菠萝
deleter 装饰器
和 setter 装饰器差不多写法
语法格式
@方法名.deleter
def 方法名(self):
...
代码栗子
class PoloBlog: def __init__(self, name): self.__name = name @property def name(self): return self.__name @name.setter def name(self, name): self.__name = name @name.deleter def name(self): print("删除 __name") blog = PoloBlog("小菠萝") # 打印属性值 print(blog.name) # 修改属性 blog.name = "新的小菠萝" # 删除属性 del blog.name # 输出结果 小菠萝 删除 __name
@property 踩坑
加了 @property 的方法相当于一个实例属性,所以不能和其他实例属性重名
错误代码栗子
class A: def __init__(self): # 已经定义了 name 实例属性 self.name = 2 # 这里相当于也定义了一个 name 实例属性 @property def name(self): return self.name @name.setter def name(self, name): self.name = name a = A() print(a.name) # 输出结果 Traceback (most recent call last): File "/Users/polo/Documents/pylearn/第四章:面向对象/17_实战5.py", line 26, in <module> a = A() File "/Users/polo/Documents/pylearn/第四章:面向对象/17_实战5.py", line 14, in __init__ self.name = 2 File "/Users/polo/Documents/pylearn/第四章:面向对象/17_实战5.py", line 23, in name self.name = name File "/Users/polo/Documents/pylearn/第四章:面向对象/17_实战5.py", line 23, in name self.name = name File "/Users/polo/Documents/pylearn/第四章:面向对象/17_实战5.py", line 23, in name self.name = name [Previous line repeated 994 more times] RecursionError: maximum recursion depth exceeded
报错翻译:递归错误 超过最大递归深度
其实就是因为命名冲突导致了死循环
改下命名就好了
class A: def __init__(self): # 已经定义了 name 实例属性 self.name = 2 # 这里相当于也定义了一个 name 实例属性 @property def name_func(self): return self.name @name_func.setter def name_func(self, name): self.name = name a = A() print(a.name) # 输出结果 2