python笔记57-@property源码解读与使用
前言
Python 内置的 @property
装饰器的作用是把方法变成属性,调用的时候不需要加括号
property源码
property() 方法的传四个参数
- fget --获取属性值的函数
- fset --设置属性值的函数
- fdel --删除属性值函数
- doc --属性描述信息
class property(object):
"""
property(fget=None, fset=None, fdel=None, doc=None) -> property attribute
fget is a function to be used for getting an attribute value, and likewise
fset is a function for setting, and fdel a function for del'ing, an
attribute. Typical use is to define a managed attribute x:
class C(object):
def getx(self): return self._x
def setx(self, value): self._x = value
def delx(self): del self._x
x = property(getx, setx, delx, "I'm the 'x' property.")
Decorators make defining new properties or modifying existing ones easy:
class C(object):
@property
def x(self):
"I am the 'x' property."
return self._x
@x.setter
def x(self, value):
self._x = value
@x.deleter
def x(self):
del self._x
"""
def deleter(self, *args, **kwargs): # real signature unknown
""" Descriptor to change the deleter on a property. """
pass
def getter(self, *args, **kwargs): # real signature unknown
""" Descriptor to change the getter on a property. """
pass
def setter(self, *args, **kwargs): # real signature unknown
""" Descriptor to change the setter on a property. """
pass
def __delete__(self, *args, **kwargs): # real signature unknown
""" Delete an attribute of instance. """
pass
def __getattribute__(self, *args, **kwargs): # real signature unknown
""" Return getattr(self, name). """
pass
def __get__(self, *args, **kwargs): # real signature unknown
""" Return an attribute of instance, which is of type owner. """
pass
def __init__(self, fget=None, fset=None, fdel=None, doc=None): # known special case of property.__init__
"""
property(fget=None, fset=None, fdel=None, doc=None) -> property attribute
fget is a function to be used for getting an attribute value, and likewise
fset is a function for setting, and fdel a function for del'ing, an
attribute. Typical use is to define a managed attribute x:
class C(object):
def getx(self): return self._x
def setx(self, value): self._x = value
def delx(self): del self._x
x = property(getx, setx, delx, "I'm the 'x' property.")
Decorators make defining new properties or modifying existing ones easy:
class C(object):
@property
def x(self):
"I am the 'x' property."
return self._x
@x.setter
def x(self, value):
self._x = value
@x.deleter
def x(self):
del self._x
# (copied from class doc)
"""
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
def __set__(self, *args, **kwargs): # real signature unknown
""" Set an attribute of instance to value. """
pass
fdel = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
fget = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
fset = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
__isabstractmethod__ = property(lambda self: object(), lambda self, v: None, lambda self: None) # default
源码解读
先看源码里面第一个示例
class C(object):
def getx(self):
return self._x
def setx(self, value):
self._x = value
def delx(self):
del self._x
x = property(getx, setx, delx, "I'm the 'x' property.")
实例化后调用x属性
c = C()
c.x = 20 # c.x = value 将触发 setter
print(c.x) # c.x 将触发 getter
del c.x # del c.x 触发 deleter
c 是 C 的实例化对象, c.x 将触发 getter,c.x = value 将触发 setter , del c.x 触发 deleter。
如果给定 doc 参数,其将成为这个属性值的 docstring,否则 property 函数就会复制 fget 函数的 docstring(如果有的话)
装饰器使定义新属性或修改现有属性变得容易,property 的 getter, setter 和 deleter 方法同样可以用作装饰器:
class C(object):
def __init__(self):
self._x = None
@property
def x(self):
"""I'm the 'x' property."""
return self._x
@x.setter
def x(self, value):
self._x = value
@x.deleter
def x(self):
del self._x
这个代码和第一个例子完全相同,但要注意这些额外函数的名字和 property 下的一样,例如这里的 x。
@property 只读属性
我们知道类的属性是可以动态赋值的
class People(object):
def __init__(self):
self.name = "yoyo"
self.age = 20
people = People()
print(people.age) # 20
# 属性动态赋值
people.age = 22
print(people.age) # 22
如果我不想让age属性改变,可以使用 @property
可以设置只读属性的 getter 方法
class People(object):
def __init__(self):
self.name = "yoyo"
self.age = 20
@property
def get_age(self):
return 20
people = People()
print(people.get_age) # 20
如果使用这种赋值代码people.get_age = 22
,会抛出异常AttributeError: can't set attribute
使用示例
设置 my_age 属性可读可写
class Person(object):
def __init__(self, name, age):
self.__name = name
self.__age = age
@property
def my_age(self):
return self.__age
@my_age.setter
def my_age(self, value):
"""设置my_age属性,并校验值"""
if not isinstance(value, int):
raise ValueError('年龄必须是数字!')
if value < 0 or value > 100:
raise ValueError('年龄必须是0-100')
self.__age = value
person = Person("yoyo", 20)
print(person.my_age) # 20
person.my_age = 22
print(person.my_age) # 22
person.my_age = "hh" # ValueError: 年龄必须是数字!
如果你想设置my_age属性可以删除,需用到property 的 deleter 装饰器
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
2019-06-23 docker学习1-CentOS 7安装docker环境
2019-06-23 python笔记38-使用zmail发各种邮件案例代码