函数:先定义,后调用
# 函数的语法:参数和return可以没有,参数为原材料,返回值为产品
def 函数名(参数1,参数2,...):
"""函数描述"""
函数体
return 值
# 定义函数发生的过程:
# 1.开辟内存空间保存函数体
# 2.将内存地址绑定给函数名
# 定义函数不会执行函数体代码,只会检测语法错误
# 调用函数过程
# 1.通过函数名找到函数的内存地址
# 2.然后函数名加()就是出发函数体代码运行
# 示范:定义函数是把函数体放入内存,不会调用函数
# 当函数调用时foo()和bar()都在内存中可以找到,所以不会报错
def foo():
bar()
print('from a')
#foo() #如果放着调用就会报错,因为内存只写入了foo()没有找到bar
def bar():
print('from b')
foo()
定义函数的三种方式
# 形式一:无参函数
def func():
print('hhh')
func() # 调用函数
# 形式二:有参函数
def func(x, y):
print(x, y)
func(1, 2)
# 形式三:空函数:构思代码占位用
def func(x, y):
pass
调用函数的三种方式
def func(x, y):
res = x + y
return res
# 语句形式:只加括号调用函数
func(1, 2)
# 表达式形式:
res = func(1, 2) # 赋值表达式
# res = func(1, 2) * 10 # 数学表达式
print(res)
# 函数调用可以当作参数,可以当作函数当作另一个的返回值
res = func(func(1, 2), 10) # 参数传入1、2,然后再传入3、10
print(res)
# g=func(1, 2)
# res = func(g,10)
# print(res)
返回值的三种方式
# return是函数结束的标志,运行到return就会立即停止
# yield可以返回值,可以返回多个值,使用next(函数)会触发函数体代码的运行,遇到yield函数暂停
# return的值,会当作本次运行的结果返回
# 优先级return>break>False
# 注意:返回值需要输出才会有值,返回多个值,会形成一个元组
# 没有返回值
def func(x, y):
res = x + y
return # 没有返回值得不到结果为None
res = func(1, 2)
print(res) # None
# 返回一个值
def func():
return 10
res=func()
print(res)
# 返回多个值,会形成一个元组
def func():
return 10, 'aa', [1, 2], {'a': 1}
res = func()
print(res[1])
函数的类型提示
def func(name:'传入名字',age:int,sex:str): # :后面的为类型提示,并不是硬性要求,只是提示
print(name)
print(age)
print(sex)
return 11
func('admin','2',1)
内置函数
# 1.divmod 输出商和余数
print(divmod(10000,33)) # 显示两个值,前面是10000出33的值,后面的为余数
# 2.dir输出参数有那些属性
class Foo:
pass
obj=Foo()
obj.xxx=111
print(dir(obj))
# 3.enumerate拿到值的索引
for i,v in enumerate(['a','b','c']):
print(i,v)
# 4.eval执行字符串的表达式
res=eval('1+2')
print(res)
# 5.isinstance判断类型
print(isinstance([],list))
函数参数的使用
函数的参数分为形式参数和实际参数,简称形参和实参
# 形参:位置形参、默认形参。在定义函数阶段定义的参数称为形式参数,相当于变量名
def func(x, y):
print(x, y)
# 实参:位置实参、关键字实参。在调用函数阶段传入的值称为实际参数,相当于变量值
func(1, 2) #只要是一个值,就可以为实参
# 注意:位置形参必须在默认形参前边,位置实参必须在关键字实参之前
# 在调用阶段,实参(变量值)会绑定给形参(变量名),函数调用结束后,就会解除绑定
# 这种绑定关系只能在函数体内使用
形参
# 默认形参:在定义函数阶段,就已经被赋值的形参,被赋予的是值的内存地址
# 默认形参不要定义为可变类型:列表、字典
# 以实参传入的值为准
def func(x, y=3): #y为默认形参,位置形参必须在默认形参前边
print(x, y)
func(x=1,y=4) # 关键字实参
func(1,2) # 位置实参
1.2、实参
def func(x, y): #位置形参
print(x, y)
a=1
b=2
func(a, b) #可以间接引用
func(x=1, y=2) #关键字实参
func(1, 2) #位置实参
func(1, y=2) #混合使用,位置实参必须在关键字实参之前
可变长度的参数(*与**的用法)
```
# 可变长度指的是在调用函数时,传入的值(实参)的个数不固定
# 实参是用来为形参赋值的,针对溢出的实参要有对应的形参来接收
```
*形参名:用来接收溢出的位置实参,溢出的保存为元组格式
def func(x,y,*z): # 溢出的位置实参会被*保存为元组格式,然后赋值给后面的形参
print(x,y,z)
func(1, 2, 3, 4, 5)
# *也可以在实参中使用,*可以把后面的值分散为位置实参对应形参
def func(x,y,z):
print(x,y,z)
func(1,y=2,*'h') # 报错,因为*后面为位置实参,位置实参应该在y=2表达式实参之前
#func(*[11,22,33]) # 集合为一个实参,*可以把后面的值分散为位置实参对应形参
#func(*{'a':11,'b':22,'c':33}) # 字典为一个实参,*可以把后面的key值分散为位置实参对应形参
#func(*(11,22,33)) # 元组同理
#func(*'hel') # 字符串同理
# l=[11,22,33]
# func(*l)
# 形参与实参都有*
def func(x,y,*z):
print(x,y,z)
func(1,2*[11,22,33],*[44,55]) #第二实参是集合变为两份,第三个实参先分散后保存为元组
**形参名:用来接收溢出的关键字实参,溢出的保存为字典格式
def func(x,y,**z): # 溢出的位置实参会被**保存为字典格式,然后赋值给后面的形参
print(x,y,z)
func(x=1,y=2,z=3,a=4,b=5)
# **也可以在实参中使用(实参**后只能为字典),**可以把后面的值分散为关键字实参对应形参
def func(x,y,z):
print(x,y,z)
func(**{'x':11,'y':22,'z':33}) # 字典为一个实参,**可以把后面的key:value值分散为位置实参key=value对应形参
# 形参与实参都有**
def func(x,y,**z):
print(x,y,z)
func(**{'x':11,'y':22,'z':33,'a':44}) # 先分散后保存为字典
*和**混合使用,*必须在**之前
def func(x,*y,**z):
print(x,y,z)
func(1,2,3,4,a=5,b=6)
# 在两个函数中*与**的间接调用
def index(x, y):
print(x, y)
def wrapper(*x, **y):
index(*x, **y)
# 实际传入wrapper和传入index的一模一样,对wrapper传实参的格式要看index形参格式
# wrapper(1,2) # wrapper(*(1,2),**y),实际传入的为index(1,2)
# wrapper(1,2,3) # wrapper(*(1,2,3),**y),实际传入index的x为三个值会报错
# wrapper(1,y=2) # wrapper(*(1),{'y': 2}),实际传入的为index(1,2),将字典的key与value对应传入index
# wrapper(1,x=2) # wrapper(*(1),{'x': 2}), 实际传入index的x为两个值会报错
名称空间与作用域
```
# 名称空间:namespace:存放变量名的地方,是对栈区的划分
# 有了名称空间,就可以在栈区存放相同的变量名
```
名称空间分为三种:内置名称空间、全局名称空间、局部名称空间
内置名称空间
# 存放的名字:存放python解释器内置的名字
# 存活空间:python解释器启动则产生,python解释器关闭则销毁
# 例如:import os #os为内置名字,即内置名称空间
全局名称空间
# 存放的名字:只要不是函数内定义、也不是内置的,剩下的都是全局名称空间
# 存活空间:python文件执行则产生,python文件执行结束后销毁
x = 10 # x、y都为全家名称空间,因为不是函数内定义的也不是内置的
if 13 > 3:
y = 20
def func(): # func为全局内存空间,因为是函数名并不是函数内定义的
a = 1 # a为函数内定义的所以不是全局名称空间
b = 2 # b为函数内定义的所以不是全局名称空间
class foo: # foo为全局内存空间,因为是类名并不是函数内定义的
pass
局部名称空间
# 存放的名字:在调用函数时,运行函数体代码过程中产生的函数内的名字
# 存活空间:函数调用时存活,函数调用完毕后销毁
def func(): # func为全局内存空间
a=111 # a为局部名称空间
b=222 # b为局部名称空间
func() #调用一次就产生一次
名称空间优先级
# 名称空间的加载顺序
# 局部名称空间>全局名称空间>内置名称空间
# 名称空间销毁顺序
# 内置名称空间>全局名称空间>局部名称空间
# 名字的查找优先级:当前所在位置一层层查找
# 局部名称空间
# 全局名称空间
# 内置名称空间
# 如果当前在局部名称空间:局部名称空间-->全局名称空间-->内置名称空间
# 如果当前在全局名称空间:全局名称空间-->内置名称空间
# 不同函数之间变量名独立,不会跨函数找,嵌套的时候特殊,会往上一级找
# 示范一
def func():
print(x) # 局部
x=111 # 全局
func() # 局部-->全局
# 示范二:名称空间的嵌套调用关系,是以函数定义阶段为准,与调用位置无关
x=1 # 为全局
def func(): # 为全局名称空间
print(x) # 为局部名称空间,先去func里面找,找不到就去全局找,不会去foo找
def foo(): # 为全局名称空间
x=2 # 为局部名称空间,局部作用域,不同函数之间不能跨函数找
func() # 定义阶段为准,也是局部名称空间
foo() #得到的值为1,因为print(x)为局部-->全局找到x=1,所以为1
# 示范三、函数嵌套,是以函数定义阶段为准,与调用位置无关
input = 1
def f1():
input = 2
def f2():
input = 3
print(input)
f2() # 不看调用是的级别,而是定义时的级别
f1() # 输出为3,可以理解为,寻找在同一级别的input,没有就往上一级找
作用域
# 全局作用域:内置名称空间、全局名称空间
# 全局有效,全局存活
# 局部作用域:局部名称空间
# 局部有效,只有自己函数内有效
# 不同函数之间变量名独立,不会跨函数找,嵌套的时候特殊,会往上一级找
# 示例
x=1 # 为全局名称空间
def func(): # 为全局名称空间
print(x) # 为局部名称空间
def foo(): # 为全局名称空间
x=2 # 为局部名称空间
func()
foo() #得到的值为1,因为print(x)为局部-->全局找到x=1,所以为1
global与nonlocal
# global:可以将全局名称空间赋值给函数内的局部名称空间
# 主要用在,局部名称空间要修改全局变量的值的时候
# 在用于可变类型时,会产生新的值,而不是添加
# nonlocal 用于声明一个变量在外层(非全局)作用域中。
# 它常用于嵌套函数中,允许内层函数修改外层函数的变量。
# 示例一
x=111
def func():
x=222
func()
print(x)
# 示例二
x=111
def func():
global x # 把来自全局的x赋值给了222,之后全局名称空间的x=222
x=222
func()
print(x)
# 示例三
x=[111,222]
def func():
x.append(333) # 因为x为集合,内存地址根本没有变化,可以读到
func()
print(x)
函数对象
# 可以把函数当成变量去用
# func()=内存地址
def func():
print('admin')
可以赋值
f=func # f=func的内存地址
print(f,func)
函数调用可以当作参数传给另一个函数
def foo(x):
print(x)
foo(func) #foo(func的内存地址)
可以当作函数当作另一个的返回值
def foo(x): # x=func的内存地址
return x #返回的func的内存地址
res=foo(func) # res=foo(func的内存地址) 即res=func
print(res)
res()
可以当作容器类型的一个元素
l=[func,]
l[0]() # 相当于通过列表取到func,然后加()调用
dic={'k1':func}
dic['k1']() # 相当于通过字典取到func,然后加()调用
# 示例
def a():
print('退出')
def b():
print('登录')
def c():
print('充值')
def d():
print('提现')
def e():
print('转账')
def f():
print('查看余额')
z={
'0':['退出',a],
'1':['登录',b],
'2':['充值',c],
'3':['提现',d],
'4':['转账',e],
'5':['查看余额',f]
}
while True:
for i in z:
print(i,z[i][0])
x=input("请输入命令:").strip()
if x=='0':
break
elif not x.isdigit(): # isdigit()方法检测字符串是否只由数字组成
print("请输入正确的命令:")
continue
elif x not in z:
print("命令不存在,请重新输入:")
else:
z[x][1]()
函数嵌套
# 函数嵌套的调用:在调用一个函数的过程中又调用其他函数
# 注意:函数嵌套可以用外层的函数为内层的函数另外传入参数,
# 当内侧函数的变量需要根据外部变化时,给他一个外层函数,使变量可以向外侧寻找
# 找最大值
def max2(x,y):
if x>y:
return x
else:
return y
def max4(a,b,c,d,*e):
#第一步比较a,b
res1=max2(a,b)
#第二步比较res1,c
res2=max2(res1,c)
#第三步比较res2,d
res3=max2(res2,d)
return res3
z=input("请输入4个值:")
res = max4(*z)
print(res)
闭包函数
闭包函数=名称空间与作用域+函数嵌套+函数对象
# 定义在函数内部,对外部作用域有引用
# 核心:名字的查找关系是以函数定义阶段为准
# 闭函数指该函数的外层函数,f1
# 包函数为函数的内嵌函数,f2
def f1():
def f2():
pass
闭包函数的名称空间与作用域、函数嵌套应用
x=1
def f1():
def f2():
print(x)
return f2 #调用f1()返回了f2的内存地址
def f3():
x=3
res1=f1() #调用f1()返回函数f2的内存地址,赋值给res1
res1() #需要按照函数定义时的作用关系去执行,与调用位置无关
res=f1() # 将f2的内存地址赋给res
res()
f3() #结果为1
闭包函数的函数对象应用
x=1
def outer():
x=2
def inner(): # 被outer嵌套之后,inner不再是全局名称空间
print(x)
return inner # 调用outer()返回了inner的内存地址,将inner变为全局名称空间, outer()=inner
func=outer() # 将inner的内存地址赋给func func=inner
func() # 结果为2,突破限制可以直接调用inner
#方式一
import requests # 向网站发送 HTTP 请求,并获取响应结果。
def get(url):
response = requests.get(url)
print(response.text)
get('https://www.baidu.com')
# 方式二
import requests
def outter(url):
def get():
response = requests.get(url)
print(response.text)
return get
f = outter('https://www.baidu.com')
f()
无参装饰器
装饰器的组成
*args、**kwargs,可以用于将传入wrapper的参数原封不动传入index
def index(x,y,a,b):
print(x,y,a,b)
def wrapper(*args,**kwargs): #*和**在形参中会聚合为 wrapper((111,222),{'a':333,'b':444})
index(*args,**kwargs) #*和**在实参参中会分散为 index(111,222,a=333,b=444)
wrapper(111,222,a=333,b=444)
名称空间有作用域:名称空间的嵌套关系是在函数定义阶段确定的
函数对象
# 可以把函数的内存地址当作参数传入
# 可以把函数的内存地址当作返回值返回
def index():
return 123
def foo(func):
return func
foo(index)
函数的嵌套和闭包定义
# 注意:函数嵌套可以用外层的函数为内层的函数另外传入参数
def func1(x,y):
print('ok')
def func2(x,y):
print('no')
def outter(func): #为wrapper内层的func传值
def wrapper(*x,**y): # 调用方式不能改变,如果要func可以被传值,只能在外面套一层,额外传值
func(*x,**y) # func为变量,变换可以调用不同函数
return wrapper # 返回的为wrapper内存地址,变为全局名称空间,outter(xxx)=wrapper,这样可以通过outter函数为wrapper另外传入参数
f=outter(func1) # f=outter(func1)=wrapper内层的func=func1
f(1,2) # f()=wrapper()
装饰器
注意:装饰器就是在不修改 被装饰器对象的源代码以及调用方式的前提下为被装饰对象添加功能
每次调用被装饰对象都会先调用装饰器功能
装饰器缺点:
会改变函数的元信息,属性丢失问题
可以通过@functools.wraps(func)进行修改
import time
from functools import wraps # 引入wraps包,将被装饰器的全部属性赋值给装饰器
# 由于语法糖的缘故,第二层的timmer装饰器只能接收一个被装饰对象的内存地址
def timmer(func): # 装饰器 timmer(func)就相当于为wrapper中的func传值
@wraps(func) # 将func的全部属性赋值给wrapper
# 首先创建wrapper函数作为计数功能,使func变量可以使用任意函数
def wrapper(*x, **y): # *x,**y接收用户输入
start = time.time() # 获取当前时间
time.sleep(3)
res = func(*x, **y) # wrapper()传入index(),找不到func就会去外层找,将func(*x, **y)的返回值赋值给res
stop = time.time()
print(stop - start)
return res # 返回func(*x, **y)的返回值即index()的返回值
return wrapper # 将wrapper作为返回值返回,返回的是内存地址,变为全局名称空间
# 语法糖写在被装饰器上面,装饰器要在语法糖上面
@timmer # index=timmer(index)=wrapper
def index(x, y): # 被装饰对象
print('index {} {}'.format(x, y))
return 0
@timmer
def func1(x, y): # 被装饰对象
print('index {} {}'.format(x, y))
return 1
@timmer
def func2(x, y): # 被装饰对象
print('index {} {}'.format(x, y))
return 2
func2(1, 2)
# index= timmer(index) 语法糖自动做了这一部分,可以直接调用
index(1, 2) # 因为语法糖已经自动做了转化index(1, 2)=wrapper(1, 2)传入index(1, 2)
res = index(1, 2) # res为index(1, 2)的返回值
print(res) # 返回index的返回值
# 登录认证
def auth(func):
def wrapper(*x, **y):
name = input("请输入账号:").strip()
pwd = input("请输入密码:").strip()
if name == 'admin' and pwd == 'admin':
res = func(*x, **y)
return res
else:
print('no')
return wrapper
@auth
def admin():
print("登陆成功")
return 0
admin()
无参装饰器模板
# 注意!!!! return后面的函数不能加()
from functools import wraps
def outter(func): # 第二层参数只能有一个,指向func被装饰对象
@wraps(func) # 将func的全部属性赋值给wrapper
def wrapper(*x, **y): # 参数要与被装饰对象一致,不能动
# 中间为装饰器功能
res = func(*x, **y) # 指定被装饰对象,转到被装饰函数中去
return res
return wrapper
有参装饰器
#装饰器最多只有三层,第三次参数没有固定,可以传入任意多个参数
from functools import wraps
def auth(admin,yy): #第三层没有限制。即使参数用不到
def index(func):
@wraps(func)
def wrapper(*x,**y):
if admin=='file':
count=0
while count<3:
name = input("请输入账号:").strip()
pwd = input("请输入密码:").strip()
with open(r'user.txt', mode='rt', encoding='utf-8') as f:
for k in f:
k = k.strip().split(':')
if name == k[0] and pwd == k[1]:
print('基于文件认证ok')
res=func(*x,**y)
return res
else:
print('基于文件认证no')
count+=1
else:
print("错误次数过多")
elif admin=='db':
count = 0
while count < 3:
name = input("请输入账号:").strip()
pwd = input("请输入密码:").strip()
if name=='123' and pwd=='123':
print('基于数据库认证ok')
res=func(*x,**y)
return res
else:
print('基于数据库认证no')
count+=1
else:
print("错误次数过多")
else:
print("未选择登陆方式")
return wrapper
return index
# 账号密码来源是文本
@auth(admin='file',yy=0)
def file_admin():
print("文本登陆页面")
# 账号密码来源是数据库
@auth(admin='db',yy=1)
def db_admin():
print("数据库登陆页面")
file_admin()
有参装饰器模板
# 注意!!!! return后面的函数不能加()
from functools import wraps
def 有参装饰器(x,y,z): #第三层参数没有限制,可以为任意个
def outter(func): # 第二层参数只能有一个,指向func被装饰对象
@wraps(func)
def wrapper(*x,**y): # 参数要与被装饰对象一致,不能动
# 中间为装饰器功能
res=func(*x,**y) # 指定被装饰对象,转到被装饰函数中去
return res
return wrapper
return outter
@有参装饰器(1,2,3)
def 被装饰对象():
pass
迭代器
# 迭代器:迭代取值的工具,取值时用
# 迭代是一个重复的过程,每次重复都是基于上一次的结果而进行下一次
count=0
while count<3:
print("x")
count+=1
# while循环的方式只能取到有索引的数据,但是for循环可以取到,如集合,字典,文件等没有索引的不能使用while循环取
x={'a':1,'b':2,'c':3}
x1 = {"admin", 'admin'}
for i in x:
print(i)
print(x[i])
# 所以引入迭代器,对没有索引的可迭代对象循环进行取值
# 注意:可迭代对象:但凡内有__iter__方法的都称为可迭代对象
# 可迭代对象:字符串、列表、字典、元组、集合、文件
# 迭代器对象:文件
#.__next__()用来接收返回值
def func():
print('a')
yield 1 # 可以让迭代器接收返回值,可以返回多个值,不结束代码,只是暂停到这
print('b')
yield 2
print('c')
g=func()
print(g.__next__()) # g.__next__使用一次就取一次值
print(next(g)) # next(g)和g.__next__()一样,形式不同
生成器
# 生成器就是迭代器,yield关键字
# 注意:yield关键字可以将函数暂停,很nb
# 在函数内一旦存在yield关键字,调用函数并不会执行函数代码
# 会返回一个生成器对象,生成器就是自定义的迭代器
def func():
print('a')
yield 1 # 返回值和return差不多,但是可以返回多个值,不结束代码,只是暂停到这
print('b')
yield 2
print('c')
yield 3
g=func()
# 会触发函数体代码的运行,遇到yield停下,将yield后面的值当作本次运行的结果
res1=next(g) # 将func的返回值接收赋值给res1
print(res1)
res2=next(g)
print(res2)
# 案例
def my_range(start,stop,step=1):
print("start:")
while start<stop:
yield start
start+=step # 将第一次的start值加上step值,然后传入下次循环
print('end:')
g=my_range(1,5,2)
print(next(g) ) # 第一次取start值
print(next(g) ) # 第二次取start值
叠加多个装饰器
from functools import wraps
def deco1(func1): # func1=被装饰对象wrapper2函数的内存地址
@wraps(func1)
def wrapper1(*args,**kwargs):
res1=func1(*args,**kwargs)
return res1
return wrapper1
def deco2(func2): # func2=被装饰对象wrapper3函数的内存地址
@wraps(func2)
def wrapper2(*args,**kwargs):
res2=func2(*args,**kwargs)
return res2
return wrapper2
def deco3(x):
@wraps(x)
def outter3(func3): # func3=被装饰对象index函数的内存地址
def wrapper3(*args,**kwargs):
res3=func3(*args,**kwargs)
return res3
return wrapper3
return outter3
# 加载顺序自下而上
@deco1 # index=deco1(wrapper2的内存地址) -->index=wrapper1的内存地址
@deco2 # index=deco2(wrapper3的内存地址) -->index=wrapper2的内存地址
@deco3(111) # index=outter3(index) -->index=wrapper3的内存地址
def index(x,y):
print("from index {}:{}".format(x,y))
# 运行执行顺序
# 自上而下 deco1-->deco2-->deco3
# 第一个调用wrapper1函数的func1变量,实际调用的是wrapper2函数的func2
# 然后func2实际调用的是func3,func3调用的就是index函数,index调用完之后返回res3、res2、res1
index(1,2)
yield表达式
# yield可以返回值,可以返回多个值,使用next(函数)会触发函数体代码的运行,遇到yield函数暂停
def dog(name):
print('聪聪{}吃了吗'.format(name))
count = 0
while True:
count += 1
print('第{}次循环开始'.format(count))
x=yield # x=None、x='一根骨头'
print('聪聪{}吃了{}'.format(name,x))
print('第{}次循环结束'.format(count))
g=dog('你')
g.send(None) # 等同于next(g),让第一次循环在yield位置暂停
g.send(None) # 将None当作值传给当前暂停的yield然后又传给x第一次循环继续
g.send('一根骨头') # 第二次循环为x赋值
三元表达式
x=1
y=2
def func(x,y):
if x>y:
return x
else:
return y
res=func(1,2)
print(res)
# 三元表达式(可以在函数内):有条件,有两个返回值。与上面的代码含义一样,简写了
res1=x if x>y else y # if else两边为返回值x,y中间为判断条件
print(res1)
res2=11 if x>y else 22 # if else两边为返回值11,22中间为判断条件
print(res2)
生成式
列表生成式
# 提取dsb结尾的元素放入新列表
l=['a_dsb','b_dsb','c_dsb','d']
new_l=[]
for name in l:
if name.endswith('dsb'):
new_l.append(name)
# 第一个name为一个可放入的值,可以是任意对象
new_l=[name for name in l if name.endswith('dsb')]
print(new_l)
# 只要运行把l的东西都放入新列表
new_l2=[name for name in l ]
print(new_l2)
# 转换大写 upper
l1=[name.upper() for name in l ]
print(l1)
# 去除后缀 replace把_dsb改为空
l2=[name.replace('_dsb','') for name in l]
print(l2)
字典生成式
keys=['name','age','sex']
dic={key:None for key in keys}
print(dic)
items=[('name','admin'),('age',18),('sex','man')]
res={k:v for k,v in items if k!='sex'}
print(res)
集合生成式
keys=['name','age','sex']
set={key for key in keys}
print(set)
生成器表达式
g=(i for i in range(10) if i>3) #在没有运行的时候g里面是没有值的
print(next(g))
print(next(g))
print(next(g))
print(next(g))
# 统计文件字符
with open(r'xxx.txt',mode='rt',encoding='utf-8') as f:
count=0
for i in f:
count+=len(i)
print(count)
# sum方法,可以统计字符数,对每一行进行累加
res=sum(len(i) for i in f)
print(res)
函数的递归调用
递归调用具体是,在调用一个函数的过程中又直接或者间接调用到本身
# 就是循环调用,不应该一直循环下去,一个要满足某个条件然后退出循环
def f1(n):
if n >= 10:
print(n,'123')
else:
n+=1
print(n)
f2(n)
def f2(*x,**y):
f1(*x,**y)
f2(8)
递归的两个阶段
# 回溯:一层一层调用下去
# 递推:满足某种结束条件,结束递归调用,然后一次一次返回
# age(5)=age(4)+10
# age(4)=age(3)+10
# age(3)=age(2)+10
# age(2)=age(1)+10
# age(1)=18
def age(n):
if n == 1:
return 18
return age(n-1) + 10
print(age(5))
递归应用,不要打印列表,单独打印字符串
l=[(11,22),1,2,[3,[4,[5,[6,[7,[8,[9,[10]]]]]]]]]
def f1(list1):
for i in list1:
if type(i) is list or type(i) is tuple:
#如果是列表或者元组,就再次运行f1函数继续读下一层,对列表或者元组再次取值
f1(i) # 把读到列表或元组的那个元素,当作参数继续读
else:
print(i)
f1(l)
二分法
# 算法就是高效解决问题的方法
# 二分法应用场景
# 案例,把一个从小到大排列的数字列表,顺序随机可以用sort方法排序,找到想要的数字
nums = [-3, 4, 7, 10, 13, 21, 43, 77, 89]
x = 21
def func(x,nums):
count = len(nums) // 2 # 中间值的位置
if nums[count] > x:
nums = nums[0:count + 1]
func(x,nums)
elif nums[count] == x:
print('ok')
else:
nums = nums[count:len(nums) + 1]
func(x, nums)
func(13,nums)
匿名函数
定义匿名函数lambda,没有被绑定任何内存地址,定义完之后就立即销毁
# 一次性的多于其他函数配合使用
lambda x,y:x+y # 返回值为x+y
# 调用匿名函数 lambda x,y:x+y()
res=(lambda x,y:x+y)(1,2)
print(res)
# 案例,找出薪资最高的那个人
salaries={
'siry':3000,
'tom':7000,
'lili':10000,
'jack':2000
}
max方法会找出最大值,字典如果不指定比较对象,比较对象就是字典的key
res=max(salaries,key=lambda k:salaries[k]) # key=内存地址也就是value
print(res)
# min方法会找出最小值,字典不指定比较方式就是字典的key
res=min(salaries,key=lambda k:salaries[k])
print(res)
sorted可以对所有可迭代对象进行排序
res=sorted(salaries,key=lambda k:salaries[k])
print(res)