Python武器库开发-高级特性篇(七)

news2024/11/18 22:29:56

高级特性篇(七)

装饰器

装饰器是给现有的模块增添新的小功能,可以对原函数进行功能扩展,而且还不需要修改原函数的内容,也不需要修改原函数的调用。这也称为元编程,因为程序的一部分试图在编译时修改程序的另一部分。Python中的所有内容都是对象。我们定义的名称只是绑定到这些对象的标识符。函数也不例外,它们也是对象(带有属性)。可以将各种不同的名称绑定到同一功能对象。

def first(msg):
    print(msg)    

first("Hello")

second = first
second("Hello")

当你运行代码时,这两个函数first和second给出相同的输出。在此,名称first和second指代相同的功能对象:

在这里插入图片描述

现在情况是不是感觉变复杂了点,可以将函数作为参数传递给另一个函数。这种以其他函数为参数的函数也称为高阶函数。这是这种函数的一个实例。

def inc(x):
    return x + 1

def dec(x):
    return x - 1

def operate(func, x):
    result = func(x)
    return result

print(operate(inc,3))
print(operate(dec,3))

程序的输出结果如下:

在这里插入图片描述

函数和方法被称为可调用的,因为它们可以被调用。

实际上,任何实现特殊方法__call __()的对象都称为可调用的。 因此,从最基本的意义上讲,装饰器是可调用的,可返回可调用的。

基本上,装饰器接受一个函数,添加一些功能并返回它。

def make_pretty(func):
    def inner():
        print("我被装饰了")
        func()
    return inner

def ordinary():
    print("我是普通的函数")

print(ordinary())
print("-----------------------")

pretty = make_pretty(ordinary)
print(pretty())

程序的输出结果如下:

在这里插入图片描述

在上面显示的示例中,make_pretty()是一个装饰器,pretty = make_pretty(ordinary),函数ordinary()被修饰,返回的函数被命名为pretty。这是一个常见的构造,因此,Python具有简化此语法的语法。我们可以将@符号与装饰器函数的名称一起使用,并将其放置在要装饰的函数的定义上方。例如:

def make_pretty(func):
    def inner():
        print("我被装饰了")
        func()
    return inner

@make_pretty
def ordinary():
    print("我是普通的函数")

print(ordinary())

就相当于

def make_pretty(func):
    def inner():
        print("我被装饰了")
        func()
    return inner

def ordinary():
    print("我是普通的函数")

ordinary = make_pretty(ordinary)

print(ordinary())

在Python中,我们可以通过完成的function(*args, **kwargs)。这样,args是位置参数的元组,kwargs而是关键字参数的字典。这样的装饰器的一个实例是:

def works_for_all(func):
    def inner(*args, **kwargs):
        print("我可以装饰任何函数")
        return func(*args, **kwargs)
    return inner

@works_for_all
def test():
    print("我被装饰了")


test()

程序的输出结果如下:

在这里插入图片描述

在Python中,我们还可以链接多个装饰器。一个函数可以用不同(或相同)的装饰器多次装饰。我们只需将装饰器放置在所需函数之上。

def star(func):
    def inner(*args, **kwargs):
        print("*" * 30)
        func(*args, **kwargs)
        print("*" * 30)
    return inner

def percent(func):
    def inner(*args, **kwargs):
        print("%" * 30)
        func(*args, **kwargs)
        print("%" * 30)
    return inner

@star
@percent
def printer(msg):
    print(msg)
printer("Hello")

程序的输出结果如下:

在这里插入图片描述

链接装饰器的顺序很重要。如果我们按相反的顺序

def star(func):
    def inner(*args, **kwargs):
        print("*" * 30)
        func(*args, **kwargs)
        print("*" * 30)
    return inner

def percent(func):
    def inner(*args, **kwargs):
        print("%" * 30)
        func(*args, **kwargs)
        print("%" * 30)
    return inner

@percent
@star
def printer(msg):
    print(msg)
printer("Hello")

执行的程序结果输出将如下:

在这里插入图片描述

迭代器

对于Python中的任意对象,只要它定义了可以返回一个迭代器的 _ iter_ 方法,或者定义了可以支持下标索引的 _ getitem_ 方法,那么它就是一个可迭代对象。对可迭代对象使用 _ iter_ 方法后,会返回一个迭代器。iter()函数(也就是__iter__()方法)从它们返回一个迭代器。我们使用该next()函数手动遍历迭代器的所有项目。 当我们到达末尾并且没有更多数据要返回时,它将引发StopIteration。 以下是一个示例:

# 定义一个列表
my_list = [4, 7, 0, 3]

# 使用iter()获得迭代器
my_iter = iter(my_list)

## 使用iter()获得迭代器 

#输出 4
print(next(my_iter))

#输出 7
print(next(my_iter))

## next(obj)与obj .__ next __()相同

#输出 0
print(my_iter.__next__())

#输出 3
print(my_iter.__next__())

## 这将引起错误,没有项目剩下
next(my_iter)

以上实例输出的结果如下:

在这里插入图片描述

在Python中从头开始构建迭代器很容易。我们只需要实现这些方法__iter__()和__next__()。iter()方法返回迭代器对象本身。如果需要,可以执行一些初始化。next()方法必须返回序列中的下一项。在到达终点时,以及在随后的调用中,它必须引发StopIteration。这里,我们展示了一个示例,它将在每次迭代中为我们提供2的次幂。幂指数从0到用户设置的数字:

class PowTwo:
    """实现迭代器的类
             二的幂"""

    def __init__(self, max = 0):
        self.max = max

    def __iter__(self):
        self.n = 0
        return self

    def __next__(self):
        if self.n <= self.max:
            result = 2 ** self.n
            self.n += 1
            return result
        else:
            raise StopIteration

a = PowTwo(4)
i = iter(a)

print(next(i))
print(next(i))
print(next(i))
print(next(i))
print(next(i))

以上实例输出的结果如下:

在这里插入图片描述

迭代器对象中的项不必耗尽。可能有无限的迭代器(永远不会结束)。在处理这样的迭代器时,我们必须小心。在这些类型的无限迭代器上进行迭代时,请小心包含终止条件。这是一个演示无限迭代器的简单示例:

class InfIter:
    """无限迭代器返回所有
                 奇数"""

    def __iter__(self):
        self.num = 1
        return self

    def __next__(self):
        num = self.num
        self.num += 2
        return num

a = iter(InfIter())

print(next(a))
print(next(a))
print(next(a))
print(next(a))
print(next(a))
print(next(a))
print(next(a))
print(next(a))

运行结果如下:

在这里插入图片描述

生成器

用Python构建迭代器有很多开销; 我们必须使用__iter__()和__next__()方法实现一个类,跟踪内部状态,在没有要返回的值时触发StopIteration等等。这既冗长又违反直觉。生成器在这种情况下可以派上用场。Python生成器是创建迭代器的简单方法。我们上面提到的所有开销都由Python的生成器自动处理。

简而言之,生成器是一个函数,它返回一个对象(迭代器),我们可以对其进行迭代(一次一个值)。

生成器是动态生成的,当你要迭代的对象有非常多的元素时,使用生成器能为你节约很多内存

在Python中创建生成器非常简单。 就像使用yield语句而不是return语句定义普通函数一样容易。

如果一个函数包含至少一个yield语句(它可能包含其他yield或return语句),那么它就成为一个生成器函数。yield和return都将从函数返回一些值。

不同之处在于,当return语句完全终止一个函数时,yield语句会暂停该函数保存其所有状态,然后在后续调用时继续执行。

这是生成器函数与常规函数的不同之处:

  • 生成器函数包含一个或多个yield语句。

  • 调用时,它返回一个对象(迭代器),但不会立即开始执行。

  • 像__iter__()和__next__()这样的方法会自动实现。因此,我们可以使用next()来遍历项目。

  • 一旦函数产生了结果,函数就会暂停,控制就会转移给调用者。

  • 局部变量及其状态在连续调用之间被记住。

  • 最后,当函数终止时,在进一步调用时会自动引发StopIteration。

这是一个示例,用于说明上述所有要点。我们有一个my_gen()由几个yield语句命名的生成器函数:

# 一个简单的生成器函数
def my_gen():
    n = 1
    print('这是第一次打印')
    # 生成器函数包含yield语句
    yield n

    n += 1
    print('这是第二次打印')
    yield n

    n += 1
    print('这是最后一次打印')
    yield n

# 它返回一个对象,但不立即开始执行
a = my_gen()
# 我们可以使用next()遍历这些项.
next(a)
# 一旦函数产生了结果,函数就会暂停,控制就会转移给调用者。

# 局部变量及其状态在连续调用之间被记住。
next(a)

next(a)

# 最后,当函数终止时,在进一步调用时将自动引发StopIteration。

next(a)

这是以上实列的输出结果:

在这里插入图片描述我们可以直接将生成器与for循环一起使用。

这是因为,for循环接受一个迭代器,并使用next()函数对其进行迭代。当StopIteration被触发时,它会自动结束

# 一个简单的生成器函数
def my_gen():
    n = 1
    print('这是第一次打印')
    # 生成器函数包含yield语句
    yield n

    n += 1
    print('这是第二次打印')
    yield n

    n += 1
    print('这是最后一次打印')
    yield n

# 使用for循环
for item in my_gen():
    print(item)

运行该程序时,输出为:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1142006.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

通达信涨停回马枪选股公式,涨停回调不破起涨点

在编写涨停回马枪选股公式之前&#xff0c;我们需要先深入了解如何编写涨停公式。在前面的文章《创业板、科创板也适用的通达信涨停指标公式怎么写&#xff1f;》中介绍了涨停指标公式的编写方法&#xff0c;然而这种方法偶尔还是会有漏网之鱼。因此借此机会&#xff0c;我们将…

【C++】多态 ② ( 面向对象中 “ 多态 “ 的真正需求 | 面向对象 “ 多态 “ 实现 - virtual 修饰函数 | 代码示例 )

文章目录 一、多态实现1、面向对象中 " 多态 " 的真正需求2、面向对象 " 多态 " 实现 - virtual 修饰函数 二、代码示例 - 多态实现1、代码示例2、执行结果 一、多态实现 1、面向对象中 " 多态 " 的真正需求 在上一篇博客 【C】多态 ① ( 类型兼…

2017-2022年中国地方ZF数据开放指数数据/历年开放数林指数数据集(省域指数、城市指数)

2017-2022年中国地方ZF数据开放指数数据/历年开放数林指数数据集&#xff08;省域指数、城市指数&#xff09; 1、时间&#xff1a;2017-2021年 2、指标&#xff1a;地方、准备度指数、准备度排名、平台层指数、平台层排名、数据层指数、数据层排名、利用层指数、利用层排名…

【Linux】部署单体项目以及前后端分离项目(项目部署)

一、简介 以下就是Linux部署单机项目和前后端分离项目的优缺点&#xff0c;希望对你有所帮助。 1、Linux部署单机项目&#xff1a; 优点&#xff1a; 简化了系统管理&#xff1a;由于所有服务都在同一台机器上运行&#xff0c;因此可以简化系统管理和维护。提高了性能&#x…

三大电商平台(淘宝/京东/阿里巴巴)封装商品详情API接口附代码实例|参数解析

接口的特点 Java接口中的成员变量默认都是public,static,final类型的(都可省略),必须被显示初始化,即接口中的成员变量为常量(大写,单词之间用"_"分隔) Java接口中的方法默认都是public,abstract类型的(都可省略),没有方法体,不能被实例化 Java接口中只能包含publi…

[PyTorch][chapter 58][强化学习-1]

前言&#xff1a; RL(Reinfocement Learning) 强化学习 是机器学习&#xff0c;深度学习一个重点。 后面20章将重点结合一些例子回顾一下经典的强化学习算法。 这里重点介绍一下机器学习中的强化学习算法&#xff0c;以及Gym 工具 目录&#xff1a; 简介 强化学习基本要素 …

释放搜索潜力:基于ES(ElasticSearch)打造高效的语义搜索系统,让信息尽在掌握[2.项目讲解篇],支持Linux/Windows部署安装

搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排精排重排混排)、系统架构、常见问题、算法项目实战总结、技术细节以及项目实战(含码源) 专栏详细介绍:搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排精排重排混排)、系统架构、常见问题、算法项目实战总结、技术…

智慧矿山系统中的猴车安全监测与识别

智慧矿山是近年来兴起的一种采用人工智能&#xff08;AI&#xff09;技术的矿山管理方式&#xff0c;它通过利用智能传感设备和先进算法来实现对矿山环境和设备进行监测和管理&#xff0c;从而提高矿山的安全性和效率。在智慧矿山的AI算法系列中&#xff0c;猴车不安全行为识别…

js中HTMLCollection如何循环

//不带索引 let divCon document.getElementsByClassName("el-form-item__error"); if (divCon.length > 0) {for (var item of divCon) {console.log("打印&#xff1a;", item.innerText);} }//带有索引 let divCon document.getElementsByClassNam…

毅速丨增减材协同制造已逐渐成为趋势

近年来&#xff0c;增材制造3D打印技术的发展非常迅速&#xff0c;被广泛应用于航空航天、汽车、电子、医疗等许多行业。增材制造技术通过逐层增加材料的方式制造出各种复杂形状的零件&#xff0c;具有很高的制造效率和灵活性。 然而&#xff0c;在精密加工领域&#xff0c;增材…

如何学好C++?学习C和C++的技巧是什么?

如何学好C?学习C和C的技巧是什么&#xff1f; 你这三个问题&#xff0c;前两个都是意思是差不多的&#xff0c;那么怎么怎么学习C/C我来问答一下&#xff1a;最近很多小伙伴找我&#xff0c;说想要一些C资料&#xff0c;然后我根据自己从业十年经验&#xff0c;熬夜搞了几个通…

二叉树问题——对称二叉树

摘要 101. 对称二叉树 一、对称二叉树解析 1.1 递归思路分析 首先想清楚&#xff0c;判断对称二叉树要比较的是哪两个节点&#xff0c;要比较的可不是左右节点&#xff01;对于二叉树是否对称&#xff0c;要比较的是根节点的左子树与右子树是不是相互翻转的&#xff0c;理解…

Map集合的遍历:键值对

package day01;import java.util.*;public class Mapday1 {public static void main(String[] args) {/* HashMap 无序 不重复&#xff0c;会覆盖前面 无索引*/System.out.println("--------------------");Map<String, Integer> map new HashMap<>();m…

如何设置模型的粗糙质感?

1、粗糙贴图的原理 粗糙贴图&#xff08;Roughness Map&#xff09;是一种用于模拟物体表面粗糙程度的贴图技术。它通过控制光线在物体表面的散射程度来实现不同粗糙度的效果。粗糙贴图通常使用灰度图像来表示不同部分的粗糙度&#xff0c;白色表示较光滑的表面&#xff0c;黑…

敏捷战略下的目标管理

1. 生而敏捷的 OKR 敏捷战略规划的周期相对较长&#xff0c;一般是以年为单位在做规划&#xff0c;通常是 3~5年。在战略规划之后&#xff0c;需要有更短周期的目标管理去做承接。现今&#xff0c; OKR 成为承接敏捷战略最好的目标管理工具。 将OKR 和战略、愿景、使命之间的关…

【网络工程师8个疑难杂症解决方案】

典型问题① 用户抱怨:整个网络变慢 网络症状:影响所有连接到网段上的工作站 查找问题:在正常的网络使用时段&#xff0c;将网络测试仪连接到集线器&#xff0c;在光纤连接的两端产生流量&#xff0c;测试每边健康状况。在某一时刻断开或接上光纤&#xff0c;每当光纤连入网段…

基于GPIO子系统编写LED驱动

编写应用程序进行测试 设置定时器&#xff0c;每5秒打印一次hello world 驱动程序 #include <linux/init.h> #include <linux/module.h> #include<linux/of.h> #include<linux/of_gpio.h> #include<linux/fs.h> #include<linux/io.h> #i…

笔记-《RabbitMQ实战指南》

目录 1.发到Mq对应的3个参数&#xff1a;Exchange(交换器)&#xff0c;RountingKey(路由键)&#xff0c;param2.队列3.Exchange(交换器)4.Binding(绑定)5.交换器类型6.Connection(连接)&#xff0c;Channel(信道)7. AMQP协议8. 判断Channel或者Connection关闭状态9. 交换器和队…

【论文解读】RLAIF基于人工智能反馈的强化学习

一、简要介绍 人类反馈强化学习(RLHF)可以有效地将大型语言模型(LLM)与人类偏好对齐&#xff0c;但收集高质量的人类偏好标签是一个关键瓶颈。论文进行了一场RLHF与来自人工智能反馈的RL的比较(RLAIF) -一种由现成的LLM代替人类标记偏好的技术&#xff0c;论文发现它们能带来相…

Spring MVC的常用注解

目录 RequestMapping 例子&#xff1a; RequestMapping 支持什么类型的请求 使 RequestMapping 只支持特定的类型 RestController 通过 HTTP 请求传递参数给后端 1.传递单个参数 注意使⽤基本类型来接收参数的情况 2.传递多个参数 3.传递对象 4.RequestParam 后端参数…