1123581321递归算法java_【python 2】python 进阶

文章目录

一、函数

1、函数的参数

2、全局变量和局部变量

3、内部函数

4、闭包

5、匿名函数

6、系统自带的函数

7、递归函数

二、文件操作

三、os 模块

1、os.path

2、os 里边的函数

四、异常

五、推导式

1、列表推导式

2、集合推导式

3、字典推导式

六、生成器

七、迭代器

一、函数

def 函数名():

函数体

调用:函数名() —>找到函数,并执行函数体的内容

写了函数名() 就是调用,调用的过程是,系统先顺着名字找到地址,找到地址就找到了内容,之后执行内容。

1、函数的参数

定义:

def 函数名(参数):

函数体

调用:

求随机数的函数,产生的个数不确定:

定义的时候定义的参数:形参(占位)

调用的时候需要的参数:实参(具体的参数)

import random

def generate_random(number):

for i in range(number):

ran = random.randint()

print(ran)

print(generate_random)

输出:>>>

generate_random(3)

输出:>>>

7

6

5

练习 1:封装一个用户登陆函数

'''

定义一个登陆函数,参数是 uername, password

函数体:

判断参数传过来的 username、password 是否正确,如果正确则登陆成功,否则登陆失败

'''

# 函数的定义

def login(username, password):

uname = 'admin123'

pword = '112233'

for i in range(3):

if username == uname:

print('登陆成功!')

break

else:

print('用户名或密码不匹配,登陆失败!')

username = input('请输入用户名:')

password = input('请输入密码:')

else:

print('超过三次错误,用户锁定!')

# 函数的调用

username = input('请输入用户名:')

password = input('请输入密码:')

login(username, password)

>>>

请输入用户名: admin123

请输入密码: 112233

登陆成功!

练习 2:封装一个求最大值的函数

# 定义

def max(iterable):

max = iterable[0]

for i in iterable:

if i > max:

max = i

print('最大值是:', max)

# 调用

list1 = [3,6,3,2,7]

max(list1)

>>>

最大值是: 7

# 定义

def min(iterable):

min = iterable[0]

for i in iterable:

if i < min:

min = i

print('最小值是:',min)

# 调用

list1 = [3,6,3,2,7]

min(list1)

>>>

最小值是: 2

判断是不是 list、tuple等类型:isinstance()

# isinstance(名称,类型)

print(isinstance(list1,list))

>>>

True

练习3:模拟 enumerate

s = [1,3,5,7,9]

for i in s:

print(i)

print('-----------------')

for index,value in enumerate(s):

print(index,value)

print('-----------------')

list1 = []

index = 0

for i in s:

t1 = (index,i)

list1.append(t1)

index+=1

print(list1)

print('-----------------')

for index,value in list1:

print(index,value)

>>>

1

3

5

7

9

-----------------

0 1

1 3

2 5

3 7

4 9

-----------------

[(0, 1), (1, 3), (2, 5), (3, 7), (4, 9)]

-----------------

0 1

1 3

2 5

3 7

4 9

# 定义

def enumerate(value):

list1 = []

index = 0

for i in value:

t1 = (index,i)

list1.append(t1)

index += 1

for index,value in list1:

print(index,value)

#调用:

value = [1,3,5,7,9]

enumerate(value)

>>>

0 1

1 3

2 5

3 7

4 9

列表是可变的,字符串是不可变的,

# 列表可变

list1 = [1,2,3,4]

list2 = list1

list1.remove(3)

print(list2)

>>>

[1, 2, 4]

# 字符串不可变

s1 = 'abc'

s2 = s1

s1 = 'abcd'

print(s2)

>>>

abc

可变参数的定义方式:

# 定义

def add(*args):

print(args)

# 调用

add()

add(1,)

add(1,2)

>>>

() # 空元组

(1,)

(1, 2)

可变参数必须放在不可变参数的后面

def add(name, *args):

print(name, args)

add('aa',1,2,3)

>>>

aa (1, 2, 3)

默认值:

def add(a, b=10):

result = a+b

print(result)

add(3)

add(4,7) # b=7,会覆盖掉默认的b=10

>>>

13

11

# 想给c赋值,不想给b赋值,通过关键字赋值

def add1(a,b=10,c=4):

result = a+b+c

print(result)

add1(2,c=10)

>>>

22

打印每位同学的姓名和年龄:

students={'001':('王俊凯', 20),'002':('易烊千玺',19), '003':('王源',19)}

def print_boy(person):

if isinstance(person, dict):

for name, age in person.values():

print('{}的年龄是: {}'.format(name,age))

print_boy(students)

>>>

王俊凯的年龄是: 20

易烊千玺的年龄是: 19

王源的年龄是: 19

关键字参数:

# **kwargs:关键字参数,必须按 a=10,c=9 这样来赋值

# 得到字典形式的结果

def func(**kwargs):

print(kwargs)

func(a=1,b=2,c=3)

>>>

{'a': 1, 'b': 2, 'c': 3}

能用字典传入吗?

给函数赋值的时候,传递实参的时候,用到 ** 的时候,把这个字典拆包,拆成关键字的形式。拆成 001=python, 003=java…,

dict = {'001':'python','002':'java','003':'c++','004':'go'}

def func1(**kwargs):

print(kwargs)

# 调用

func1(**dict)

>>>

{'001': 'python', '002': 'java', '003': 'c++', '004': 'go'}

使用的时候:

调用的时候用 **dicts:拆包, 穿实参的时候加 **,系统会先拆成关键字的形式(001=python,002=java…)

定义的时候用 **kwargs:装包,把拆完的又给装成字典

def bb(a, b, *c, **d):

print(a,b,c,d)

bb(1,2)

bb(1,2,3,4)

bb(1,2,x=10,y=20)

bb(1,2,3,x=100)

>>>

1 2 () {}

1 2 (3, 4) {}

1 2 () {'x': 10, 'y': 20}

1 2 (3,) {'x': 100}

函数返回值:将函数运算的结果,利用return的形式返回来,return result。

# 把函数的输出结果扔出来

def add(a,b):

result1 = a+b

return result1

result = add(1,2)

print(result)

>>>

3

练习 1:加入购物车

'''

加入购物车

判断用户是否登录,如果登录,则成功加入购物车,如果没有登陆,则提示登陆之后再添加

'''

islogin = False # 用于判断用户是否登录的变量,默认是没有登陆的

def add_shoppingcart(goodsName):

global islogin

if islogin:

if goodsName:

print('成功加入购物车!')

else:

print('登陆成功,没有选中任何商品!')

else:

answer = input('用户没有登陆,是否登陆?(y/n)')

if answer == 'y':

username = input('请输入用户名:')

password = input('请输入密码:')

islogin = login(username, password)

else:

print('很遗憾,不能添加任何商品!')

def login(username, password):

if username == '李佳琪' and password == '123456':

return True

else:

print('用户名或密码有误,请重新输入:')

return False

# 调用函数,添加到购物车

username = input('请输入用户名:')

password = input('请输入密码:')

islogin = login(username, password)

add_shoppingcart('阿玛尼唇釉')

>>>

请输入用户名: 离

请输入密码: ww

用户名或密码有误,请重新输入:

用户没有登陆,是否登陆?(y/n) y

请输入用户名: 李佳琪

请输入密码: 123456

验证码验证:

def generate_checkcode(n):

s = '0123456789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM'

code = ''

for i in range(n):

ran = random.randint(0,len(s)-1)

code += s[ran]

return code

def login():

username = input('输入用户名:')

password = input('请输入密码:')

code = generate_checkcode(5)

print('验证码是:',code)

code1 = input('请输入验证码!')

# 验证

if code.lower() == code1.lower():

if username == 'lijiaqi' and password == '123456':

print('用户登陆成功!')

else:

print('用户名或密码有误!')

else:

print('验证码输入错误')

login()

>>>

输入用户名: lijiaqi

请输入密码: 123456

验证码是: Wavvv

请输入验证码! Wavvv

用户登陆成功!

2、全局变量和局部变量

局部变量:函数内部声明的变量,只能在函数体内改变

全局变量:声明在函数外侧的,所有函数都可以访问,在函数体中不能修改,如果要改,要在函数的开头加 global name,只有修改的时候,才需要加。

什么情况加 global:全局变量是不可变的(字符串、float等)但要修改的时候,需要加 global。如果全局变量是可变的,比如 list、修改的时候是不用加 global 的。

3、内部函数

在函数里边又声明一个函数,这个内部函数就是在大函数里边的。

特点:

内部函数可以访问这个函数中声明的变量

内部函数可以修改外部函数的可变类型的变量,比如list

内部函数不能修改外部函数的不可变变量,要修改得加 nonlocal。

内部函数不能修改全局变量,要修改得在内部函数里边加 global.

修改全局变量: global a

修改局部变量: nonlocal b

def func3():

p = 100

list1 = [3,1,2,4]

# 声明内部函数

def inner_func():

for index in range(len(list1)):

list1[index] +=5

print(list1)

inner_func()

func3()

>>>

[8, 6, 7, 9]

def func3():

p = 100

list1 = [3,1,2,4]

# 声明内部函数

def inner_func():

for index,value in enumerate(list1):

list1[index] = value + 5

print(list1)

inner_func()

func3()

>>>

[8, 6, 7, 9]

a = 100

print(globals())

def func():

b = 90

def inner_func():

global a

nonlocal b

c = 88

# 尝试修改

c += 12

b += 10

a += 10

print(a, b, c)

inner_func()

print(locals())

func()

>>>

110 100 100

{'inner_func': .inner_func at 0x00000238961E37B8>, 'b': 100}

locals() 函数:是一个内置函数,可以查看当前函数中声明内容有哪些

locals() 输出的形式: key:values

globals() 函数:查看全局变量有哪些,以字典的形式输出。

4、闭包

闭包是在函数中提出的概念,也就是在外部函数的外部访问内部函数。

闭包的格式:在函数里边定义了一个内部函数,把内部函数通过 return 给扔出来了,就叫闭包。

闭包的条件:

必须要有内部函数

内部函数必须引用外部函数的变量

外部函数是有返回值的,返回的值是内部函数名

格式:

def 外部函数():

...

def 内部函数():

...

return 内部函数名

def func():

a = 100

def inner_func():

b = 90

print(a,b)

return inner_func

# 调用,相当于把 inner_func 给了a,a就是内部函数了,然后调用该内部函数,就给 a 加括号就好啦

a = func()

a()

>>>

100 90

def func(a,b):

c = 10

def inner_func():

s = a+b+c

print('相加之和的结果是:', s)

return inner_func

ifunc = func(6,9)

ifunc()

ifunc = func(5,6)

ifunc()

>>>

相加之和的结果是: 25

相加之和的结果是: 21

闭包的特点:

能够保存返回闭包时的状态,不会受后面输入参数变化的影响。

5、匿名函数

简化函数的定义

定义格式:lambda 参数1,参数2 : 运算

有lambda,底层就会给你创建一个函数,这个函数是没有名字的,匿名的,前面是参数,:后面的就相当于 return 返回的结果。

# s 是一个函数

s = lambda a,b : a+b

result = s(1,2)

print(result)

>>>

3

匿名函数可以作为参数:

def func(x, y, func):

print(x, y)

print(func)

s = func(x, y)

print(s)

func(1, 2, lambda a, b : a + b)

>>>

1 2

at 0x0000023896096378>

3

list1 = [3,4,5,6,8]

m = max(list1)

print('列表最大值:',m)

list2 = [{'a':10,'b':20},{'a':13,'b':20},{'a':9,'b':20},{'a':29,'b':20}]

# 找 a 的最大值

m = max(list2, key = lambda x:x['a'])

print('列表的最大值:',m)

>>>

列表最大值: 8

列表的最大值: {'a': 29, 'b': 20}

6、系统自带的函数

1、map() 函数,对列表中元素进行操作,免去了之前的for循环

# map(操作函数,操作对象)

map(lambda ..., list1)

list1 = [3,4,5,6,7,9]

result1 = map(lambda x : x+2, list1)

print(list(result1))

>>>

[5, 6, 7, 8, 9, 11]

如果是偶数,则返回偶数本身,如果不是偶数,则进行+1操作:

# 方法一

func = lambda x : x if x%2 == 0 else x+1

result = func(5)

print(result)

>>>

6

# 方法二,对列表中的奇数进行+1,偶数不变

result = map(lambda x : x if x%2 == 0 else x+1, list1)

print(list(result))

>>>

[4, 4, 6, 6, 8, 10]

2、reduce() 函数,对列表(可迭代的)中的元素进行 ±*/

from functools import reduce

tuple1 = (3,5,6,7,8)

result = reduce(lambda x, y: x+y, tuple1)

print(result)

>>>

29

3、filter() 函数,过滤符合条件的元素,且原始的list不会被改变

list1 = [3,4,5,6,8]

result = filter(lambda x:x>5, list1)

print(list(result))

>>>

[6, 8]

students = [{'name':'lucy','age':21},

{'name':'tomy','age':20},

{'name':'jack','age':19},

{'name':'json','age':18},]

result = filter(lambda x:x['age']>20,students)

print(list(result))

>>>

[{'name': 'lucy', 'age': 21}]

按照年龄从小到大排序:

result = sorted(students, key=lambda x:x['age'])

print(result)

>>>

[{'name': 'json', 'age': 18}, {'name': 'jack', 'age': 19}, {'name': 'tomy', 'age': 20}, {'name': 'lucy', 'age': 21}]

总结:

max(), min(), sorted():都可以结合key来选择

map():将列表中的每个元素进行统一操作

reduce(): 对列表中的元素进行累加啊

filter():过滤

7、递归函数

普通函数:def func(): pass

匿名函数: lambda 参数:返回结果

递归函数:普通函数的一种表现形式,函数自己调用自己

递归函数的特点:

一定要有终点(加判断)

通常都会有一个入口

def sum(n):

if n == 0:

return 0

else:

return n+sum(n-1)

sum(10)

>>>

55

二、文件操作

1、mode:

r : read 读,纯文本文件

w: write 写,纯文本文件

rb:read binary 二进制读,包括纯文本、图片、音乐、MV等

wb:write binary 二进制写

a: append 追加

这里的读写,其实就是确定管道的类型:读、写

系统函数:

open(file, mode, buffering...)

open 就相当于给 file.txt 和 pycharm 建立了一个管道,.read() 就相当于把文件中的东西给读出来,通过管道传递出来。

2、读

stream = open(filename, 'r')

# 返回值是一个stream,流管道

# 然后用 read 去读

container = stream.read()

stream = open(r'file.txt')

# .read() 读所有内容

container = stream .read()

print(container)

# .readable() 判断是否可以读取

container = stream.readable()

print(container)

>>>

hello world!

hello kitty!

hello May!

-----------------------

True

-----------------------

stream = open(r'file.txt')

# .readline() 一行一行读

line = stream.readline()

print(line)

>>>

hello world!

readline() 通常用 for 循环

stream = open(r'file.txt')

while True:

line = stream.readline()

print(line)

if not line:

break

>>>

hello world!

hello kitty!

hello May!

# .readlines(),全部读取,保存在列表里

stream = open(r'file.txt')

lines = stream.readlines()

print(lines)

print('---------------------------')

for i in lines:

print(i)

>>>

['hello world!\n', 'hello kitty!\n', 'hello May!']

---------------------------

hello world!

hello kitty!

hello May!

读取图片,要使用 rb 方式

stream = open(r’image.jpg’,‘rb’)

container = stream.read()

3、写

stream.write('内容‘)

stream.writelines(Iterable),没有换行的效果,可以自己加\n

特点:

在对 stream 的操作时,都会把原来的内容覆盖掉。也就是上次写的内容覆盖掉,但不会把这一次读写的内容覆盖掉。

从得到一个 stream 到关闭这个 stream 叫一次读/写,这一次的读/写中,可以多次对这个 stream 进行操作。

stream = open('file.txt','w')

s = 'hello xiao ming!'

stream.write(s)

stream.write('hello xiao hua!')

stream.close()

9c9be46ac819332bb63cb20d45013ae6.png

换行写:

stream = open('file.txt','w')

stream.write('hello jenny!')

stream.writelines(['hello denny!\n','hello xiao hong!\n'])

3a733201888197c9d8e8845ae872058f.png

4、追加模式 a

在写的时候,不会把之前的内容擦掉,会在后面追加

stream = open('file.txt','a')

stream.write('hello jenny!\n')

stream.writelines(['hello denny!\n','hello xiao hong!\n'])

11f2ef7d9a03365f7ee3211eeff4cfe0.png

5、文件的复制

原文件:\img\image.jpg

目标文件:\img\image1.jpg

每次要打开,要关闭 stream 会比较麻烦,可以直接用 with,with可以帮助我们自动释放资源。

with open('image.jpg','rb') as stream:

container = stream.read()

with open('image1.jpg','wb') as wstream:

wstream.write(container)

print('文件复制完成!')

>>>

文件复制完成!

9d871c17f556ea02aae18f25c3f05410.png

三、os 模块

operation system

模块的概念:.py就是一个模块

stream.name 可以得到文件的路径+名称

os.path:

os.path.dirname(‘file’) :获取当前文件所在的文件目录(绝对路径)

os.path.join(path,‘img.jpg’):返回一个拼接后的新路径

# 1、绝对路径

os.path.dirname()

with open('image.jpg','rb') as stream:

container = stream.read()

path = os.path.dirname('__file__')

path1 = os.path.join(path,'image2.jpg')

with open(path1,'wb') as wstream:

wstream.write(container)

print('文件复制完成!')

with open('p1/image1.jpg','rb') as stream:

container = stream.read()

print(stream.name)

file = stream.name

filename = file[file.rfind('/')+1:] # 截取文件名

path = os.path.dirname('__file__')

path1 = os.path.join(path, filename)

with open(path1,'wb') as wstream:

wstream.write(container)

print('文件复制完成!')

>>>

p1/image1.jpg

文件复制完成!

1、os.path

os.path

absolute:绝对路径

表示当前文件的上一级,…/

import os

# 1、判断是否是绝对路径

os.path.isabs(r'p1/image.jpg')

>>>

False

获取文件所在文件夹的当前路径:

path = os.path.dirname('__file__')

print(path)

>>>

C:\Users\man.wang\python\python\part4.py

获取绝对路径:

path = os.path.abspath('file.txt')

print(path)

>>>

C:\Users\man.wang\python\python\file.txt

获取当前文件的绝对路径:

path = os.path.abspath('__file__')

print(path)

获取当前文件的文件夹所在的路径:

path = os.getcwd() #

print(path)

>>>

C:\Users\man.wang\python\python

文件名切分:split

os.path.split(path):把文件名前的路径和文件名分别存成元组的两个元素

os.path.splitext():文件和扩展名分开,存放成元组的两个元素

# os.path.split()

path = r'C:\Users\man.wang\python\python\file.txt'

result = os.path.split(path)

print(result)

print(result[1])

>>>

('C:\\Users\\man.wang\\python\\python', 'file.txt')

file.txt

# os.path.splitext()

path = r'C:\Users\man.wang\python\python\file.txt'

result = os.path.splitext(path)

print(result)

>>>

('C:\\Users\\man.wang\\python\\python\\file', '.txt')

得到文件的大小,单位是字节个数:

os.path.getsize(path)

path = r'C:\Users\man.wang\python\python\file.txt'

result = os.path.getsize(path)

print(result)

>>>

92

2、os 里边的函数

获取当前文件所在的目录:os.getcwd()

result = os.getcwd()

print(result)

>>>

C:\Users\man.wang\python\python

获取文件夹中的所有文件/文件夹的名字:os.listdir()

path = r'C:\Users\man.wang\python\python'

result = os.listdir(path)

print(result)

>>>

['.ipynb_checkpoints', 'file.txt', 'image.jpg', 'image1.jpg', 'image2.jpg', 'p1', 'p2', 'part 1.ipynb', 'part2.ipynb', 'part3.ipynb', 'part4.ipynb']

创建文件夹:os.mkdir(),如果存在则报错

所以用 os.mkdir() 时候,最好先判断文件夹是否存在

dirc = 'p3'

if not os.path.exists(dirc):

os.mkdir('p3')

删除空文件夹:os.rmdir()

os.rmdir('p3')

删除非空文件夹:要一层一层的删 os.removedirs('p3)

删除文件:os.remove()

os.remove(r'C:\Users\man.wang\python\python\p1\image.jpg')

# 删除 p1 文件夹中的所有文件

path = r'C:\Users\man.wang\python\python\p1'

filelist = os.listdir(path)

for file in filelist:

path1 = os.path.join(path,file)

os.remove(path1)

# 删除p1

else:

os.rmdir(path)

print('删除成功')

>>>

删除成功

切换目录:os.chdir()

# 切换目录,可以切换到指定目录下

f = os.chdir(r'C:\Users\man.wang\python\python\p2')

print(os.getcwd())

>>>

C:\Users\man.wang\python\python\p2

四、异常

语法没报错,运行的时候报错

def chu(a,b):

return a/b

chu(1,0)

>>>

ZeroDivisionError: division by zero

异常处理:

try:

可能出现异常的代码

except:

如果有异常,则执行此处的代码

finally:

无论是否存在异常,都会被执行的代码

如果不加异常,这段代码有问题的话,下面的所有的代码都不会被执行。

def func():

try:

n1 = int(input('输入第一个数字:'))

n2 = int(input('输入第二个数字:'))

# 加法

result = n1 + n2

print('两数之和为:',result)

except:

print('必须输入数字!')

func()

>>>

输入第一个数字: 2

输入第二个数字: w

必须输入数字!

def func():

try:

n1 = int(input('输入第一个数字:'))

n2 = int(input('输入第二个数字:'))

oper = input('请输入运算符号:(+-*/)')

result = 0

if oper == '+':

result = n1 + n2

elif oper == '-':

result = n1 - n2

elif oper == '*':

result = n1 * n2

elif oper == '/':

result = n1 / n2

else:

print('符号输出错误!')

print('结果为:',result)

except ZeroDivisionError:

print('除数不能为 0!')

except ValueError:

print('必须输入数字!')

func()

>>>

输入第一个数字: 1

输入第二个数字: 0

请输入运算符号:(+-*/) /

除数不能为 0!

如果用了 else,在 try 代码中不能出现 return,如果走了 try,然后直接就终止代码了。

情况1:

try:

pass

except:

pass

情况2:打印错误原因

try:

pass

except Exception as err:

print(err)

情况3:没有异常的时候,会执行的 else 的代码,但 try 里边不能用 return,因为没有异常的时候,

try:

pass

except ValueError:

pass

else:

print('')

异常抛出:

# 实现用户名小于6位时抛出异常

def register():

username=input('请输入用户名:')

if len(username)<6:

raise Exception('用户名长度必须6位以上!')

else:

print('输入的用户名是:',username)

register()

>>>

input-> www

Exception: 用户名长度必须6位以上!

五、推导式

从旧的列表推导得到一个新的列表

1、列表推导式

格式:

[表达式 for 变量 in 旧列表]

[表达式 for 变量 in 旧列表 if 条件]

符合 if 条件的变量,扔到最前面的表达式中

# 过滤掉长度 <= 3 的人名

names = ['tom','lily','jack','json','bob']

# 第一个 name 就放的是names中符合长度 >3 条件的 name

result = [name for name in names if len(name)>3]

print(result)

result = [name.capitalize() for name in names if len(name)>3]

print(result)

result = [name.title() for name in names if len(name)>3]

print(result)

>>>

['lily', 'jack', 'json']

['Lily', 'Jack', 'Json']

['Lily', 'Jack', 'Json']

# 列表推导式等价实现

names = ['tom','lily','jack','json','bob']

new_name=[]

def func(names):

for name in names:

if len(name)>3:

name = name.title()

new_name.append(name)

return new_name

func(names)

>>>

['Lily', 'Jack', 'Json']

# 将 1~100 之间,能被 3 整除的扔出来

newlist = [i for i in range(1,101) if i%3 == 0]

print(newlist)

>>>

[3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60, 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, 93, 96, 99]

# 将 1~100 之间,能被 3 整除,并且能被5整除的拿出来放到一个列表

newlist = [i for i in range(1,101) if i%3 == 0 and i%5 == 0]

print(newlist)

>>>

[15, 30, 45, 60, 75, 90]

# 求 0~5 之间的偶数,和 0~5 之间的奇数,构成一个元组,放到列表里边

def func():

new_list=[]

for i in range(5):

if i%2 == 0:

for j in range(5):

if j%2 != 0:

new_list.append((i,j))

return new_list

func()

>>>

[(0, 1), (0, 3), (2, 1), (2, 3), (4, 1), (4, 3)]

# 列表推导式写

# 在for后面再写for,就相当于循环中的嵌套

new_list = [(x,y) for x in range(5) if x%2==0 for y in range(5) if y%2 != 0]

print(new_list)

>>>

[(0, 1), (0, 3), (2, 1), (2, 3), (4, 1), (4, 3)]

练习:不带条件的列表推导式,直接取就好啦

'''

list1 = [[1,2,3],[4,5,6],[7,8,9]] -----> list2=[3,6,9]

'''

list1 = [[1,2,3],[4,5,6],[7,8,9]]

new_list = [i[-1] for i in list1]

print(new_list)

>>>

[3, 6, 9]

练习:带 else 的列表推导式,把 for 放到最后

dict1={'name':'tom','salary':5000}

dict2={'name':'lili','salary':8000}

dict3={'name':'jack','salary':3000}

list1 = [dict1, dict2, dict3]

# 如果薪资 > 5000 加工资 200,低于等于 5000 加工资 500

new_list = [person['salary']+200 if person['salary']>5000 else person['salary']+500 for person in list1 ]

print(new_list)

>>>

[5500, 8200, 3500]

2、集合推导式

# 遍历 list 里边的元素,把元素放到集合里边,相当于去重

list1 = [1,2,3,4,5,6,3,1,2,3]

set1 = {x for x in list1}

print(set1)

set2 = {x+1 for x in list1 if x>3}

print(set2)

>>>

{1, 2, 3, 4, 5, 6}

{5, 6, 7}

3、字典推导式

# key 和 value 进行交换

dict1 = {'a':'A','b':'B','c':'C','d':'C'}

new_dict = {value:key for key,value in dict1.items()}

print(new_dict)

>>>

{'A': 'a', 'B': 'b', 'C': 'd'}

六、生成器

通过列表生成式(列表推导式),可以直接创建一个列表,但是,收到内存的限制,列表容量肯定是有限的,而且,创建一个包含100w个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面的大多数元素占用的空间就白白浪费了。所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算后续的元素呢,这样就不必创建整个list了,从而能够大量的节省空间,在 python 中,这种一边循环,一边计算的机制,成为生成器(generator)。

得到生成器的方式:

通过列表推导式得到生成器(用小括号)

# [0,3,6,9,12,15,18,21,24,27]

# 1、列表推导式

new_list = [x*3 for x in range(20)]

print(new_list)

>>>

[0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57]

# 2、列表生成式,只要调一下,就产生一次

# 得到生成器

g = (x*3 for x in range(20))

print(type(g))

print(g)

# 方式一

print(g.__next__())

print(g.__next__())

print(g.__next__())

>>>

at 0x000002BFF85C4F48>

0

3

6

# 方式二:next(),每调用一次,就会产生一个元素

print(next(g))

print(next(g))

print(next(g))

>>>

9

12

15

# 生成器产生元素完毕,你再次调用的时候,就会报错

print(next(g))

>>>

StopIteration:

使用一个循环来搞定:

g = (x*3 for x in range(10))

while True:

try:

e = next(g)

print(e)

except:

print('没有更多元素啦!')

break

>>>

0

3

6

9

12

15

18

21

24

27

没有更多元素啦!

yield():函数里边有yield,说明函数就不是函数了,就变成了生成器

'''

使用函数得到生成器:

1、定义一个函数,函数中使用yield

2、调用函数,并接收调用的结果

3、得到生成器

4、借助 next()/__next()__ 得到元素

'''

# 调用 func() 的时候是不会走到函数里边去的

# 只有用 next() 的时候才会走到函数里边

def func():

n = 0

while True:

n += 1

yield n # return+暂停

g = func()

>>>

# yield 就相当于 return + 暂停,把 n 扔出去,并且停下来,不进行循环了,当你下次再用 next() 的时候,值再走到 while true里边,进行下一次循环。

def func():

n = 0

while True:

n += 1

yield n

g = func()

print(next(g))

print(next(g))

print(next(g))

print(next(g))

>>>

1

2

3

4

斐波那契数列:

def fib(length):

a, b = 0, 1

n = 0

while n

# print(b)

yield b

a, b = b, a+b

n += 1

return '没有更多元素!'

g = fib(8)

print(next(g))

print(next(g))

print(next(g))

print(next(g))

print(next(g))

print(next(g))

print(next(g))

print(next(g))

print(next(g))

print(next(g))

>>>

1

1

2

3

5

8

13

21

StopIteration: 没有更多元素!

生成器方法:

next():获取下一个元素

send():像每次生成器中传值的,第一次调用的时候必须先传一个 None

生成器应用:

进程>线程>协程

一个进程可以用多个线程来并行完成,一个线程又可以用多个协程来并完成。

# 任务是前后进行的,先搬完砖才能听歌

def task1(n):

for i in range(n):

print('正在搬第{}块转'.format(n))

def task2(n):

for i in range(n):

print('正在听第{}首歌'.format(n))

task1(3)

task2(3)

>>>

正在搬第0块转

正在搬第1块转

正在搬第2块转

正在听第0首歌

正在听第1首歌

正在听第2首歌

# 两个任务同时进行

def task1(n):

for i in range(n):

print('正在搬第{}块转'.format(i))

yield None

def task2(n):

for i in range(n):

print('正在听第{}首歌'.format(i))

yield None

g1 = task1(3)

g2 = task2(3)

while True:

try:

g1.__next__()

g2.__next__()

except:

break

>>>

正在搬第0块转

正在听第0首歌

正在搬第1块转

正在听第1首歌

正在搬第2块转

正在听第2首歌

生成器的构成:

通过列表推导式完成

通过 函数 + yield 完成

产生元素:

next(generator)

生成器自己的方法

generator._ next _(),产生完毕再次调用,会产生异常

generator.send(),给生成器送值

生成器的应用:在协程中使用

七、迭代器

可迭代的对象:

生成器

元组、列表、集合、字典、字符串

如何判断是否可迭代:isinstance()

from collections import Iterable

# 列表是可迭代的

list1 = [1,2,3]

isinstance(list1,Iterable)

>>>

True

# 整型是不可迭代的

isinstance(1,Iterable)

>>>

False

# 生成器是可迭代的

g = (x +1 for x in range(10))

isinstance(g,Iterable)

>>>

True

迭代器:可以被 next() 函数调用并不断返回下一个值的对象,称为迭代器 iterator

迭代器是访问集合元素的一种方式

迭代器是可以记住遍历位置的对象,迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问结束

迭代器只能往前,不能后退

生成器:可迭代,也是迭代器(可以用 next() 方法)

列表:可迭代,但不是迭代器(不可以 next() 方法)

怎么把一个可迭代的对象变成迭代器:iter(obj)

list1 = [1,2,3]

print(type(list1))

list1 = iter(list1)

print(type(list1))

print(next(list1))

print(next(list1))

>>>

1

2

生成器:为了节省内存,一个个拿到元素,生成的方式有两种,一种是 列表生成式的方式,另一种是借助函数+yield方式。

迭代器:只要能够调用 next得到下一个元素的,就叫迭代器

迭代器是一个大的范围, 生成器是迭代器的一种,生成器也是迭代器。

列表/元组等不是一个迭代器,但也可以变成一个迭代器。

迭代器:

借助 iter() 转换,可以得到

不借助,本身就是迭代器

7616a5bc5a88572828b36a8751772e1c.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值