Python
复用代码
函数
- 函数
- 有参数函数
- 无参数函数
- 参数
- 形参(定义函数时的参数)
- 位置参数
- 默认值参数
- 关键字参数
- 实参(调用函数时的参数)
- 形参(定义函数时的参数)
- def
- 定义函数
- args
- 位置参数
- kwargs
- 关键字参数
代码示例:
# 基本结构:
def foo():
pass
foo() # 调用函数(执行函数体的内容)
# 无参数函数:
def foo():
print('bar')
# 无参数调用:
foo() # bar
# 有参数函数(位置参数:调用时实参与形参的位置顺序一一对应,缺少实参则报错):
def foo(args,kwargs):
print(args,kwargs)
# 有参数调用:
foo('args','kwargs') # args kwargs
# 默认值参数(定义函数形参时候,已经给予的默认实参,可被覆盖):
def foo(args,kwargs = 'kwargs'): # 规范(位置参数要位于默认值参数前面)
print(args,kwargs)
foo('args') # args kwargs
foo('args','bar') # args bar
# 关键字参数(调用时指定函数的形参名):
def foo(args,kwargs = 'kwargs'):
print(args,kwargs)
foo(kwargs = 'bar',args = 'args') # args bar
foo('args',kwargs = 'bar') # args bar
可变参数
- 符号
- *
- 概念
- 在形参前面
- 可容纳多个实参的形参(返回值:tuple,装包)
- 在实参前面
- 拆分元组(拆包)
- 在形参前面
代码示例:
def foo(*args): # 装包
print(args)
foo(1,2,3,4,5) # (1, 2, 3, 4, 5)
def foo(args,kwargs):
print(args,kwargs)
foo(*(1,2)) # 拆包(1 2)
def foo(*args):
print(args)
foo((1,2)) # ((1,2),)
foo(*(1,2)) # (1,2)
a,*b,c = 1,2,3,4,5 # 在变量名前时(装包)
print(a,b,c) # 1 [2, 3, 4] 5
a,b,c = (1,2,3) # 在变量名前时(拆包)
print(a,b,c) # 1 2 3
a,b,*c = (1,2,3,4,5)
print(a,b,c) # 1 2 [3, 4, 5]
- 符号
- **
- 概念
- 在形参前面
- 可容纳多个实参的形参(装包,返回值:dict)
- 在实参前面
- 拆分字典(拆包)
- 在形参前面
代码示例:
def foo(**args): # 装包
print(args)
foo(foo = 'foo',bar = 'bar') # {'foo': 'foo', 'bar': 'bar'},实参为关键字形式(键值对)
def foo(**args): # 封装
for k,v in args.items():
print(k,v)
foo(**{'foo':1024,'bar':2048}) # 拆包
# *与**的组合:
def foo(*args,**kwargs):
print(args,kwargs)
foo('foo','bar',*(1024,),**{'foo':'bar'}) # ('foo', 'bar', 1024) {'foo': 'bar'}
返回值
- 概念
- 函数里面向外界传值,只要有一个return被执行,那么函数体就会结束执行
- return
- 输出函数返回值,需要用变量名来接收
- 可以是任意数据类型
- 多个输出值默认的数据类型为元组
代码示例:
def foo():
return 1,2 # 输出多个值
bar = foo() # 接收
print(bar) # (1,2)
# return在结束循环的同时也结束了函数体的执行
def foo():
for i in range(5):
if i == 3:
return
print('foo')
foo() #
# break只能结束循环,不能结束函数体的执行
def foo():
for i in range(5):
if i == 3:
break
print('foo')
foo() # foo
相互调用
代码示例:
def foo():
print('foo',end = ' ')
bar()
def bar():
print('bar') # 这里如果调用foo函数会造成死循环
foo() # foo bar
全局变量与局部变量
- 全局变量
- 可以在函数外使用的变量
- 局部变量
- 只能在函数内使用的变量(执行时创建,结束时销毁局部变量)
- 优先级
- 局部 > 全局
- global
- 修改指定全局变量的值
- globals
- 查看全局变量(返回值:dict)
代码示例:
def foo():
bar = 'bar' # 局部变量
print(a,bar,end = ' ')
def bar():
bar = 1024
a = 'a' # 优先级
print(bar,a)
a = 'foo' # 全局变量(自上而下的执行顺序,a写在foo()的下面会导致报错)
foo()
bar() # foo bar 1024 a
# 函数内部可以使用全局变量,但不可直接修改全局变量,需要借助global才可以(使用时需置顶)
def foo():
global bar,a
bar -= 10
a = 'b'
print(bar,a,end = ' ') # 调用、修改全局变量的同时,也会在函数里产生一个修改后的变量(局部)
bar = 100
a = 'a'
foo()
print(bar,a) # 90 b 90 b
print(globals()) # 分成系统与自定义
可变类型与不可变类型
- id
- 查看变量的内存地址
- 可变类型
- 当变量的值改变时,内存地址没有发生改变(list/dict/set)
- 不可变类型
- 当变量的值改变时,内存地址发生了改变(int/str/float/bool/tuple)
- 函数里的可变类型不需要加global
- 只有不可变类型才需要加global
代码示例:
def foo():
bar.append('foo')
print(bar)
bar = ['bar']
foo() # ['bar', 'foo']
高级注释
代码示例:
def foo():
'''
:return: 我是return的高级注释,会说明这个函数的return值
'''
嵌套
- 优先级
- 内部 > 外层 > 全局 > 系统(builtins)
- locals
- 查看当前函数体中的局部变量(返回值:dict)
- nonlocal
- 修改指定外层函数变量的值
代码示例:
def foo():
a = 100
def bar():
b = 200
f = locals()
print(f,end = ' ')
print(a) # 调用外层函数的变量(因为调用了,所以会在内部函数里产生一个相同的变量)
bar()
foo() # {'b': 200, 'a': 100} 100
# 内部函数与外层函数同属于一块局部变量内,内部函数可以调用外层函数的变量,但不可直接修改,需要借助nonlocal才可以(使用时需置顶)
def foo():
a = 100
def bar():
nonlocal a
a -= 10
bar()
print(a)
foo() # 90
闭包
- 概念
- 必须是(嵌套/内部)函数引用外层函数的变量(返回值:内部函数)
- 应用场景
- 装饰器
代码示例:
def foo():
a = 100
def bar():
b = a
return bar
fq = foo()
print(fq) # <function foo.<locals>.bar at 0x000002361A0ED310>
装饰器
- 符号
- @
- 特性
- 遵循开放封闭原则,在不改变原函数的情况下,扩展了函数的功能
- 应用场景
- 引入日志
- 函数执行时间统计
- 执行函数前预备处理
- 执行函数后清理功能
- 权限校检等场景
代码示例:
# 不带参数、返回值:
def foo(app): # app参数必须有,接收函数a的内存地址
print('foo')
def bar(): # 第一次执行foo函数体时bar函数只是预载
app() # 执行函数a(可放在bar函数体最下面,让装饰代码先执行)
print('bar') # 装饰的代码
print('233')
return bar # 输出装饰器的内存地址,给函数a来接收(函数a的内存地址 == bar函数的内存地址)
@foo
def a():
print('a')
a()
'''
foo
233
a
bar
'''
# 带参数:
def foo(app):
print('foo')
def bar(*args,**kwargs): # 接收多个参数
app(args,kwargs)
print('bar')
print('2048')
return bar
@foo
def a(args,kwargs):
print(args,kwargs)
a('a','b',**{'kwargs':1024})
'''
foo
2048
('a', 'b') {'kwargs': 1024}
bar
'''
# 带返回值:
def foo(app):
print('foo')
def bar(*args,**kwargs):
r = app(args,kwargs) # r接收的是1024,顺便执行a函数
print('bar')
return r # 再返回出值给g接收
print('2048')
return bar
@foo
def a(args,kwargs):
print(args,kwargs)
return 1024
g = a('a','b',**{'kwargs':4096}) # g接收的是r返出的1024
print(g)
'''
foo
2048
('a', 'b') {'kwargs': 4096}
bar
1024
'''
# 装饰器带参数:
def foo(app): # 由外层向内层递进
print('foo')
def bar(args): # args接收的是函数a的内存地址
print('bar')
def hqsy():
print('hqsy')
if app == 1024: # 最终返回值为函数a的return出的'shigure'
return args()
else: # 如果不成立则最终返回值为'kurosaki'
return 'kurosaki'
return hqsy
return bar
@foo(1024) # 传给形参app
def a():
return 'shigure'
print(a())
'''
foo
bar
hqsy
shigure
'''
# 多层装饰器:
@foo
@bar
def a(a,b):
pass
# 先执行@bar再把结果返回给@foo最后再把最终值返回给a函数
递归
一个函数体中不调用其它函数,而是调用本身
代码示例:
# 必须要有出口(结束条件),每次递归都向出口(结束条件)靠近
def foo(args):
if args == 10: # 出口(结束条件)
print(args,end = ' ')
else:
print(args,end = ' ')
args += 1 # 向出口(结束条件)靠近
foo(args) # 调用本身
foo(1) # 1 2 3 4 5 6 7 8 9 10
# 递归式累加和:
def foo(args):
if args == 10:
return 10 # 返回给上一层
else:
return args + foo(args + 1) # 最后一次递归拿到结果后参与运算再返回给上一层
bar = foo(1)
print(bar) # 55
# 递归式累加和:
def foo(args):
if args == 6:
return args
def bar(args):
return args + foo(args + 1)
r = bar(5)
print(r) # 11
匿名函数
- lambda
- 定义匿名函数
- 特点
- 匿名函数能接收任何数量的实参,当只能返回一个表达式的值
- 应用场景
- 作为参数来使用
- 与高阶函数配合使用
代码示例:
def foo(a,b):
return a + b
bar = foo(1,2)
print(bar) # 3
# 匿名函数:
foo = lambda x,y:x + y
bar = foo(1,2)
print(bar) # 3
# 参数本身可以作为函数名使用:
def foo(x,y):
r = y(x)
print(r)
foo(8,lambda z:z * 2) # 16
高阶函数
- 概念
- 把另一个函数作为参数来使用
- 标准高阶函数
- max
- min
- sorted
- filter
- map
- reduce
代码示例:
# max:
foo = [('foo',22),('bar',33)]
bar = max(foo,key = lambda x:x[1]) # x[1]:(0,1)区间
print(bar) # ('bar', 33)
# min:
foo = [('foo',22),('bar',33)]
bar = min(foo,key = lambda x:x[1])
print(bar) # ('foo', 22)
# sorted:
foo = [('foo',22),('bar',33)]
bar = sorted(foo,key = lambda x:x[1]) # 支持reverse = true(降序)
print(bar) # [('foo', 22), ('bar', 33)]
# filter:
foo = [('foo',22),('bar',33)]
bar = filter(lambda x:x[1] > 30,foo) # 只返回条件为真的结果
print(list(bar)) # [('bar', 33)](因为返回值是自定义类型,所以必须强转类型,否则返回一个对象)
# map:
foo = [('foo',22),('bar',33)]
bar = map(lambda x:x[0].title(),foo) # 指定列表中每个元组元素的下标(元组里面的元素),并对其进行首字母大写
print(list(bar)) # ['Foo', 'Bar']
# reduce:
from functools import reduce # 导入标准库
foo = [1,2,3,4,5]
bar = reduce(lambda x,y:x + y,foo) # 累加
print(bar) # 15