四十四.python装饰器@方法的使用

使用装饰器的目的是为了减少代码的修改量以及提高代码的可读性和可维护性。

先来看一个基本的函数定义:

#python2.7
def add(x,y):
    return "%d+%d=%d" %(x,y,x+y)

def sub(a,b):
    return "%d-%d=%d" %(a,b,a-b)
print add(2,1)
print sub(2,1)

打印结果为:

那么假设我需要在该函数里加入分割线显得更好看,一般是这样写:

#coding:utf-8
def add(x,y):
    print "==================="
    return "%d+%d=%d" %(x,y,x+y)

def sub(a,b):
    print "==================="
    return "%d-%d=%d" %(a,b,a-b)
print add(2,1)
print sub(2,1)

打印结果为:

那假设基本的那个函数定义老板不允许你进行修改,还要实现以上的效果,请参考以下代码:

#coding:utf-8
def add(x,y):
    return "%d+%d=%d" %(x,y,x+y)

def sub(a,b):
    return "%d-%d=%d" %(a,b,a-b)

def fgx(func):
    print "==================="
    return func
print fgx(add(2,1))
print fgx(sub(2,1))

打印结果为:

上面代码多加了一个函数,而这个函数的方法是打印分割线,参数是一个函数,而返回是返回函数,则可以直接使用fgx(函数的方法)。看不懂 def fgx(func): 这个的请参考四十一高阶函数写法。

那以上的方法的话,还是需要改调用函数的方法,那样如果有100个或是更多的函数时还是需要改100次或是1000次几个调用函数的方法,那么这时怎么处理呢?请参考以下代码:尝试使用@装饰器写法改为:

#coding:utf-8
def fgx(func):
    print "==================="
    return func
@fgx
def add(x,y):
    return "%d+%d=%d" %(x,y,x+y)
@fgx
def sub(a,b):
    return "%d-%d=%d" %(a,b,a-b)

print add(2,1)
print sub(2,1)

返回结果为:(而这个不是我们要的效果,那么还是需要继续修改。)

 

修改为:

#coding:utf-8
def fgx(func):
    def f(*num):
        print "==================="
        return func(*num)
    return f
@fgx
def add(x,y):
    return "%d+%d=%d" %(x,y,x+y)
@fgx
def sub(a,b):
    return "%d-%d=%d" %(a,b,a-b)

print add(2,1)
print sub(2,1)

返回结果:

理解代码:

第一个@fgx生效时,会执行函数 fgx(add(x,y)) ,而fgx(func)函数return是内部函数f,则会执行f(*num),按顺序先执行print,再接着执行func(*num),这里的func(*num) = add(x,y),则会执行def add(x,y)的函数,而add(x,y)函数return就是x+y的值。

第二个@fgx生效同理。

<think>我们正在讨论Python中的@classmethod装饰器。根据用户的问题,他们想了解这个装饰器的作用和使用方法。根据引用,我们知道: - @classmethod用于定义类方法,该方法绑定到类而非实例(引用[1]) - 类方法的第一个参数是类本身,通常命名为cls(引用[2]) - 类方法可以访问类变量,但不能访问实例变量(因为不依赖于实例) - 类方法常用于创建工厂方法,用于创建类的实例(引用[3]) 现在,我们将按照用户要求的结构化方式回答,并生成相关问题。 注意:在回答中,我们将使用中文,并确保数学表达式(如果有)按照系统指令格式化。由于本问题不涉及数学公式,我们主要关注代码示例和解释。</think>### Python @classmethod 装饰器详解 #### 一、核心作用 1. **创建类方法**:将普通方法转换为类方法,使其**绑定到类本身**而非实例(引用[2]) ```python class MyClass: @classmethod def class_method(cls): # cls 自动接收类本身 return cls.__name__ ``` 2. **访问类级属性**:通过 `cls` 参数直接访问类变量(引用[4]) ```python class Counter: count = 0 @classmethod def increment(cls): cls.count += 1 # 修改类级变量 ``` 3. **替代构造函数**:实现多种对象创建方式(工厂模式) ```python class Date: def __init__(self, year, month, day): self.year = year self.month = month self.day = day @classmethod def from_string(cls, date_str): # 替代构造函数 year, month, day = map(int, date_str.split('-')) return cls(year, month, day) # 创建新实例 ``` #### 二、与实例方法对比 | 特性 | 类方法 (`@classmethod`) | 实例方法 | |--------------|------------------------------|-------------------| | 第一个参数 | `cls` (类对象) | `self` (实例对象) | | 调用方式 | 类名直接调用 `MyClass.method()` | 需实例化后调用 | | 访问权限 | 仅访问类属性 | 可访问实例属性 | | 内存占用 | 类加载时创建,单份存在 | 每实例独立存在 | #### 三、典型使用场景 1. **工厂模式**(引用[3]) ```python class Car: def __init__(self, model): self.model = model @classmethod def electric_car(cls): return cls("Tesla Model 3") # 创建特定类型实例 ``` 2. **类状态管理** ```python class Config: _settings = {} @classmethod def set_config(cls, key, value): cls._settings[key] = value ``` 3. **继承场景多态**(引用[5]) ```python class Parent: @classmethod def create(cls): return cls() # 子类调用时返回子类实例 class Child(Parent): pass obj = Child.create() # 返回Child实例而非Parent ``` #### 四、与@staticmethod区别 - `@classmethod` 接收 `cls` 参数,可访问/修改类状态 - `@staticmethod` 无隐式参数,相当于普通函数(引用[3]) ```python class Utilities: @staticmethod def validate_email(email): # 无需访问类/实例 return "@" in email ``` > **最佳实践**:当方法需要访问类属性或创建类实例时使用 `@classmethod`;当方法独立于类状态时用 `@staticmethod`(引用[3])
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值