python_d05

本文深入探讨Python中的迭代器概念,包括如何使用它们以及生成器的优势。接着,我们讨论`yield`表达式的不同应用,如何从面向过程编程过渡到函数式编程,并介绍了Python中的简洁语法,如三元表达式、列表生成式、字典生成式和生成器表达式。此外,还介绍了Python的匿名函数`lambda`及模块的导入和管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

01 迭代器

'''
1、什么是迭代器
    迭代的工具

    什么是迭代?
    迭代是一个重复的过程,每一次重复都是给予上一次结果而进行的

    单纯的重复并不是迭代
    while True:
        print('=====>')

2、为什么要用迭代器
    找到一种可以不依赖索引的迭代取值方式

3、怎么用迭代器
    可迭代对象?
        在Python中,但凡内置有__iter__方法对象,都是可迭代的对象

    迭代器对象?
        执行可迭代对象下__iter__方法得到的返回值就是一个迭代器对象

        迭代器对象内置
            __next__方法
            __iter__方法,执行该方法得到仍然是迭代器本身,干什么用??

    迭代器对象一定是可迭代的对象
    可迭代的对象不一定是迭代器对象
'''

# l=['a','b','c']
# l='hello'
# l=('a','b','c','d','e')
# l={'a':1,'b':2,'c':3}  #报错,字典是无序
# i=0
# while i < len(l):
#     print(l[i])
#     i+=1

# a=1
# b=1.1
# #以下都是可迭代的对象
# c='hello'
# d=[1,2,3]
# e=(1,2,3)
# d={'a':1}
# g={1,2,3}
# f=open('aa.py','rb')

# 执行可迭代对象的__iter__方法得到迭代器对象
# dic={'k1':1,'k2':2,'k3':3}
# iter_obj=dic.__iter__()
#
# # print(iter_obj)
#
# print(iter_obj.__next__())
# print(iter_obj.__next__())
# print(iter_obj.__next__())
# print(iter_obj.__next__())   #报错,因为没有第四个字典的key


# f=open('aa.py','rt',encoding='utf-8')
# iter_obj=f.__iter__()
#
# print(iter_obj)
# print(iter_obj.__next__(),end='')
# print(iter_obj.__next__(),end='')
# print(iter_obj.__next__(),end='')

# 基于迭代器的迭代取值方式
dic={'k1':1,'k2':2,'k3':3}
#
# iter_obj=dic.__iter__()
# print(iter_obj)    #<dict_keyiterator object at 0x0000000001D94778>
#
# print(iter_obj.__iter__().__iter__().__iter__().__iter__() is iter_obj)  #iter_obj.__iter__就是他本身
#
# while True:
#     try:
#         print(iter_obj.__next__())
#     except StopIteration:
#         break


# for循环的底层运行机制:for循环可以称之为迭代器循环
# 1、新调用in后那个对象的__iter__方法,得到该对象的迭代器对象
# 2、执行迭代器对象的__next__方法,将得到的返回值赋值in前面的变量名,然后执行一次循环体代码
# 3、循环往复,直到取干净迭代器内所有的值,自动捕捉异常结束循环

# for k in dic:   #iter_obj=dic.__iter__()
#     print(k)

# for x in 10:  #报错,10不是可迭代的
#     pass

# f=open('aa.py','rt',encoding='utf-8')
# for line in f:
#     print(line)

# 示范一
# dic={'k1':1,'k2':2,'k3':3}
# iter_obj=dic.__iter__()
#
# print('第一次迭代iter_obj')
# for k in iter_obj:
#     print(k)
#
# print('第二次迭代iter_obj')
# for k in iter_obj:
#     print(k)

'''
第一次迭代iter_obj
k1
k2
k3
第二次迭代iter_obj
'''

# 示范二
# dic={'k1':1,'k2':2,'k3':3}
# iter_obj=dic.__iter__()
# print('第一次迭代iter_obj')
# for k in iter_obj:
#     print(k)
#
# iter_obj=dic.__iter__()
# print('第二次迭代iter_obj')
# for k in iter_obj:
#     print(k)

'''
第一次迭代iter_obj
k1
k2
k3
第二次迭代iter_obj
k1
k2
k3
'''

# 示范三:1
# dic={'k1':1,'k2':2,'k3':3}
# #每次都会主动先调用in后那个对象的__iter__方法,得到该对象的迭代器对象
# print('第一次迭代')
# for k in dic:
#     print(k)
#
# print('第二次迭代')
# for k in dic:
#     print(k)

# 迭代器的优缺点:
# 优点:
# 1、提供一种不依赖与索引的迭代取值方式===》应用于for循环
# 2、节省内存

# l=[1,2,3,4,5,6,6,6,6,6,6,6,6,6,6,6]
#一次往下读一行
# obj=l.__iter__()
# f=open('aa.py')
# print(f.__next__())
# print(f.__next__())

# f.readline()

# for line in f:
#     print(line)


# for i in range(1,10000):
#     print(i)


# 缺点:
# 1、只能往后取,不能往前取,是一次性的,值取干净后无法再次取值,除非重新得到新的迭代器对象
# 没有按索引取值的方式灵活
# 
# 2、值取不干净,永远无法预测迭代器的长度

02 生成器

​
'''
一、什么是生成器
    在函数内但凡有yield关键字,再调用函数就不会执行函数体代码,得到   返回值    就是一个   生成器对象
    强调:生成器本质就是迭代器

    next(g)过程:
        会触发生成器g所对应的函数的执行,直到遇到yield才停下来,然后把yield后的返回值当做本次next操作的结果

二、为什么要用生成器:
    学习生成器是为了掌握一种自定义迭代器的方式

三、总结yield:
    1、yield提供一种自定义迭代器的方式
    2、与return对比,都能返回值,都能返回多个值,都没有类型限制,而return只能返回一次值,
        而yield可以返回多次值(yield可以帮我们保存函数的执行状态)


'''

# def func():
#     print('first')
#     yield 1    #<generator object func at 0x0000000002871728>
#     print('second')
#     yield 2      # # yield 1  <generator object func at 0x0000000002281728>
#     print('third')

# g=func()
# print(g)

# res1=next(g)   #g.__next__()
# print(res1)
# '''
# first
# 1
# '''
# res2=next(g)  #g.__next__()
# print(res2)
# '''
# first
# 1
# second
# 2
# '''
# res3=next(g)  #取到third后报错
# '''
# Traceback (most recent call last):
#   File "D:/ProgramData/old boy/SH_s1/day05/02 生成器.py", line 44, in <module>
#     res3=next(g)  #取到third后报错
# StopIteration
# first
# 1
# second
# 2
# third
# '''

# g=func()
# for item in g:  #item=next(g)
#     print(item)
'''
first
1
second
2
third
'''

range(1,100,2)
def my_range(start,stop,step=1):
    print('开始运行')
    while start < stop:
        yield start
        start+=step
    print('结束运行')

obj=my_range(1,1000,2)

res1=next(obj)
print(res1)


​

03 yield的表达式形式应用

def dog(name):
    print('粽子%s准备开吃' %name)
    food_list=[]
    while True:    #while True 语句中一定要有结束该循环的break语句
        food=yield food_list  #暂停 food=yield='骨头'
        print('粽子%s 吃了%s' %(name,food))
        food_list.append(food)

g=dog('c')
# print(g)   #打印生成器对象地址<generator object dog at 0x0000000001DDDFC0>
res1=next(g)  #到food=yield food_list暂停了,返回了food_list
print(res1)   #打印得到[]
'''
粽子c准备开吃
[]
'''

# res2=next(g)
# print(res2)
'''
粽子c吃了None
[None]
'''
# g.send(None) #完全等同于next(g),强调:对于表达式形式yield的生成器,在使用前必须用next(g)或g.send(None)初始化一次

res2=g.send('骨头')  #food=骨头,粽子c 吃了骨头
print(res2)    #res2=next(g),粽子c 吃了骨头>>food_list.append('骨头')>>food=yield food_list中断,返回food_list,res2=['骨头']>>print(res2)得['骨头']

res3=g.send('骨头1')
print(res3)
'''
粽子c 吃了骨头1
['骨头','骨头1']
'''

# res4=g.send('骨头2')
# print(res4)

'''
粽子c 吃了骨头2
['骨头', '骨头1','骨头2']
'''

res4=next(g)
print(res4)
'''
粽子c 吃了None
['骨头','骨头1',None]
'''

04 面向过程编程

'''
1、面向过程编程
    核心是过程,过程指的是解决问题的步骤,即先干什么,再干什么,后干什么
    基于面向过程的思想编写程序好比在设计一条流水线,是一种机械式思维方式


    优点:
        将复杂的问题流程化,进而简单化
    缺点:
        修改某一个阶段,其他相关的阶段都有可能受影响,牵一发而动全身,扩展性极差
    应用:
        应用于对扩展性要求不高的场景
'''

def interactive():
    '''接收用户输入的用户名、密码'''
    uname=input('username>>>:').strip()
    group=input('group>>>:').strip()
    pwd=input('password>>>:').strip()
    return uname,group,pwd

def auth(uname,group,pwd):
    '''认证用户名与密码是否正确'''
    if uname == 'm' and pwd == '123' and group == 'master':
        return True,uname,group
    else:
        return False,uname,group

def index(res):
    '''如果认证成功,则打印欢迎界面'''
    if res[0]:
        print('部门:%s 员工:%s 登陆成功' %(res[2],res[1]))

    else:
        print('部门:%s 员工:%s 登陆失败' %(res[2],res[1]))

uname,group,pwd=interactive()
res=auth(uname,group,pwd)
index(res)

05 三元表达式

x=10
y=30

res=x if x > y else y
print(res)

06 列表生成式、字典生成式、生成器表达式

# 列表生成式
# l=[]
# for i in range(10):
#     l.append('egg%s' %i)
#
# print(l)   #['egg0', 'egg1', 'egg2', 'egg3', 'egg4', 'egg5', 'egg6', 'egg7', 'egg8', 'egg9']


# l=['egg%s' %i for i in range(10)]
# print(l)    #['egg0', 'egg1', 'egg2', 'egg3', 'egg4', 'egg5', 'egg6', 'egg7', 'egg8', 'egg9']


# nums=[i**2 for i in range(10)]
# print(nums)   #[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

# 1、将names=['egon','alex_sb','wupeiqi','yuanhao']中的名字全部变大写
# names=['egon','alex_sb','wupeiqi','yuanhao']
# names=[name.upper() for name in names]
# print(names)   #['EGON', 'ALEX_SB', 'WUPEIQI', 'YUANHAO']

# 2、将names=['egon','alex_sb','wupeiqi','yuanhao']中以sb结尾的名字过滤掉,然后保存剩下的名字长度
# names=['egon','alex_sb','wupeiqi','yuanhao']
# l=[len(name) for name in names if not name.endswith('sb')]
# print(l)   #[4, 7, 7]

# 字典生成式
# d={i:i for i in range(10) if i >0}
# print(d)    #{1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9}
#
# userinfo=[('egon','123'),('alex','456'),('wxx','678')]
# dic={k:v for k,v in userinfo}
# print(dic)   #{'egon': '123', 'alex': '456', 'wxx': '678'}

# 生成器表达式
# g=(i for i in range(1000000000000000000000000000000000))
# # print(g)   # <generator object <genexpr> at 0x000000000260DFC0>
# print(next(g))
# print(next(g))

# chicken=('egg%s' %i for i in range(3))
# # print(chicken)
# print(next(chicken))
# print(next(chicken))
# print(next(chicken))
# '''
# egg0
# egg1
# egg2
# '''
# print(next(chicken))  #报错,只有三个值
# '''
# Traceback (most recent call last):
#   File "D:/ProgramData/old boy/SH_s1/day05/06 列表生成式、字典生成式、生成器表达式.py", line 50, in <module>
#     print(next(chicken))
# StopIteration
# '''

#求文件a.txt中最长的行的长度(长度按字符个数算,需要使用max函数)
# res=max((1,2,3,4,5,6,7))
# print(res)

with open('a.txt','r',encoding='utf-8') as f:
    nums=(len(line) for line in f)
    # print(nums)  #<generator object <genexpr> at 0x0000000001DCDFC0>
    # print(nums)
    # print(next(nums))   #文件已经关闭,报错,不占用内存。ValueError: I/O operation on closed file.

    print(max(nums))

07 匿名函数

# def f1():
#     print('from f1')
#
# f1()
# f1()

# def func(x,y):
#     return x+y
#
# print(func)   #<function func at 0x00000000004F3E18>
# # func(1,2)
# print(func(1,2))  #3

# 匿名
# 注意:
# 1、不会单独使用,会与其他函数配合使用
# 2、匿名函数的精髓在于没有名字,如果没有名字意味着用一次就立即回收,匿名函数仅用于使用一次的场景
# lambda x,y:x+y

# 配合使用的内置函数:max,min,sorted,filter,map
salaries={
   'egon':3000,
    'alex':10000000,
    'wupeiqi':10000,
    'yuanhao':2000
}
# 求出最大工资的那个人名
# def func(k):
#     return salaries[k]

# print(max(salaries,key=lambda x:salaries[x]))    #alex,比的是value,得到的结果是key
# print(min(salaries,key=lambda x:salaries[x]))    #yuanhao

# sorted,按照薪资排序,从小到大排
# print(sorted(salaries,key=lambda x:salaries[x]))   #['yuanhao', 'egon', 'wupeiqi', 'alex']
# sorted,按照薪资排序,从大到小排
# print(sorted(salaries,key=lambda x:salaries[x],reverse=True))  #['alex', 'wupeiqi', 'egon', 'yuanhao']

# map的应用

names=['alex', 'wupeiqi', 'egon', 'yuanhao']
# l=[name+'_sb' for name in names]
# print(l)   #['alex_sb', 'wupeiqi_sb', 'egon_sb', 'yuanhao_sb']

# obj=map(lambda x:x+'_sb',names)
# print(list(obj))

# filter的应用
names=['alex_sb','wupeiqi_sb','egon','yuanhao_sb','liuqingzheng_sb']

l=(name for name in names if name.endswith('sb'))
print(list(l))
# print(l)   #<generator object <genexpr> at 0x0000000002861728>
# print(l.__next__())     #alex_sb
# print(l.__next__())     #wupeiqi_sb
# print(l.__next__())     #yuanhao_sb
# print(l.__next__())     #liuqingzheng_sb


# filter会得到names的迭代器对象obj,然后next(obj)将得到的值传给filter第一个参数指定的函数
# 将函数返回值为True的那个值留下
# res=filter(lambda x:x.endswith('sb'),names)
# print(list(res))   #['alex_sb', 'wupeiqi_sb', 'yuanhao_sb', 'liuqingzheng_sb']

0801 模块介绍

一、什么是模块
    模块就是一组功能的集合体,模块组织形式有以下几种
    1、一个Python文件是一个模块,文件名是module.py,模块名则是module(自定义模块的常见形式)
    2、已被编译为共享库或DLL的C或C++扩展
    3、使用c编写并链接到Python解释器的内置模块
    4、把一系列模块组织到一起的文件夹(注:文件夹下有一个__init__.py文件,该文件夹称之为包)

二、为什么要用模块
    1、可以将程序中频繁用来的一些公共的功能组织到一个文件中,从而减少代冗余
    2、直接使用内置或者第三方的模块中的功能,这种拿来主义可以提升开发效率

三、如何使用模块
# spam.py
# print('from the spam.py')

__all__=['money','read1']    #from spam import *,控制的就是*所导入的名字
money=1000

def read1():
    print('spam模块:',money)

def read2():
    print('spam模块')
    read1()

def change():
    global money
    money=0

#当文件被当做脚本执行时__name__的值为"__main__"
# 当文件被导入时__name__的值为"模块名"
print(__name__)    #直接执行得到__main__,import spam得到spam

if __name__ == '__main__':
    read1()
    read2()
    change()

 

 0802 import导入模块

# ==============================第一部分
x=1
y=2
# from spam import money,read1,read2,change
# 1、from 。。。import。。。首次导入模块也做三件事:
#     1.1 首先产生一个模块的名称空间
#     1.2 会执行模块文件的代码,将产生的名字放到模块的名称空间中
#     1.3 会在当前名称空间中直接拿到一个模块名称空间中的名字
# money=1  #  print(money)   结果为1===》》容易与当前名称空间中的名字冲突

# 2、可以不加前缀直接使用
# print(money)
# print(read1)
# print(read2)
# print(change)
'''
1000
<function read1 at 0x0000000002838268>
<function read2 at 0x0000000002838840>
<function change at 0x0000000002838B70>
'''
# 优点:简洁
# 缺点:容易与当前名称空间中的名字冲突

#强调强调强调:来自于模块名称空间中的函数一定是模块的名称空间为准
# read1()    #spam模块: 1000
# change()
# read1()  #spam模块: 0
# print(money)    #1,change不会改变当前money的值

# =======================第二部分
# from spam import *
# #不推荐使用*,除非在我们需要引入模块中很多名字时,可以用*起到一个节省代码的作用
# print(money)
# print(read1)
# print(read2)
# print(change)
# '''
# 1000
# <function read1 at 0x0000000002898840>
# <function read2 at 0x0000000002898B70>
# <function change at 0x0000000002898BF8>
# '''

# ==========================第三部分(了解)
# from spam import *
# #spam.py中添加__all__=['money','read1']
# print(money,read1)   #1000 <function read1 at 0x0000000002848840>
# print(read2)    #报错,NameError: name 'read2' is not defined
# '''
# 1000 <function read1 at 0x0000000002848268>
# <function read2 at 0x0000000002848840>
# '''
# =========================第四部分
from spam import money as m
print(m)    #1000

 

 

 

### Python 主题歌曲与相关音乐资源 Python 作为一种广受欢迎的编程语言,其社区中也涌现了许多与之相关的创意作品,包括音乐和音频资源。以下是一些与 Python 主题歌曲或相关音乐资源的详细信息: #### 数据读取与处理 在查找 Python 主题歌曲或相关音乐时,可以使用数据库文件进行数据读取和统计分析[^1]。例如,通过统计用户播放量、歌曲流行度等指标,筛选出与 Python 相关的音乐资源。 #### 音乐生成工具 利用深度学习技术,可以生成与 Python 主题相关的音乐。MuseScore 数据集提供了从 MusicXML 文件到数字矩阵的转换脚本,便于开发者构建智能音乐生成系统[^2]。以下是一个简单的安装和使用示例: ```python !wget https://github.com/cuthbertLab/music21/archive/v.6.7.zip !unzip v.6.7.zip !mv music21-6.7/* . !rm -rf music21-6.7 v.6.7.zip README.md LICENSE* CHANGES* pip install music21 ``` #### 热门艺术家与歌曲 通过数据分析,可以绘制热门艺术家及其歌曲的播放量分布图。例如,使用 `popular_artist_top_20` 数据集中的艺术家名称和播放次数,生成可视化图表[^3]: ```python import numpy as np import matplotlib.pyplot as plt objects = list(popular_artist_top_20['artist_name']) y_pos = np.arange(len(objects)) performance = list(popular_artist_top_20['listen_count']) plt.bar(y_pos, performance, align='center', alpha=0.5) plt.xticks(y_pos, objects, rotation=90) plt.ylabel('播放次数') plt.title('最受欢迎的艺术家') plt.show() ``` #### 音频爬取与下载 对于具体的 Python 主题歌曲,可以通过网络爬虫获取相关音频资源。以下是一个简单的音频爬取示例[^4]: ```python import requests url = "https://sy-sycdn.kuwo.cn/edde772eaab20af3f141ec9f2561df44/66912c2a/resource/n2/70/55/756351052.mp3?bitrate$128&from=vip" response = requests.get(url) if response.status_code == 200: with open("python_song.mp3", "wb") as f: f.write(response.content) print("音频下载成功") else: print("音频下载失败") ``` #### 加密音频资源解码 某些音频资源可能需要解密才能正常播放。以下是一个基于 JSON 的解密示例[^5]: ```python import json data = { "d": '{"ids":"[523946593]","br":128000,"csrf_token":""}', "e": "010001", "f": "00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7', "g": "0CoJUm6Qyw8W8jud" } json_data = json.dumps(data) print(json_data) ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值