惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hacker News: Front Page
P
Palo Alto Networks Blog
T
ThreatConnect
Apple Machine Learning Research
Apple Machine Learning Research
博客园_首页
T
True Tiger Recordings
P
Privacy & Cybersecurity Law Blog
B
Blog
IT之家
IT之家
Last Week in AI
Last Week in AI
F
Full Disclosure
Hacker News: Ask HN
Hacker News: Ask HN
C
Comments on: Blog
Microsoft Azure Blog
Microsoft Azure Blog
C
Cybersecurity and Infrastructure Security Agency CISA
Microsoft Security Blog
Microsoft Security Blog
博客园 - 【当耐特】
N
News and Events Feed by Topic
NISL@THU
NISL@THU
腾讯CDC
雷峰网
雷峰网
Security Latest
Security Latest
李成银的技术随笔
M
Microsoft Research Blog - Microsoft Research
L
LangChain Blog
L
Lohrmann on Cybersecurity
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Check Point Blog
Y
Y Combinator Blog
Recent Announcements
Recent Announcements
博客园 - Franky
N
News | PayPal Newsroom
V
V2EX
A
About on SuperTechFans
The Register - Security
The Register - Security
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Google Online Security Blog
Google Online Security Blog
MyScale Blog
MyScale Blog
Cisco Talos Blog
Cisco Talos Blog
Vercel News
Vercel News
WordPress大学
WordPress大学
C
Cyber Attacks, Cyber Crime and Cyber Security
The Hacker News
The Hacker News
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
爱范儿
爱范儿
A
Arctic Wolf
L
LINUX DO - 最新话题
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

博客园 - 遥月

畅网n100 dc版本 黑群晖风扇转速问题 黑群晖7.x ame半洗白加激活补丁 win10/11 系统频繁重启,bcd错误或丢失 jellyfine-code1008播放器无法实例化错误、群晖系统分区空间不足解决办法 为什么nas上不用joplin而用trilium笔记? 国内dockerhub镜像2025.3.5 Docker+Gunicorn+Flask部署项目(转载) 群晖用软连接替换掉自带低版本python 群晖安装pip包管理器 docker save和docker export的区别 群晖套件正在开始...... jellyfine套件登录忘记密码 用vb6拖拽生成tkinter界面 python 打包exe文件 群晖虚拟window系统,远程连接3389 群晖虚拟openwrt做旁路由 黑群晖改造清单 windows下写sh脚本, 在linux下执行乱报错的问题 群晖drive的文件和目录挂载软链接问题,如何一个目录多头管理 拒绝算法推荐,使用rss订阅消息与新闻!订阅源推荐! 群晖docker-compose简单应用搭建zblog+mysql博客系统
python装饰器详解
遥月 · 2024-12-16 · via 博客园 - 遥月

一、函数装饰器,装饰函数

 #上面是装饰器,下面是原函数   
def ifren(p):    #p是额外带来的参数,因为要带参数p所以多了一层函数嵌套,如果需要给装饰器本身传递参数,可以使用一个外层函数来封装装饰器。
    def plusnihao(function):
    
        def wraper():  #核心装饰器代码,function代指sayhello函数,是由上一层传入进来的,本层负责增加前后功能
            function()
            print("and nihao")  #添加的功能
            print(p)             #最上层传入进来的,是额外带进来的参数

        return wraper      #返回核心装饰器
    return plusnihao       #因为有参数p,再给核心装饰器装一层皮 返回
     
@ifren(1000)               #额外的参数p。 @后面是装饰器函数名   这句话相当于 ifren(1000)(plusnihao(wraper(sayhello)))
def sayhello():
    print("nihao")

sayhello()           #用原函数运行

再一例子

def decorator(func):
    def wrapper(*args, **kwargs):  # 参数必须和func一样,这样写全能
        # 在这里添加额外的功能
        print("Before calling the function")
        result = func(*args, **kwargs)   #以前什么参数,现在原样执行
        print("After calling the function")
        return result  # 有没有返回不重要

    return wrapper


@decorator
def my_function(a=5, b="fgh"):
    print(f"Hello{a}, this is my {b} function.")


# 调用my_function时,实际上调用的是wrapper函数
my_function()
# 使用functools.wraps保留原函数信息
# 在使用装饰器时,原函数的元信息(如函数名、文档字符串等)会被包装函数所替代。为了保留这些信息,可以使用functools.wraps装饰器。

from functools import wraps

def my_decorator(func):
    @wraps(func)   #这个地方保留
    def wrapper(*args, **kwargs):
        print("Something is happening before the function is called.")
        result = func(*args, **kwargs)
        print("Something is happening after the function is called.")
        return result

    return wrapper

@my_decorator
def example():
    """This is an example function."""
    print("Hello from a function.")

print(example.__doc__)  # 输出: This is an example function.

 二、类装饰器,装饰函数

# author:baoshan
# 带参数的类装饰器,和不带参数的类装饰器有很大的不同
# 类装饰器的实现,必须实现__call__和__init__两个内置函数。
# __init__:装饰器带参数时不再接收被装饰函数,而是接收传入参数;没带参数时接受函数为构造函数
# __call__:带参数时接收被装饰函数,再起一层wrapper。不带参数时接受参数*args, **kwargs参数,这时他就是wrapper。

例子:不带参数


from functools import wraps 

class animal:
    def __init__(self, func): #原函数变为类的构造函数
        self.func = func

    # @wraps  保留函数元信息
    def __call__(self, *args, **kwargs):#在Python中,__call__是一个特殊方法,
        #它允许一个类的实例表现得像函数一样,可以被调用。当你调用一个类的实例时,Python会自动执行该实例的__call__方法
        print("working here")
        res = self.func(*args, **kwargs)
        return res


@animal    #类装饰器装饰函数,函数就变为了类的构造函数
def test(name, kind):
    word = f"{name} belongs to {kind}"
    return word


A = test("cow", "mammals")
print(type(test))
print(A)

例子:带参数

class animals:
    def __init__(self, prefix):
        self.prefix = prefix  # 装饰器传入的参数变为类的属性

    def __call__(self, func):  # 原传入函数在call函数传入,再起一层wraooer
        def wrapper(*args, **kwds):  # 核心装饰器,参数用通用的这个格式
            print("前置功能" + self.prefix)
            print(func(*args, **kwds))
            print("后置功能")

        return wrapper


@animals("汪汪叫")
def cat(c):
    print(f"叫声是{c}")


cat("喵喵叫")