【Python】基本语法:装饰器语法糖@

1、什么是装饰器?

装饰器就是:动态地给一个现有对象或函数附加额外功能,同时又不修改原有类或函数的源代码、不通过继承扩展子类。

和继承的区别:

  • 继承是静态绑定:编译期就确定好了功能,运行时无法随时增删功能;
  • 装饰器模式:运行时动态给对象叠加 / 移除功能;
  • 如果依靠类继承扩展功能:每增加一种功能就要新建一个子类,功能组合一多,子类会爆炸式增多

2、Python装饰器

Python中的装饰器:一般是用于包装函数,函数式编程思想;

Python使用@符号,标记装饰器,是 Python 语法糖,在不修改原函数代码的前提下,给函数增加额外功能,比如:异常捕获、计时、日志、权限校验等。

2.1 异常捕获+日志

异常捕获装饰器:给被修饰的函数,添加捕获异常功能,并将异常记录到日志中;

防止因为没有处理被装饰的函数的异常,而导致崩溃;

python 复制代码
def safe_wrapper(logger=None , default = None):
    def outer(func):
        def inner(*args, **kwargs):
            try:
                return func(*args, **kwargs)
            except Exception as e:
                if logger : logger.exception(f"{func.__doc__}失败 : {e}")
                return default
        return inner
    return outer

1)第一层safe_wrapper:接收两个参数:日志对象、出错要返回的默认值;

2)第二层outer:标准装饰器入口,接收要被包装的函数 func;

3)第三层inner:真正替换原函数的内层函数,原函数所有参数传递给 *args **kwargs;

4)第四层 try-except:将原函数包装到异常处理中;

5)第五层func:执行原函数,返回执行结果;

用法:

python 复制代码
import logging
logging.basicConfig(level=logging.INFO)
log = logging.getLogger()

@safe_wrapper(logger=log, default=None)
def div(a, b):
    return a / b

print(div(10, 0))

捕获除零异常,不会崩溃,返回None,并打印异常日志

2.2 不使用语法糖

如果不使用Python的语法糖@,等同于使用下面的方式执行:div(10, 0)

python 复制代码
def div(a, b):
    return a / b
    
outer = safe_wrapper(logger=log, default=None)
inner = outer(div)
inner(10, 0)

2.3 统计函数运行时间

python 复制代码
import time

def timer(func):
    def wrap(*args, **kwargs):
        start = time.time()
        res = func(*args, **kwargs)
        print(f"耗时:{time.time()-start:.2f}s")
        return res
    return wrap

@timer
def calc():
    sum(range(1000000))

calc()

3、内置装饰器

3.1 @property 函数当变量

把类的函数伪装成实例变量(属性):

  • 调用函数使用:class.fun();
  • 伪装成变量后:class.fun;
  • 默认不能赋值,添加setter修饰后,可以赋值;
python 复制代码
class Person:
    def __init__(self, birth_year):
        self.birth_year = birth_year
        self._age=0
        self._set=False
    @property
    def age(self):
        if(self._set):
            return self._age
        else:
            return 2026 - self.birth_year
    @age.setter
    def age(self, val):
          self._age = val
          self._set = True

3.2 @staticmethod 静态函数

和C++一样:静态函数属于类,不用实例化类也可以直接调用的函数;

注意:静态函数中,不能调用非静态的函数和变量(实例属性);但是可以访问类属性

python 复制代码
class Tools:
    @staticmethod
    def add(a, b):
        return a + b

调用时,直接用类调用,不用创建对象也能调用

复制代码
print(Tools.add(1, 2))

3.3 @classmethod 类函数

类函数 和 静态函数类似;区别如下:

  • 类函数支持继承重写,静态函数不能;
  • 类函数的第一个参数表示类本身,子类调用时,该参数自动变成子类;
python 复制代码
class Tool:
    PI = 3.14159
    @staticmethod
    def static_pi():
        return Tool.PI
    @classmethod
    def class_pi(cls):
        return cls.PI

class NewTool(Tool):
    PI = 3.14

print(NewTool.static_pi())

输出,依然是父类的Tool值,static_pi中写死了 Tool.PI:

复制代码
3.14159  

print(NewTool.class_pi())

输出,是子类NewTool自己的PI:

复制代码
3.14     
  • 静态函数:函数逻辑完全独立,既不调用类变量,也不调用实例变量,仅仅是把函数归类放到类中管理
  • 类函数:需要调用类属性,例如:常用于工厂方法模式中,根据不同参数,创建类的实例

4、类属性和实例属性

C++中的成员变量,在Python中称为属性

类属性(类似C++中,静态成员变量)

  • 写在 class 内部、__init__ 外面,属于整个类本;
  • 所有实例共享同一份类属性;
  • 可以通过类直接访问,也可以通过实例对象来访问;

实例属性(类似C++中,非静态成员变量)

  • 在构造方法 __init__(self) 里通过 self.xxx 定义,只属于每一个单独的对象实例;
  • 每个对象互相独立,修改互不影响;
  • 只能通过实例对象访问,类无法直接访问;

可以通过 __dict__,来打印所有的属性字典

python 复制代码
class Student:
    school = "河北石油大学"
    def __init__(self, name, age):
        self.name = name
        self.age = age 
        
laoer = Student("laoer", 28)
print(laoer.__dict__)
print(Student.__dict__)
相关推荐
杨杨杨大侠5 小时前
Jev、Kev、Laya:决策模型怎么选,什么时候需要微调?
人工智能·python·agent
LOVE️YOU6 小时前
Python 在定义函数时,究竟定义的是什么?
python
段一凡-华北理工大学6 小时前
大模型应用开发 100 天:Python + LLM 从入门到精通 day26~Prompt 调试与优化——A/B 测试与效果评估
windows·python·大模型·prompt·智能体·提示词工程·高炉智能化
Minecraft红客6 小时前
以撒的结合
python·游戏·电脑·娱乐
Circ.6 小时前
Python 调试 Litellm 本地大模型接口:模型列表与对话接口实操踩坑记录
开发语言·python
风早爽太7 小时前
用 ‌Render‌ 快速部署网站和常见问题解决
python·fastapi
李航19838 小时前
给自己的图形引擎,配上了AI渲染,做设计真是太方便了
人工智能·python·计算机视觉·ai·ai编程
L@ncor8 小时前
第六章 框架开发实践 · 学习笔记(AutoGen / AgentScope / CAMEL / LangGraph)
python·框架·autogen·langgraph·agentscope
Zhou1411368 小时前
SpringSecurity_02_授权与高级功能
开发语言·python
摇滚侠10 小时前
《On Java 中文版 基础卷》阅读笔记 对象无处不在 03
java·笔记·python