打卡第三十天:类的装饰器

知识点回顾
1.类的装饰器
2.装饰器思想的进一步理解:外部修改、动态
3.类方法的定义:内部定义和外部定义

作业:复习类和函数的知识点,写下自己过去29天的学习心得,如对函数和类的理解,对python这门工具的理解等,未来再过几个专题部分我们即将开启深度学习部分。

辨别类与函数的方法

类和函数在编程中具有不同的结构和用途,可以通过以下特征进行区分。

定义方式

函数通常使用 def 关键字定义,而类使用 class 关键字定义。函数的定义更简单,仅包含名称和参数列表;类的定义包含名称、属性和方法。

# 函数的定义
def greet(name):
    return f"Hello, {name}"

# 类的定义
class Person:
    def __init__(self, name):
        self.name = name

    def greet(self):
        return f"Hello, {self.name}"

调用方式

函数可以直接调用,而类通常需要实例化后才能调用其方法。函数调用仅需传递参数,而类的方法调用需要通过实例对象。

# 函数调用
print(greet("Alice"))  # 输出: Hello, Alice

# 类调用
person = Person("Bob")
print(person.greet())  # 输出: Hello, Bob

内部结构

类可以包含多个方法(函数)和属性(变量),而函数仅包含一段独立的代码逻辑。类的方法通常通过 self 访问实例属性,函数则直接操作传入的参数。

# 函数内部结构
def add(a, b):
    return a + b

# 类内部结构
class Calculator:
    def __init__(self):
        self.result = 0

    def add(self, a, b):
        self.result = a + b
        return self.result

状态管理

类可以维护状态(通过属性),函数是无状态的。类的实例可以保存数据,而函数每次调用都是独立的。

# 无状态的函数
def increment(x):
    return x + 1

# 有状态的类
class Counter:
    def __init__(self):
        self.value = 0

    def increment(self):
        self.value += 1
        return self.value

继承与多态

类支持继承和多态,函数不支持。类可以通过继承扩展功能,函数无法直接继承其他函数。

# 类的继承
class Animal:
    def speak(self):
        pass

class Dog(Animal):
    def speak(self):
        return "Woof!"

# 函数无法继承

命名约定

类的名称通常采用驼峰命名法(如 MyClass),而函数名称通常采用小写和下划线(如 my_function)。

# 函数命名
def calculate_total():
    pass

# 类命名
class ShoppingCart:
    pass

通过以上特征,可以清晰地区分类和函数。

函数修饰器与类修饰器的区别

作用对象不同

函数修饰器用于修饰函数或方法,在函数定义时通过@decorator语法对目标函数进行包装。类修饰器用于修饰类定义,通过相同语法对类进行动态修改或扩展。

# 函数修饰器示例
def log_func(func):
    def wrapper(*args, **kwargs):
        print(f"Calling {func.__name__}")
        return func(*args, **kwargs)
    return wrapper

@log_func
def greet():
    print("Hello")

# 类修饰器示例
def add_method(cls):
    def new_method(self):
        return "Added method"
    cls.new_method = new_method
    return cls

@add_method
class MyClass:
    pass

实现机制差异

函数修饰器通常返回一个新函数(闭包),替换原函数的执行逻辑。类修饰器可以返回修改后的类,或完全替换为新的类实现。

# 函数修饰器实现
def timer(func):
    import time
    def wrapped(*args):
        start = time.time()
        result = func(*args)
        print(f"Time taken: {time.time()-start}s")
        return result
    return wrapped

# 类修饰器实现
def singleton(cls):
    instances = {}
    def get_instance(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    return get_instance

应用场景不同

函数修饰器常用于日志记录、权限验证、性能测试等横切关注点。类修饰器常用于单例模式、类属性修改、接口注册等类级别的操作。

# 函数修饰器应用
@login_required
def delete_item():
    pass

# 类修饰器应用
@dataclass
class Point:
    x: int
    y: int

参数处理方式

函数修饰器的参数默认接收函数对象,类修饰器的参数默认接收类对象。两者都支持带参数的修饰器模式,但参数传递层级不同。

# 带参数的函数修饰器
def repeat(n):
    def decorator(func):
        def wrapper(*args):
            for _ in range(n):
                func(*args)
        return wrapper
    return decorator

# 带参数的类修饰器 
def add_attributes(**kwargs):
    def decorator(cls):
        for k, v in kwargs.items():
            setattr(cls, k, v)
        return cls
    return decorator

执行时机差异

函数修饰器在函数定义时立即执行,但包装函数在被调用时才执行。类修饰器在类定义时立即执行,通常会修改类的元信息或行为。

# 函数修饰器执行顺序
@decorator1
@decorator2
def func(): pass
# 等价于 decorator1(decorator2(func))

# 类修饰器执行顺序
@decoratorA
@decoratorB
class C: pass
# 等价于 decoratorA(decoratorB(C))

@浙大疏锦行

你可能感兴趣的:(python,机器学习)