前端开发入门到精通的在线学习网站

网站首页 > 资源文章 正文

巧用Python 中的装饰器,将代码减半

qiguaw 2025-03-12 19:55:46 资源文章 42 ℃ 0 评论

Python 是一种流行且用途广泛的编程语言,它提供了许多功能和库,使编码更容易、更快捷。其中一个功能是装饰器,它是一种可以在不更改原始代码的情况下修改或增强其他功能的功能。装饰器可以帮助您将代码减半,使其更易于阅读、重用和维护。

@Property

@property装饰器允许您在类中定义属性,这些属性具有 getter 和 setter 方法。属性可以帮助您控制属性的访问和修改方式,并避免编写重复代码。

例如,假设有一个表示圆的类,并且您希望根据半径计算其面积和周长。如果不使用该属性,您将编写如下内容:

class Circle:
 def __init__(self, radius):
 self.radius = radius
def get_area(self):
 return 3.14 * self.radius ** 2
def set_area(self, area):
 self.radius = (area / 3.14) ** 0.5
def get_circumference(self):
 return 2 * 3.14 * self.radius
def set_circumference(self, circumference):
 self.radius = circumference / (2 * 3.14)

正如你所看到的,代码很长而且重复。需要写下四种查找和确定圆的面积和周长的方法,每种方法都需要根据半径进行计算。使用属性,可以将此代码简化一半:

class Circle:
 def __init__(self, radius):
 self.radius = radius
@property
 def area(self):
 return 3.14 * self.radius ** 2
@area.setter
 def area(self, area):
 self.radius = (area / 3.14) ** 0.5
@property
 def circumference(self):
 return 2 * 3.14 * self.radius
@circumference.setter
 def circumference(self, circumference):
 self.radius = circumference / (2 * 3.14)

现在,所要做的就是编写两个方法将面积和周长定义为属性,并使用 @property 和 @setter 装饰器来标记它们。然后,可以访问和修改此属性,就好像它是常规属性一样:

c = Circle(5)
print(c.area) # 78.5
print(c.circumference) # 31.4
c.area = 50
print(c.radius) # 3.99
c.circumference = 20
print(c.radius) # 3.18

@staticmethod和@classmethod

@staticmethod 和 @classmethod 修饰器允许您在类中定义静态方法和类方法,这些方法独立于实例或对象类。静态方法和类方法可以帮助您更好地组织代码,并避免创建不必要的实例或传递冗余参数。

例如,假设有一个表示计算器的类,并且想要定义一些基本运算,例如加法、减法、乘法和除法。在不使用静态方法或类方法的情况下,必须编写如下内容:

class Calculator:
 def __init__(self):
 pass
def add(self, x, y):
 return x + y
def subtract(self, x, y):
 return x — y
def multiply(self, x, y):
 return x * y
def divide(self, x, y):
 return x / y

正如你所看到的,这段代码是非常不必要和低效的。每次要执行操作时,都必须实例化 calculator 类,即使该操作完全独立于实例也是如此。还必须为每个操作提供两个参数,即使它们与类无关。

使用静态方法或类方法,可以将此代码减少到两个:

class Calculator:
 @staticmethod
 def add(x, y):
 return x + y
@staticmethod
 def subtract(x, y):
 return x — y
@staticmethod
 def multiply(x, y):
 return x * y
@classmethod
 def divide(cls, x, y):
 return x / y

现在,只需要使用 @staticmethod 或 @classmethod 装饰器将方法标记为静态或类方法。然后,您可以直接从类调用此方法,而无需实例化类或将类作为参数传递:

print(Calculator.add(2, 3)) # 5
print(Calculator.subtract(5, 2)) # 3
print(Calculator.multiply(3, 4)) # 12
print(Calculator.divide(10, 2)) # 5

@functools.lru_cache

@functools.lru_cache 装饰器是一个内置的装饰器,允许您缓存函数的结果,即为相同的输入返回相同输出的函数。缓存可以帮助您提高代码的性能和效率,尤其是对于递归函数或成本高昂的函数。

例如,假设有一个计算第 n 个斐波那契数的函数,该数列是一个数字序列,其中每个数字是前两个数字的总和。如果不使用缓存,必须写这样的东西:

def fib(n):
 if n < 2:
 return n
 else:
 return fib(n-1) + fib(n-2)

正如你所看到的,这段代码非常缓慢和浪费。必须对每个数字以递归方式调用该函数,并且每次调用都必须一遍又一遍地进行相同的计算。

使用缓存,可以将此代码简化一半:

from functools import lru_cache
@lru_cache(maxsize=None)
def fib(n):
 if n < 2:
 return n
 else:
 return fib(n-1) + fib(n-2)

现在,只需要使用 @functools.lru_cache 装饰器将函数标记为可缓存。还可以指定 maxsize 参数来限制缓存大小,或将其保留为 None 以使用无限制的缓存。然后,您可以像往常一样调用该函数,但结果要快得多:

print(fib(10)) # 55
print(fib(20)) # 6765
print(fib(30)) # 832040

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表