Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >手撕Python之生成器、装饰器、异常

手撕Python之生成器、装饰器、异常

作者头像
Undoom
发布于 2024-09-23 13:23:10
发布于 2024-09-23 13:23:10
9800
代码可运行
举报
文章被收录于专栏:学习学习
运行总次数:0
代码可运行
1.生成器

生成器的定义方式:在函数中使用yield

yield值:将值返回到调用处

我们需要使用next()进行获取yield的返回值

yield的使用以及生成器函数的返回的接收next()

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def test():
    yield 1,2,3

t=test()
print(t)
#<generator object test at 0x01B77A48>
#生成器对象的意思


#我们在函数中使用这个yield关键字,那么这个函数就是一个生成器函数

#t存放的是生成器对象的信息
#yield的作用类似于return 将值返回到调用的地方

#我们如何获取这个1呢?

#next(生成器对象)
print(next(t))
#(1, 2, 3)

#yied返回的内容我们需要通过next()进行一个获取的操作

有yiled的函数被称为生成器函数

对于性质一来说的话,yield会将后面的数据进行返回,返回到调用处

对于性质二的话,我们运行完yield之后,这个函数的运行位置就会被记录下来了

然后我们在交互模式再次进行这个next()的使用,进行返回值的获取那么就会从上次函数中结束的位置进行开始寻找数据然后进行返回的操作

然后后面如果没有yield的话,有个print('abc')

那么这个函数会将abc进行返回的,但是最终会进行报错的

就像下图所示

从下面的图片我们可以看的出什么呢?

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def test():
    yield 1,2,3
    print('abc')
    yield 'a'
t=test()
print(t)

print(next(t))
#(1, 2, 3)
print(next(t))
'''
abc
a
'''

我们在编辑模式第一次调用next()的时候打印出的返回值是1 2 3

我们在函数中又添加了一个yield关键字

然后我们在交互模式再次进行next的调用

这次的返回值是abc a

我们在调用next()的时候,这个我们会回到上一次yield结束的后面的一个位置

然后从那里开始寻找关键字yield进行数据的返回的操作

next()的作用就是获取yield后面的内容的

我们每次调用的时候就会回到上次yield结束的位置,从那个位置开始

yield和return的区别就是return会直接将函数进行结束,但是yield会保留此次的位置,下次调用的时候就从这个位置开始进行

yield只会中断,但是不会进行结束的操作

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def testa():
    for i in range(1,10):
        yield i

t1=testa()
#获取yield返回值的方式:next()
print(next(t1))
#每次获取一个值,有多少个值就获取多少次
print(next(t1))
print(next(t1))
print(next(t1))
print(next(t1))
print(next(t1))
print(next(t1))
'''
1
2
3
4
5
6
7
'''
#如果我们超出了了的话就是会报错了
#因为最后一个yield后面没有数据了



t2=testa()
#获取yield返回值的方法二
for n in t2:
    print(n)

#我们通过for循环能够一次性拿完

#我们通过next()的时候我们需要的时候就可以进行调用,想拿几个就拿几个

print(next(t1))
#8
#我们需要用的时候就进行调用一下,不用就放着

对于获取yield我们有两种方法的,第一种就是进行Next函数的调用

第二种就是利用for循环,直接将对象当做条件进行循环,将这个函数中所有的yield后面的值进行返回

我们对于第一种的话,想什么时候用就什么时候用,随时能够进行调用的操作

2.装饰器

装饰器本质上是一个Python函数(其实就是闭包),它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
'''在不改动函数的情况下,给函数添加内容
装饰器的定义:
1.嵌套函数
2.外函数返回内函数名
3.外函数中定义一个形参,形参用来接受被装饰的函数名信息
4.要添加的额外功能,写在内函数中

调用函数:函数名()

使用装饰器:@装饰器名(外部函数名)
'''
#定义装饰器
def funa(name):
    def funb():
        print('---开始执行函数---')
        #在这个中间执行被装饰的函数
        name()#这个形参是用来接受这个被装饰的函数名的信息
        '''
        name=testc
        name()=testc()
        '''

        print('---函数执行完毕---')
    return funb

#被装饰的函数
@funa
def testc():
    print('执行testc函数')

testc()

'''
---开始执行函数---
执行testc函数
---函数执行完毕---
'''
@funa
def testd():
    print('执行testd函数')
testd()
'''
---开始执行函数---
执行testd函数
---函数执行完毕--
'''

我们先进行装饰器的定义操作

1.嵌套函数

2.外函数返回内函数名

3.外函数中定义一个形参,形参用来接受被装饰的函数名信息

4.要添加的额外功能,写在内函数中

5.在内部函数中调用被装饰的函数,即外函数的函数名

我们的外函数有个形参name就是用来接受被装饰函数的函数名信息的

方便我们在内函数中进行调用

我们在被装饰的函数的定义上面加上 @外部函数名

那么就说明我们这个函数就已经被装饰好了

那么我们对testc进行调用的操作,那么就会运行我们之前在内部函数中做的装饰代码

总结:我们先会执行这个 @funa

@后面跟的是一个装饰器函数

然后就直接将这个testc的内容给到了name

给到name 之后我们就往后面走

执行内部函数,这个name=装饰的函数的函数名

我们先运行到@funa

然后就运行到def testc()

然后就def funa(name)

然后就运行到def funb()

运行到这个内部函数的时候

我们会直接返回这个funb()返回到被装饰的函数

就是返回到testc这里

那么到这里的话装饰就完成了

然后就直接跳到了testc()的带调用处

然后进行testc的调用的时候

我们就会直接调用装饰器内部函数

我们跳到testc()的地方的时候我们直接进行装饰器的内部函数的调用操作了

对于函数装饰的代码我们写在内部函数中

外部函数一定要定义形参,接受被装饰函数的函数名

不然我们在内部函数中无法进行被装饰函数的调用

那么装饰器的作用:在不改变原函数的情况下对函数进行一系列的装饰操作

就是一个外包操作的升级版本

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def log(u):
    def aaa(name,pwd):
        d={'123456':{'pwd':'1234'},
              '1234567':{'pwd':'12345'}
             }
        if name in d:
            if pwd==d[name]['pwd']:
                print("登录成功")
                #调用被装饰的函数
                u(name,pwd)#外部参数的形参是u
            else:
                print("密码错误")

        else:
            print("用户不存在")
    return aaa


#取款
@log
def get_money(name,pwd):
    print(f"取款1000")
#查询
def set_money(name,pwd):
    print(f"存款1000")



get_money('1256','1234')

#通过装饰器我们能减少代码冗余的效果

不改变函数代码的情况下,对函数增加一系列的操作

3.异常

异常的概念

异常是指程序在运行过程中发生的错误或者不正常的情况。当Python检测到一个错误时,解释器就无法继续执行了,反而出现一些错误的提示。

根据报错信息我们能找到报错的地方

常见的异常

对异常的预防(try、except、Exception、raise、assert)

当我们遇到异常的时候程序会终止执行,可能还会导致软件崩溃,遇到异常的解决方法:

  1. 预防:添加容错代码(代码过多代码冗余)
  2. 解决:添加捕获异常部分(try、expect)
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
num=input("请输入一个整数")

#异常解决方案一:添加容错代码
if num.isdigit():#判断字符串是否都是数字
    num=int(num)
else:
    print('输入的不是整数')

#异常解决方案二:捕获异常
try:
    #可能会报错的语句
    num=int(num)
except ValueError:#except异常类型---捕获对应的异常类型
    #捕获到异常,处理的语句
    print(f"输入{num}不是整型")
#报错的默认信息
except ValueError as v:#接受捕获的异常的报错信息
    print(v)
else:
  print("没有报错")
finally:
  print("异常处理完毕")
#invalid literal for int() with base 10: '1.5'
print(1234)

#用except捕获到异常之后我们就在后面进行处理,提醒出现的异常

#多个expect的关系是或的关系,他们只会执行一个的

except异常类型:

对用户进行提醒的代码

如果我们不知道对应的异常类型的话

我们就写Exception ---万能异常

能接收所有的错误信息

能代替所有异常类型

如果我们看默认报错的话,我们就这么写

except Exception as a:

print(f"错误{a}")

这后面字母a,你想起什么字母就写什么字母

这个存储的是错误信息

finally 的话,不管有没有异常,都会执行下面的代码的

except和else关系是或,只能执行一个

try后面必须有一个except

finally不管是否发生异常,始终都会执行

raise会主动抛出异常

函数在出现异常的时候会将异常返回至函数调用处,在调用处就能进行处理操作

raise 异常类型(异常描述信息)---抛出异常

在后面加上异常提示信息

raise的用法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def test():
    tel=input("请输入手机号码")
    if not(tel.isdigit() and len(tel)==11):#号码写错的情况下就会进行下面的代码
      #将错误信息抛出
        raise ValueError("请输入正确的11位手机号码")

try:
    test()
except Exception as e:
    print(e)

assert语句的格式:

assert测试条件,错误信息

断言语句是一种调试工具,用来测试某个断言条件,如果断言条件为真,则程序将继续正常执行;如果条件为假,则会引发AssertionError异常并显示相关错误信息

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
try:
    n=input("请输入数字")
    assert n.isdigit(),'只能输入数字'
    #断言异常的话就会提示后面的错误信息的
except AssertionError as a:
    print(a)
print('6')

assert n.isdigit(),'只能输入数字'

assert 判断条件 ,‘报错信息’

4.模块

模块的简介

Python中的模块,指的就是一个py文件。对于一个py文件,可以只用import来导入其中的代码

模块的使用:import 模块名

import keyword---查看关键字

import random---电脑产生随机值

模块的分类

  1. 内置模块:这类模块是Python自带的,可以直接导入使用。
  2. 第三方模块:也就是别人写好的一些模块,你要安装之后才可以用(先下载再导入使用 )。

3.自定义模块:自己在项目中定义的一些模块,注意自定义模块的时候命名要遵循标识符规定和变量的命名规范,并且不要与内置模块起冲突,否则将导致模块功能无法使用。

不能和内置模块冲突了

我们在同一文件夹中写一个py文件

然后在这个文件里面导入另一个文件

假设另外一个文件叫test.py

里面有个名字

我们在这个文件中写

import test

print(test.name)

我们需要先将test.py里面的代码运行进行保存

我们在别的文件才能进行调用

最好将这几个文件放到同一个目录之下

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-09-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
python3 迭代器、生成器、装饰器、
孩子我现在有个需求看列表[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],我要求你把列表里的每个值加1你怎么实现你可能会想到2种方式 
py3study
2020/01/03
1K0
python3 迭代器、生成器、装饰器、
Python 基础(十七):装饰器
不过都没关系,我们再以 Python 为例更通俗的解释一下:比如我们调用一个带有返回值的函数 x,此时函数 x 为我们返回一个函数 y,这个函数 y 就被称作闭包,这么一说是不是豁然开朗了
Python小二
2020/08/18
3010
Python 基础(十七):装饰器
Python生成器,迭代器,装饰器
使用了yield函数 就被称之为生成器,生成器是一个返回迭代器的函数,说白了生成器就是迭代器,只能用于迭代操作
Gorit
2021/12/09
3310
Python生成器,迭代器,装饰器
手撕Python之函数
函数的作用:我们把需要反复执行的程序封装起来,制作成一个可以反复调用的工具,这个工具在编程中就叫函数
Undoom
2024/09/23
1310
手撕Python之函数
【Python系列】为啥老问装饰器、迭代器、生成器?
好麻,最近整理下Python学习笔记,把面试常问的几个装饰器、迭代器、生成器总结一下。
用户9913368
2022/08/13
7570
【Python系列】为啥老问装饰器、迭代器、生成器?
【Python基础之函数:异常相关和生成器对象、yield用法、生成器表达式】
​ 在没完善一个程序之前,我们不知道程序在哪里会出错,与其让它在运行最崩溃,不如在出现错误条件时就崩溃,这时候就需要assert断言的帮助
老虎也淘气
2024/01/30
2020
剖析 Python 面试知识点(一): 魔法方法、闭包/自省、装饰器/生成器
在Python中用双下划线__包裹起来的方法被成为魔法方法,可以用来给类提供算术、逻辑运算等功能,让这些类能够像原生的对象一样用更标准、简洁的方式进行这些操作。 下面介绍常常被问到的几个魔法方法。
天澄技术杂谈
2019/04/05
7160
python生成器,递归调用
什么是生成器:只要在函数体内出现yield关键字,那么再执行函数就不会执行函数代码,会得到一个结果,该结果就是生成器
py3study
2020/01/20
1.1K0
生成器send方法,递归,匿名函数,内置
一,复习 ''' 1.带参装饰器 - 自定义 | wraps def wrap(info) def outer1(func): from functools import wraps @wraps(func) def inner(*args, **kwargs): # 需要外界的参数 return func(*args, **kwargs) return inner def ou
py3study
2020/01/16
5310
python3 基础(4)-装饰器、生成
def bar(): print("in the bar") #函数bar()在以下三处位置,只有1、2处时,调用foo()才正确执行 ------------------------------ #1# def foo(): print("in teh foo")    bar() #2# foo() #3#
py3study
2020/01/03
4460
python3 基础(4)-装饰器、生成
【Python基础编程】迭代器、生成器、装饰器与闭包全攻略
上篇文章将了python多态,类属性等知识,这篇文章了解一下python的三器一包:迭代器、生成器、装饰器和闭包
易辰君
2024/11/07
4050
Python之@函数装饰器
装饰器的作用 —— 不想修改函数的调用方式 但是还想在原来的函数前后添加功能 原则: 开放封闭原则 开放 : 对扩展是开放的 封闭 : 对修改是封闭的
cuijianzhe
2022/06/14
3930
Python之@函数装饰器
【Python】笔记第六部分:生成器和函数式编程
每一次对过程的重复称为一次“迭代”,而每一次迭代得到的结果会作为下一次迭代的初始值。例如:循环获取容器中的元素。
杨丝儿
2022/02/17
4570
彻底理解 Python 生成器
如果列表元素按照某种算法推算出来,那我们就可以在循环的过程中不断推算出后续的元素,这样就不必创建完整的list,从而节省大量的空间。
py3study
2020/01/19
6070
彻底理解 Python 生成器
周末学习笔记——day02(带参装饰器,
一,复习 ''' 1.函数的参数:实参与形参 形参:定义函数()中出现的参数 实参:调用函数()中出现的参数 形参拿到实参的值,如果整体赋值(自己改变存放值的地址),实参不会改变,(可变类型)如果修改内部内容,实参会跟着变化 位置实参 - 只能对位置形参赋值 关键字实参 - 可以对所有(不包含可变长位置形参)形参赋值 位置形参 - 必须出现在最前,且必须传值 默认形参 - 出现在位置形参后*前,可以不用传参 可变长位置形参
py3study
2020/01/17
3910
Python之生成器
虽然生成器对象的使用方法与迭代器对象类似,但是内部原理是不同的 构建迭代器时,不是把所有元素一次性加载到内存,而是一种延迟计算的方式返回元素。 生成器就是一特殊迭代器,它不会把所有内容放在内存里,每次调用 next()函数时,返回的都是本次计算出来的那个元素,用完之后立刻销毁。
cuijianzhe
2022/06/14
1810
【python】生成器
生成器实现了__next__可以使用next()来获取下一个值,当然也可以使用for循环遍历
JuneBao
2022/10/26
3290
python迭代器、生成器、装饰器
可以直接作用于for循环的对象统称为可迭代对象,即Iterable。   # 一是集合数据类型,如list、tuple、dict、set、str等;   # 二是generator,包括生成器和带yield的generator function。
用户1432189
2018/09/05
8940
python迭代器、生成器、装饰器
4.python迭代器生成器装饰器
基本概念 1.容器(container) 容器是一种把多个元素组织在一起的数据结构,容器中的元素可以逐个地迭代获取,可以用in, not in关键字判断元素是否包含在容器中。通常这类数据结构把所有的元素存储在内存中(也有一些特例,并不是所有的元素都放在内存,比如迭代器和生成器对象)在Python中,常见的容器对象有: list, deque, …. set, frozensets, …. dict, defaultdict, OrderedDict, Counter, …. tuple, namedtupl
zhang_derek
2018/04/11
5980
python之迭代器、生成器、装饰器
对于Python 列表的 for 循环,他的内部原理:查看下一个元素是否存在,如果存在,则取出,如果不存在,则报异常 StopIteration。(python内部对异常已处理)
菲宇
2019/06/13
1.2K0
python之迭代器、生成器、装饰器
相关推荐
python3 迭代器、生成器、装饰器、
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验