day-11
1. 可变长参数
1.1 可变长参数之形参
1.1.1 *形参名
def f1(*args): # *args(默认的写法)用元组接收多余的位置实参
print(args)
f1() # 不传参数
f1(1) # 传一个
f1(1, 2, 3, 4, 5) #传多个
运行结果:
# 多余的变量值使用元组存储
()
(1,)
(1, 2, 3, 4, 5)
Process finished with exit code 0
1.1.2 **形参
def f1(**kwargs): # **kwargs(默认的写法)用字典接收多余的关键字实参,将字典的值赋给参数
print(kwargs)
f1()
f1(x=1)
f1(x=1, y=2)
运行结果:
# 多余的变量值使用字典存储
{} # 不传参数
{'x': 1} # 传一个
{'x': 1, 'y': 2} # 传多个
Process finished with exit code 0
1.2 可变长参数之实参(了解)
1.2.1 *实参
def f1(a, b, c, e, d, f, g):
print(a, b, c, e, d, f, g)
lt = [1, 2, 3, 4, 5, 6, 7]
f1(*lt) # * 把列表中的元素打散成位置实参依次传给位置形参
运行结果:
1 2 3 4 5 6 7
Process finished with exit code 0
1.2.1 **实参
def f1(a, b):
print(a, b)
dic = {'a': 1, 'b': 2} # a = 1,b = 2
f1(**dic) # **dic把字典打散成关键字实参然后传给函数f1
运行结果:
1 2
Process finished with exit code 0
2. 函数对象
python中一切皆对象
对象的四大功能:
- 引用
- 用作容器元素
- 作为函数的实参
- 当作函数的返回值
函数的对象
函数的对象 == 函数名
def f1(): # 定义一个函数 f1(),函数对象是 f1
print('from f1')
1. 函数对象的引用
func = f1 # func 引用函数对象 f1 ,则 func 也具有了函数的功能
print('f1:', f1)
print('func:', func)
func()
运行结果:
f1: <function f1 at 0x0000019477EB34C8>
func: <function f1 at 0x0000019477EB34C8>
# f1 和 func 指向的内存地址是相同的
from f1 # 运行了函数 f1
Process finished with exit code 0
2. 当作容器类元素
lt = [f1, 1, 2, 3] # 将函数对象当作容器类元素
print('lt[0]:', lt[0]) # 取出列表内的第一个元素
print('f1:', f1) # 打印 f1 的内存地址
lt[0]() # lt[0] 取出了函数对象,加上()直接调用函数
运行结果:
lt[0]: <function f1 at 0x0000025308EB34C8>
f1: <function f1 at 0x0000025308EB34C8>
# f1 和 lt[0] 指向的内存地址是相同的
from f1 # 运行了 f1 函数
Process finished with exit code 0
3. 作为函数的实参
def f2(f2_f1):
print('f2_f1', f2_f1)
f2_f1()
print('f1', f1)
f2(f1)
运行结果:
f2_f1 <function f1 at 0x0000022D6C343798>
from f1
f1 <function f1 at 0x0000022D6C343798>
4. 当作函数的返回值
def f2(f2_f1):
return f2_f1
res = f2(f1)
print('res', res)
print('f1', f1)
res()
运行结果:
res <function f1 at 0x000001F93C5E3798>
f1 <function f1 at 0x000001F93C5E3798>
from f1
Process finished with exit code 0
3. 函数的嵌套
函数里面再定义函数。
- 函数的嵌套
# 定义函数,只检测语法,不会执行代码
def f1():
print('from f1')
def f2():
print('from f2')
-
函数的嵌套调用
函数内部定义的函数,外部不能使用
def f1():
print('from f1')
def f2():
print('from f2')
res = f1()
运行结果:
from f1
Process finished with exit code 0
4. 名称空间和作用域
4.1 名称空间
内存中存储变量名与变量之间绑定关系的空间。
4.1.1 内置名称空间
存放 python 解释器自带的内置方法的名字,如: int float print def ……
4.1.1 局部名称空间
用于存放函数调用期间函数体产生的名字,即存放函数内部定义的变量名的空间。
如下面的: x
、 f2
def f1():
x = 10
def f2():
z = 20
4.1.1 全局名称空间
除了内置名称空间和局部名称空间外,其他所有的名称都存放再全局名称空间。
如下面的: x
、 func
、 lt
x = 1
def func():
pass
lt = [1, 2]
4.1.1 加载顺序
内置名称空间>>>全局名称空间>>>局部名称空间
python解释器加载完内置名称空间后才能打开文件,打开文件后会产生全局名称空间,当文件内的某个函数被调用,再产生局部名称空间。
4.1.1 查找顺序
当前所在的空间查找>>>局部名称空间查找>>>全局名称空间查找>>>内置名称空间查找>>>报错
# 这里使用关键字当作变量名,是为了演示查找顺序,实际使用不要这样命名
# 1
len =10
def f1():
len = 20
print('1:', len) #先查找当前名称空间,即查找局部名称空间找到为:20
f1()
# 2
len =10
def f1():
print('2:', len) #当前局部名称空间查找不到,查找全局名称空间找到为:10
f1()
# 3
def f1():
print('3:', len) #当前局部全局名称空间都查找不到,查找内置名称空间:找到内置函数 len
f1()
运行结果:
# 1
1:20
# 2
2:10
# 3
3:<built-in function len>
Process finished with exit code 0
4.2 作用域
4.2.1 全局作用域
全局作用域包括内置名称空间和全局名称空间。
全局作用域的变量 x 和局部作用域的变量 x 没有任何关系。
y = 10 # 定义一个变量 y
def f1(): # 定义一个函数 f1 ,作用是让 y = 2
y = 2
f1() # 调用函数,是函数生效
print(y) # 打印 y
运行结果:
10 # y = 10,局部作用域的变量 y 并没有被全局作用域的变量 y 影响
Process finished with exit code 0
4.2.2 局部作用域
局部作用域只包含局部名称空间。
局部作用域1的 x 和局部作用域2的 x 没有任何关系,即便他们处于同一个局部作用域下。
# 函数 f2 和 f3 同属于一个局部作用域下
def f1():
def f2():
def f3():
x = 1
print(x) # 打印 f3 局部作用域下的 x = 1
x = 2 # 让 f2 局部作用域下的 x = 2
f3()
f2()
f1() # 调用函数 f1
运行结果:
1 # 局部作用域 f3 下的变量 x 并没有被局部作用域 f2 下的 x 影响
Process finished with exit code 0
4.3 补充
4.3.1 global
和 nonlocal
(尽量不要使用)
-
global
让
global
以下的局部作用域的变量变成全局作用域的变量不使用
global
:x = 10 def f1(): # global x # 让global以下的局部的x变成全局的x x = 20 f1() print(x)
运行结果:
10 Process finished with exit code 0
使用
global
后:20 Process finished with exit code 0
-
nonlocal
nonlocal
让变量成为顶层函数的局部作用域的变量,注意不是成为全局作用域的变量(没有应用情景,生产中尽量不要嵌套函数)不使用
nonlocal
:def f1(): def f2(): def f3(): # nonlocal x # nonlocal让x成为顶层函数的局部 x = 1 x = 2 f3() print(x) f2() f1()
运行结果:
2 Process finished with exit code 0
使用
nonlocal
后:def f1(): def f2(): def f3(): nonlocal x # nonlocal让x成为顶层函数的局部 x = 1 x = 2 f3() print(x) f2() f1()
运行结果:
1 Process finished with exit code 0
4.3.2 所有可变数据类型均可打破上述一切规则
lt = [0]
def f1(): # 局部作用域内接收了全局作用域定义的变量 lt ,并且改变了 全局作用域下的 lt 的内容,
lt.append(1) # 1.向列表添加值
lt[0] = 1 # 2. 更改列表第一个值
f1()
print(lt)
运行结果:
[0, 1] # 1.
[1, 1] # 2.