Python 里的三种特殊方法修饰器—@classmethod(类方法)、@staticmethod(静态方法)、@property(属性装饰器)

Python 里的三种特殊方法修饰器:

  1. @classmethod(类方法)

  2. 作用:类方法属于类,而不是实例。它们的第一个参数是类本身 (cls),而不是实例 (self)。
  3. 适用场景:通常用于创建对象的工厂方法或者需要访问类级别的数据的方法。
  4. 代码示例
    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!"
    
  5. @staticmethod(静态方法)

  6. 作用:静态方法和普通函数类似,但属于类的命名空间,不需要访问实例 (self) 或类 (cls)。
  7. 适用场景:当方法不涉及类或实例的属性,但仍然和类逻辑相关时(比如工具方法)。
  8. 代码示例
    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"
    
  9. @property(属性装饰器)

  10. 作用:把一个方法变成“像属性一样访问”的东西,避免用 obj.method() 形式调用,而是 obj.attr 直接访问。
  11. 适用场景:当某个值需要计算,但又希望用类似属性的方式访问它,比如获取文件名、计算面积等。
  12. 代码示例
    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:让方法像属性一样访问,适用于快速计算的值,不适合耗时操作。
  • 作者:背太阳的牧羊人

    物联沃分享整理
    物联沃-IOTWORD物联网 » Python 里的三种特殊方法修饰器—@classmethod(类方法)、@staticmethod(静态方法)、@property(属性装饰器)

    发表回复