Python 里的三种特殊方法修饰器—@classmethod(类方法)、@staticmethod(静态方法)、@property(属性装饰器)
Python 里的三种特殊方法修饰器:
-
@classmethod(类方法)
- 作用:类方法属于类,而不是实例。它们的第一个参数是类本身 (
cls
),而不是实例 (self
)。 - 适用场景:通常用于创建对象的工厂方法或者需要访问类级别的数据的方法。
- 代码示例:
import random class Duck: def __init__(self, color): self.color = color def quack(self): print(f"Hi, I'm a {self.color} duck!") @classmethod def create_random(cls): """创建一只随机颜色的鸭子""" color = random.choice(['yellow', 'white', 'gray']) return cls(color) # 直接用类调用类方法创建对象 d = Duck.create_random() d.quack() # 可能输出 "Hi, I'm a white duck!"
-
@staticmethod(静态方法)
- 作用:静态方法和普通函数类似,但属于类的命名空间,不需要访问实例 (
self
) 或类 (cls
)。 - 适用场景:当方法不涉及类或实例的属性,但仍然和类逻辑相关时(比如工具方法)。
- 代码示例:
import random class Cat: def __init__(self, name): self.name = name def say(self): sound = self.get_sound() print(f'{self.name}: {sound}...') @staticmethod def get_sound(): """生成一段随机喵叫""" repeats = random.randint(1, 5) return ' '.join(['Meow'] * repeats) # 既可以用实例调用静态方法 c = Cat('Jack') c.say() # 可能输出 "Jack: Meow Meow Meow..." # 也可以用类调用静态方法 print(Cat.get_sound()) # 可能输出 "Meow Meow Meow"
-
@property(属性装饰器)
- 作用:把一个方法变成“像属性一样访问”的东西,避免用
obj.method()
形式调用,而是obj.attr
直接访问。 - 适用场景:当某个值需要计算,但又希望用类似属性的方式访问它,比如获取文件名、计算面积等。
- 代码示例:
import os class FilePath: def __init__(self, path): self.path = path @property def basename(self): """获取文件名""" return os.path.basename(self.path) @basename.setter def basename(self, new_name): """修改当前路径里的文件名部分""" dir_path = os.path.dirname(self.path) self.path = os.path.join(dir_path, new_name) @basename.deleter def basename(self): raise RuntimeError("文件名不能被删除!") # 使用属性访问方式获取文件名 p = FilePath('/tmp/foo.py') print(p.basename) # 输出: foo.py # 使用属性方式修改文件名 p.basename = 'bar.txt' print(p.path) # 输出: /tmp/bar.txt # 试图删除属性会报错 del p.basename # RuntimeError: 文件名不能被删除!
关于 @property
的额外说明
@property
适用于那些计算代价较小的属性。@property
,如果方法的执行成本较高(比如涉及网络请求或复杂计算),还是用普通方法更合适。@property
):
import time
class WebScraper:
@property
def latest_news(self):
"""假设这个方法每次执行都要爬取新闻,可能需要 5-10 秒"""
time.sleep(5) # 模拟网络延迟
return ["News1", "News2", "News3"]
s = WebScraper()
print(s.latest_news) # 这会卡 5 秒,用户可能误以为读取属性很快
正确做法:
class WebScraper:
def get_latest_news(self):
"""提供一个普通方法,而不是属性"""
time.sleep(5) # 模拟网络延迟
return ["News1", "News2", "News3"]
s = WebScraper()
print(s.get_latest_news()) # 这样更符合用户预期
总结
@classmethod
:用于操作类本身,常用于创建新对象(工厂方法)。@staticmethod
:和类有关,但不依赖实例或类数据,类似工具函数。@property
:让方法像属性一样访问,适用于快速计算的值,不适合耗时操作。作者:背太阳的牧羊人