Python Property属性详解:从原理到实战应用

陆景行
陆景行
发布时间:2026-10-13 | 4人浏览过
原创

本文深入解析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)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表