python函数相关(参数、返回值、变量global,locals,globals,nonlocal、闭包、匿名lambda)

1.  函数的意义和定义

# 函数的作用:python中的函数可以像变量一样,动态创建,销毁,当参数传递,作为值返回,叫第一类对象.其他语言功能有限
1.函数名是个特殊的变量,可以当做变量赋值
2.函数名可以作为容器类型数据的元素
3.函数名可以作为函数的参数
4.函数名可作为函数的返回值

__doc__或者help查看文档
# 函数概念: 满足某一个方法 满足某一个功能
# (1) 功能:包裹一部分代码 实现某一个功能 达成某一个目的
# (2) 可以反复调用,提高代码的复用性,提高开发效率,便于维护管理
# (3) 函数的基本格式:
'''
# 定义一个函数
def 函数名(): 
    code

# 调用函数
函数名()
'''
# 函数的定义处
def func():
    print("天下武功为快不破")

# 函数的调用处
func()

 

2.  函数的命名

函数的命名
字母数字下划线 首字符不能为数字
严格区分大小写 且不能使用关键字
函数命名有意义 且不能使用中文哦

驼峰命名法:
(1)大驼峰命名法 : myfunc => MyFunc  应用在面向对象程序当中的类名
(2)小驼峰命名法 :myfunc => myFunc  用在函数上(不做强制要求)
myfunc => my_func (推荐)

 3.  函数的参数

(1) 普通形参、默认形参、普通实参、关键字实参

'''
参数分类: 形参 和 实参
形参: 形式参数 在函数的定义处
实参: 实际参数 在函数的调用处

形参包含: 普通形参, 默认形参, 普通收集形参, 命名关键字形参, 关键字收集形参
实参包含: 普通实参,关键字实参

形参 和 实参 要一一对应
'''
# row,a,b 是普通形参,在传参数的时候,要按顺序传参
def LittleStar(row, a, b, col=80):
    i = 0
    while i < row:
        j = 0
        while j < col:
            print ("*", end='')
            j += 1
        print()
        i += 1

LittleStar(5, 0, 0)  #使用了 col=80 的默认值,即使用默认形参
LittleStar(5, 0, 0, 110)  # 使用了 col=100 实际参数,即使用普通实参
LittleStar(5, b=3, col=10, a=100)  # 使用了关键字实参进行调用,顺序随意

  

(2)收集参数(普通收集参数、关键字收集参数)

'''
(1) 普通收集参数 (可变参数)
语法:
def func(*参数名):
    pass

参数前面加上一个 * 的就是普通收集参数;
普通收集参数专门用于收集多余的普通实参,形成一个元组

arg => argument 参数
'''

def func(a, b, c, *arg):
    print(a, b, c, end='\t\t')  # 1, 2, 3
    print('arg: ', arg)   # (4, 5, 6)

func(1, 2, 3, 4, 5, 6)


'''
(2) 关键字收集参数
# 语法
def func(**参数):
    pass
参数前面加上**的就是关键字收集参数
关键字收集参数:用于收集多余的关键字实参,形成一个字典

def func(a, b, c, **kwargs):
    pass

# kwargs => keyword arguments
'''

def func(a, b, c, **kwargs):
    print(a, b, c, end='\t\t')
    print('kwargs: ', kwargs)

func(1, 2, 3, f=11, d=13, zz=99)

  执行结果:

1 2 3        arg:  (4, 5, 6)
1 2 3        kwargs:  {'f': 11, 'd': 13, 'zz': 99}

 (3)  命名关键字

'''
# 命名关键字
# 语法:
def func(参数1, 参数2, *, 参数3, 参数4):
    pass
(1) 在函数的定义处, * 号后面的参数就是命名关键字参数
(2) 在函数的定义处, 在普通收集参数和关键字收集参数之间的是命名关键字参数
def func(*arg, 命名关键字参数, **kwargs)

命名关键字必须使用关键字实参的形式进行调用
'''

# 形式1
def func(a, b, *, c):
    print(a, b, c)

func(1, 2, c=4)  # 必须写上*号后面的参数名并赋值 c=4

# 形式2
'''
如果命名关键字指定了默认值,那么在调用时,
可以不指定实参.默认使用自己的值
'''
def func(a, b, *, c=5):
    print(a, b, c)

func(1, 2, c=6)  # c为命名关键字默认参数,可以不传,但传参时,必须写上 c=4

# 形式3
def func(*arg, d, **kwargs):
    print(arg)  # 1 2 23
    print(kwargs)  # {c:1,f:2}
    print(d)  # d = 3

func(1, 2, 23, c=1, f=2, d=3)  # d为命名关键字,必须写上 d=xxx

4.  函数的返回值

# 函数的返回值 return
return: 自定义返回值 , 返回到哪里? 返回到函数的[调用处]
return 后面可以跟上六大标准数据类型 , 除此之外,可以跟上 类对象,函数,如果不写return ,默认返回None
return 如果执行了return ,意味着 return后面得所有代码,统统不执行,函数终止了.

5.  变量相关(global / locals / globals / nonlocal)

# 作用域:作用范围
# 命名空间 : 划分一块区域保存所有数据,以字典的方式存储(变量与值形成映射关系).一共三种.
(1)内建命名空间:解释器启动时创建,直到解释器运行结束,生存周期最长
(2)全局命名空间:文件运行时创建,直到解释器运行结束,生存周期较长
(3)局部命名空间:函数调用时,里面的局部变量才创建,调用结束后即释放,生存周期较短
#命名空间的提出是为了划分和控制变量是否可见,以及生存周期的长短.

#命名空间 创建顺序:(了解)
    python解释器启动->创建内建命名空间->创建全局命名空间->创建局部命名空间
#命名空间 销毁顺序:(了解)
    函数调用结束后->销毁函数对应的局部命名空间数据->销毁全局命名空间数据->销毁内建命名空间数据
global    :关键字:声明全局变量获修改全局变量
locals()  :返回字典,当前作用域所有内容(locals调用之前的变量)
globals() :返回字典,存放着全局作用域所有内容
nonlocal  :关键字:修改局部变量(当前函数上一层的局部变量)

(1)global 全局变量的获取和定义

了解 global 之前,先了解一下局部变量和全局变量:
局部变量:在函数内部声明的变量就是局部变量.
全局变量:在函数外部声明的变量或用global关键字在函数内部声明的变量

作用域:作用的范围
局部变量:作用范围在函数的内部
全局变量:作用范围横跨整个文件
'''
python特有:
如果外部存在该全局变量,那么利用global关键字,可以允许在函数内部修改全局变量
如果外部不存在该全局变量,那么利用global关键字,可以允许在函数内部定义全局变量
在使用global 关键字的时候,一般写在函数内部的第一行.
'''
c = 78


def func1():
    a = 1  # 为局部变量
    # 如果不加 global c 只能获取 不能修改
    # 加了global c 告诉系统在函数内部允许修改全局变量c
    global c
    print(c)
    c = 90


def func2():
    global a  # 在函数内部通过global 定义全局变量
    a = 985

 (2)locals 

locals 获取当前作用域的所有变量

'''
locals 获取当前作用域的所有变量
'''
# 获取打印返回值之前的所有内容
a = 10
b = 20
res = locals()
c = res['__name__']
print('c: ', c)
print('res: ', res)
d = 30


# 获取调用 locals 之前的所有的内容
def func():
    f1 = 11
    f2 = 12
    res = locals()
    f3 = 13
    print('func var: ', res)


func()

 执行结果:

c:  __main__
res:  {'__name__': '__main__', '__doc__': '\nlocals 获取当前作用域的所有变量\n', '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001B002DE4390>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:\\test.py', '__cached__': None, 'a': 10, 'b': 20, 'res': {...}, 'c': '__main__'}
func var:  {'f1': 11, 'f2': 12}

 (3)globals

'''
globals 只获取全局变量(无论在函数内外都只获取全局变量)
globals 返回的是系统的 全局命名空间的字典 ,在空间里面放的全局变量
'''

# (1) 如果在函数的外面,获取globals()返回值打印之前, 所有的内容.
a = 5
res = globals()
b = 15
print('函数外部: ', res)  # 拿不到 c 以及之后的元素
c = 26

# (2) globals 如果在函数的里面,获取globals调用之前,所有的内容
# (3) globals 动态创建全局变量


def func():
    f1 = 1
    # globals 如果在函数的里面,获取globals调用之前,所有的内容
    res = globals()
    f2 = 2
    print('函数内部: ', res)
    # globals 可以批量创建全局变量
    for i in range(3):
        res["a%d" % (i)] = i


func()
print('a0: ', a0)
print('a1: ', a1)
print('a2: ', a2)
d = 10

执行结果:

函数外部:  {'__name__': '__main__', '__doc__': '\nglobals 只获取全局变量(无论在函数内外都只获取全局变量)\n', '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000017D3B5C4390>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:\\test.py', '__cached__': None, 'a': 5, 'res': {...}, 'b': 15}
函数内部:  {'__name__': '__main__', '__doc__': '\nglobals 只获取全局变量(无论在函数内外都只获取全局变量)\n', '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000017D3B5C4390>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:\\test.py', '__cached__': None, 'a': 5, 'res': {...}, 'b': 15, 'c': 26, 'func': <function func at 0x0000017D3B57C1E0>}
a0:  0
a1:  1
a2:  2

 (4)nonlocal (符合LEGB原则)

#找寻变量的调用顺序采用 LEGB 原则(即就近原则)
B —— Builtin(Python);Python内置模块的命名空间  (内建作用域)
G —— Global(module); 函数外部所在的命名空间    (全局作用域)
E —— Enclosing function locals;外部嵌套函数的作用域  (嵌套作用域)
L —— Local(function);当前函数内的作用域          (局部作用域)
依据就近原则,从下往上,从里向外,依次寻找

 演示代码:

# nonlocal 修改的是局部变量,不是全局变量.
a = 10


def outer():
    a = 100

    def inner():
        a = 1000

        def smaller():
            nonlocal a  # 修改外层第一个局部变量
            a += 1  # 不可修改,仅可修改容器类型参数
        smaller()
        print(a)

    inner()
    print(a)

outer()
print(a)

 执行结果:

1001
100
10

6.闭包函数

闭包的定义:
    内函数使用外函数的局部变量,并且外函数将内函数返回出来的方法叫闭包,
    返回的内函数叫闭包函数。

闭包的特点:
    内函数使用了外函数的局部变量,外函数的局部变量与内函数发生绑定,延长该变量的生命周期 (实际内存给它存储了这个值,暂时不释放)

闭包的意义:
    闭包可以优先使用外函数中的变量,并对闭包中的值起到了封装保护的作用。外部无法访问。

演示代码:

def outer():
    a = 5
    # inner 是闭包函数

    def inner():
        print(a)
    return inner


# outer()()
res = outer()  # res = inner
res()          # res() = inner()

7.匿名函数

匿名函数,顾名思义就是没有名字的函数。
特点:使用 lambda 定义,而不是使用 def 定义;不用写 return 关键字。
结构:lambda 参数: 返回值

演示代码:

# 定义
fun = lambda arg: "执行我啦"
# 调用,与普通函数一样
fun()
# 一行实现函数的定义调用和输出
print((lambda x, y: x * 10 + y)(96, 1))  # 961
# 三目运算
print((lambda n: True if n > 8 else False)(10))  # False

猜你喜欢

转载自www.cnblogs.com/trent-fzq/p/10891603.html