Python中的@property和decorator

初次认识decorator和@property

Welcome. 在本文中,将详细学习如何使用Python中的decorator和@property。

将会学习的内容:

  • 使用decorator的优势。
  • 使用@property的优势。
  • 装饰器函数的基础知识:它们是什么以及如何与@property关联起来。
  • 如何使用@property定义getter、setter和deleter。

Python中decorator的优势

  • 在不确定其他代码块对现有函数的调用,不改变现有函数,保证代码可靠稳定,避免修改现有函数所引发的潜在问题。
  • 拓展原来函数功能。

Python中@property的优势

property可以视为使用属性的“Pythonic”方式,因为:

  • 用于定义property的语法简洁易读。
  • 可以完全地访问实例属性,就像是公共属性一样。
  • 通过使用@property,可以重复使用property的名字,以避免为getter、setter和deleter创建新名字。

装饰器简介

装饰器函数(decorator function)是一个函数,它能给现有的函数(此“现有的函数”作为参数传递)添加新功能。使用装饰器函数就像是给冰淇淋(代指另一个函数)添加少量的巧克力(代指新功能)。即给现有的函数添加新功能,并且不对现有的函数进行任何更新修改。

 1 def decorator(func):
 2     print("在装饰器函数内部,修饰:", func.__name__)
 3     def new_function():
 4         print("新增功能,随后执行的函数为:", func.__name__)
 5         func()
 6     return new_function
 7 
 8 @decorator
 9 def initial_function():
10     print("现有函数功能")
11     
12 initial_function()

输出结果为:

在装饰器函数内部,修饰: initial_function
新增功能,随后执行的函数为: initial_function
现有函数功能

在不使用装饰器函数时,实现以上功能的代码如下所示:

 1 def decorator(func):
 2     print("在装饰器函数内部,修饰:", func.__name__)
 3     def new_function():
 4         print("新增功能,随后执行的函数为:", func.__name__)
 5         func()
 6     return new_function
 7 
 8 
 9 def initial_function():
10     print("现有函数功能")
11     
12 initial_function = decorator(initial_function)
13 initial_function()

这两段代码,实现功能是相同的。装饰器是替代上述代码initial_function = decorator(initial_function)的语法糖,只增加一行代码就可以将现有函数包装到装饰器函数内。

对比两种实现方案,装饰器@decorator就可以理解为替换initial_function = decorator(initial_function)这条语句的实现。

装饰器更加简洁,有两部分组成:先定义用于包装或“装饰”其他函数的装饰器函数;然后立即在被包装函数的定义前面,加上“@”和装饰器函数名。这里的装饰器函数应该以一个函数为形参,返回值也是一个函数。

@property的实际应用

定义一个House类(该类仅定义了实例属性price)。通过House类创建一个house实例

1  class House:
2      def __init__(self, price):
3          self.price = price
4  
5  house = House()

这个实例属性price是公有的,因此可以使用点标记法直接访问和修改属性值。

1 # Access value
2 house.price
3 
4 # Modify value
5 house.price = 40000

然而,通常我们并不希望用户能直接访问和修改属性值,因此将实例属性设置为私有的,并采用getter和setter方法间接访问和修改私有的实例属性,更新后的代码如下:

class House:
    def __init__(self, price):
        self.__price = price

    def get_price(self):
        return self.__price

    def set_price(self, new_price):
        self.__price = new_price

之前访问该实例属性的代码均需要修改,对应的客户端也需要进行代码修改:

1 # Changed from house.price
2 house.get_price()
3 
4 # Changed from house.price = 40000
5 house.set_price(40000)

为了应对以上的情况,@property应运而生,解决了当时直接使用实例属性的代码重构问题。

 1 class House:
 2     def __init__(self, price):
 3         self.__price = price
 4     
 5     @property
 6     def price(self):
 7         return self.__price
 8     
 9     @price.setter
10     def price(self, new_price):
11         if new_price > 0 and isinstance(new_price, float):
12             self.__price = new_price
13         else:
14             print("Please enter a valid price")
15             
16     @price.deleter
17     def price(self):
18         del self.__price

此时,就可以像之前一样访问实例属性。即初始开发时可以采用传统的实例属性,以后可以根据需要随时随地无缝切换为属性,客户端代码则无须改动。

getter

1 house = House(50000.0) # Create instance
2 print(house.price)     # Access value

输出结果为:

50000.0

setter

1 house = House(50000.0)    # Create instance
2 house.price = 88888.0     # Update value
3 print(house.price)

输出结果为:

88888.0

deleter

1 # Delete the instance attribute
2 del house.price
3 
4 # The instance sttribute doesn't exist
5 print(house.price)

输出结果为:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-13-dd54e9ad0090> in <module>
      1 # The instance sttribute doesn't exist
----> 2 print(house.price)

<ipython-input-8-5e2f43c64399> in price(self)
      5     @property
      6     def price(self):
----> 7         return self.__price
      8 
      9     @price.setter

AttributeError: 'House' object has no attribute '_House__price'

总结

  • 使用decorator和@property可以使得Python代码简洁易读。
  • @property可以被视为定义getter、setter和deleter的"pythonic"方式。
  • 在不影响程序的前提下修改类的内部实现,从而避免直接对数据的访问和修改。

参考文献

  1. https://www.freecodecamp.org/news/python-property-decorator/
  2. 《Python快速入门》(第三版)

猜你喜欢

转载自www.cnblogs.com/qiuhuachuan/p/12118940.html