Python

复用代码

函数

  1. 函数
    • 有参数函数
    • 无参数函数
  2. 参数
    1. 形参(定义函数时的参数)
      • 位置参数
      • 默认值参数
      • 关键字参数
    2. 实参(调用函数时的参数)
  3. def
    • 定义函数
  4. args
    • 位置参数
  5. 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

可变参数

  1. 符号
    • *
  2. 概念
    1. 在形参前面
      • 可容纳多个实参的形参(返回值:tuple,装包)
    2. 在实参前面
      • 拆分元组(拆包)

代码示例:

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]
  1. 符号
    • **
  2. 概念
    1. 在形参前面
      • 可容纳多个实参的形参(装包,返回值:dict)
    2. 在实参前面
      • 拆分字典(拆包)

代码示例:

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'}

返回值

  1. 概念
    • 函数里面向外界传值,只要有一个return被执行,那么函数体就会结束执行
  2. 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

全局变量与局部变量

  1. 全局变量
    • 可以在函数外使用的变量
  2. 局部变量
    • 只能在函数内使用的变量(执行时创建,结束时销毁局部变量)
  3. 优先级
    • 局部 > 全局
  4. global
    • 修改指定全局变量的值
  5. 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())  # 分成系统与自定义

可变类型与不可变类型

  1. id
    • 查看变量的内存地址
  2. 可变类型
    • 当变量的值改变时,内存地址没有发生改变(list/dict/set)
  3. 不可变类型
    • 当变量的值改变时,内存地址发生了改变(int/str/float/bool/tuple)
  4. 函数里的可变类型不需要加global
    • 只有不可变类型才需要加global

代码示例:

def foo():
    bar.append('foo')
    print(bar)

bar = ['bar']
foo()  # ['bar', 'foo']

高级注释

代码示例:

def foo():
    '''
    :return: 我是return的高级注释,会说明这个函数的return值
    '''

嵌套

  1. 优先级
    • 内部 > 外层 > 全局 > 系统(builtins)
  2. locals
    • 查看当前函数体中的局部变量(返回值:dict)
  3. 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

闭包

  1. 概念
    • 必须是(嵌套/内部)函数引用外层函数的变量(返回值:内部函数)
  2. 应用场景
    • 装饰器

代码示例:

def foo():
    a = 100
    def bar():
        b = a
    return bar

fq = foo()
print(fq)  # <function foo.<locals>.bar at 0x000002361A0ED310>

装饰器

  1. 符号
    • @
  2. 特性
    • 遵循开放封闭原则,在不改变原函数的情况下,扩展了函数的功能
  3. 应用场景
    • 引入日志
    • 函数执行时间统计
    • 执行函数前预备处理
    • 执行函数后清理功能
    • 权限校检等场景

代码示例:

# 不带参数、返回值:
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

匿名函数

  1. lambda
    • 定义匿名函数
  2. 特点
    • 匿名函数能接收任何数量的实参,当只能返回一个表达式的值
  3. 应用场景
    • 作为参数来使用
    • 与高阶函数配合使用

代码示例:

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

高阶函数

  1. 概念
    • 把另一个函数作为参数来使用
  2. 标准高阶函数
    • 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