Python Property属性详解:从原理到实战应用
本文深入解析Python中property属性的两种实现方式:装饰器模式与类属性模式。通过京东商城分页、商品价格计算及私有属性封装等实例,详细对比经典类与新式类的差异,演示如何优雅地实现数据的获取、修改与删除逻辑,帮助开发者简化代码调用流程并提升代码可读性。
本文通过具体实例深入解析Python中的property属性,内容涵盖定义、调用方式及多种应用场景,旨在为读者的学习或工作提供具有实际参考价值的技术指南。
理解property属性的基本概念
一、理解property属性的基本概念
property是一种特殊属性,其使用体验类似于实例属性,但在底层实际上对应着特定的方法逻辑。
# ############### 定义 ###############
class Foo:
def func(self):
pass
# 定义property属性
@property
def prop(self):
pass
# ############### 调用 ###############
foo_obj = Foo()
foo_obj.func() # 调用实例方法
foo_obj.prop # 调用property属性
以下示例展示了如何定义一个基础的property属性:
class Goods(object):
@property
def size(self):
return 100
g = Goods()
print(g.size)
在定义和调用property属性时,需特别注意以下两点:
- 定义阶段,需在实例方法上方添加@property装饰器,且该方法仅接受self这一个参数。
- 调用阶段,直接访问属性名即可,无需添加括号。
基础应用场景示例
二、基础应用场景示例
以京东商城电脑主机列表页为例,由于数据库数据量庞大,无法一次性全量展示,需采用分页机制局部显示。因此,向数据库请求数据时,必须明确指定获取从第m条到第n条的数据范围。该分页功能主要包含以下环节:
- 根据用户请求的当前页码及总数据条数,计算出起始索引m和结束索引n。
- 依据计算出的m和n值,向数据库发起数据请求。
# ############### 定义 ###############
class Pager:
def __init__(self, current_page):
# 用户当前请求的页码(第一页、第二页...)
self.current_page = current_page
# 每页默认显示10条数据
self.per_items = 10
@property
def start(self):
val = (self.current_page - 1) * self.per_items
return val
@property
def end(self):
val = self.current_page * self.per_items
return val
# ############### 调用 ###############
p = Pager(1)
p.start # 就是起始值,即:m
p.end # 就是结束值,即:n
从上述逻辑可以看出:
Python的property属性核心功能在于:在内部执行一系列逻辑计算,最终将计算结果返回给调用者。
property属性的两种实现方式
三、property属性的两种实现方式
- 方式一:装饰器,即在方法上应用@property装饰器。
- 方式二:类属性,即在类中定义值为property对象的类属性。
3.1 装饰器实现方式
在类的实例方法上应用@property装饰器。
Python中的类分为经典类和新式类,新式类的属性机制比经典类更为丰富(若类继承自object,则视为新式类)。
经典类中,仅支持一种@property装饰器用法:
# ############### 定义 ###############
class Goods:
@property
def price(self):
return "laowang"
# ############### 调用 ###############
obj = Goods()
result = obj.price # 自动执行 @property 修饰的 price 方法,并获取方法的返回值
print(result)
新式类中,支持三种@property装饰器用法:
#coding=utf-8
# ############### 定义 ###############
class Goods:
"""python3中默认继承object类
以python2、3执行此程序的结果不同,因为只有在python3中才有@xxx.setter @xxx.deleter
"""
@property
def price(self):
print('@property')
@price.setter
def price(self, value):
print('@price.setter')
@price.deleter
def price(self):
print('@price.deleter')
# ############### 调用 ###############
obj = Goods()
obj.price # 自动执行 @property 修饰的 price 方法,并获取方法的返回值
obj.price = 123 # 自动执行 @price.setter 修饰的 price 方法,并将 123 赋值给方法的参数
del obj.price # 自动执行 @price.deleter 修饰的 price 方法
需注意以下区别:
- 经典类中的属性仅有一种访问方式,即对应被@property修饰的方法。
- 新式类中的属性支持三种访问方式,分别对应被@property、@方法名.setter、@方法名.deleter修饰的方法。
鉴于新式类具备三种访问方式,我们可以根据访问特点,将三个方法分别定义为对同一属性的获取、修改和删除操作。
class Goods(object):
def __init__(self):
# 原价
self.original_price = 100
# 折扣
self.discount = 0.8
@property
def price(self):
# 实际价格 = 原价 * 折扣
new_price = self.original_price * self.discount
return new_price
@price.setter
def price(self, value):
self.original_price = value
@price.deleter
def price(self):
del self.original_price
obj = Goods()
obj.price # 获取商品价格
obj.price = 200 # 修改商品原价
del obj.price # 删除商品原价
3.2 类属性实现方式,创建值为property对象的类属性
当使用类属性方式创建property属性时,经典类与新式类无区别。
class Foo:
def get_bar(self):
return 'laowang'
BAR = property(get_bar)
obj = Foo()
reuslt = obj.BAR # 自动调用get_bar方法,并获取方法的返回值
print(reuslt)
property方法包含四个参数:
- 第一个参数为方法名,当调用对象.属性时自动触发执行该方法。
- 第二个参数为方法名,当调用对象.属性 = XXX时自动触发执行该方法。
- 第三个参数为方法名,当调用del对象.属性时自动触发执行该方法。
- 第四个参数为字符串,当调用对象.属性.__doc__时返回此参数值,用于描述该属性。
#coding=utf-8
class Foo(object):
def get_bar(self):
print("getter...")
return 'laowang'
def set_bar(self, value):
"""必须两个参数"""
print("setter...")
return 'set value' + value
def del_bar(self):
print("deleter...")
return 'laowang'
BAR = property(get_bar, set_bar, del_bar, "description...")
obj = Foo()
obj.BAR # 自动调用第一个参数中定义的方法:get_bar
obj.BAR = "alex" # 自动调用第二个参数中定义的方法:set_bar方法,并将“alex”当作参数传入
desc = Foo.BAR.__doc__ # 自动获取第四个参数中设置的值:description...
print(desc)
del obj.BAR # 自动调用第三个参数中定义的方法:del_bar方法
由于类属性方式创建的property属性具备三种访问方式,我们可以根据访问特点,将三个方法分别定义为对同一属性的获取、修改和删除操作。
class Goods(object):
def __init__(self):
# 原价
self.original_price = 100
# 折扣
self.discount = 0.8
def get_price(self):
# 实际价格 = 原价 * 折扣
new_price = self.original_price * self.discount
return new_price
def set_price(self, value):
self.original_price = value
def del_price(self):
del self.original_price
PRICE = property(get_price, set_price, del_price, '价格属性描述...')
obj = Goods()
obj.PRICE # 获取商品价格
obj.PRICE = 200 # 修改商品原价
del obj.PRICE # 删除商品原价
综上所述:
- 定义property属性共有两种方式,分别是【装饰器】和【类属性】,其中【装饰器】方式针对经典类和新式类存在差异。
- 使用property属性能够简化调用者获取数据的流程。
property属性的实际应用
四、property属性的实际应用
4.1 为私有属性添加getter和setter方法
class Money(object):
def __init__(self):
self.__money = 0
def getMoney(self):
return self.__money
def setMoney(self, value):
if isinstance(value, int):
self.__money = value
else:
print("error:不是整型数字")
4.2 使用property升级getter和setter方法
class Money(object):
def __init__(self):
self.__money = 0
def getMoney(self):
return self.__money
def setMoney(self, value):
if isinstance(value, int):
self.__money = value
else:
print("error:不是整型数字")
# 定义一个属性,当对这个money设置值时调用setMoney,当获取值时调用getMoney
money = property(getMoney, setMoney)
a = Money()
a.money = 100 # 调用setMoney方法
print(a.money) # 调用getMoney方法
#100
4.3 使用property取代传统的getter和setter方法
重新实现属性的设置和读取方法,并可在此过程中加入边界判定逻辑。
class Money(object):
def __init__(self):
self.__money = 0
# 使用装饰器对money进行装饰,那么会自动添加一个叫money的属性,当调用获取money的值时,调用装饰的方法
@property
def money(self):
return self.__money
# 使用装饰器对money进行装饰,当对money设置值时,调用装饰的方法
@money.setter
def money(self, value):
if isinstance(value, int):
self.__money = value
else:
print("error:不是整型数字")
a = Money()
a.money = 100
print(a.money)
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









