函数参数相关&名称空间
函数参数部分
1. 函数参数的两大分类
1.1 形式参数
定义:指在函数 定义阶段 括号内所填写的参数,简称 形参。
def func(a, b):
pass
## a 和 b 就是func的形参。
1.2 实际参数
定义:指在函数 调用阶段 括号内所传入的参数,简称实参。
def func(a, b):
pass
func(1, 2)
# 数据 1和2 就是函数func的实参
1.3 注意!!
-
形参与实参的关系
可以将形参看成是 变量名,实参看成是 变量值。
两者在函数调用阶段,临时绑定,函数运行结束断开。 -
形参的表现形式只有一种:变量名。
-
实参的表现形式有多种(把握核心就是:数据值)
- 直接传入值
- 借助于变量名间接传入值
m = 12
n = 13
func(m, n) - 其他方法或者函数的返回值
func(int('123'), int('456'))
func(func1(), func2())-->将func1和func2的返回值当作参数传入。
2. 位置参数
位置参数:按照从左往右的顺序依次填入的参数。
位置形参 :在函数定义阶段,括号内按照从左往右的顺序依次填入的变量名。
位置实参:在函数调用阶段,括号内按照从左往右的顺序依次传入的变量值/数据值。
关键字实参(可以打破位置顺序):
在函数调用阶段,通过形参名= 数据值的形式,指名道姓的传值,打破位置参数的顺序。
# 定义一个比较大小的函数
def compare(a, b): # a,b--位置形参
if a > b:
return a
return b
res = compare(1, 2) # 1,2--位置实参
# 关键字实参请注意
res = compare(11, a=33) # 11,33都会传给a,这种情况是不可以出现的,报错。
res = compare(b=22,11) # 位置参数必须要在关键字参数的前面,报错。
"""格式越简单的越靠前,后面一样适用。"""
tips:
- 位置形参 与 位置实参在函数调用阶段,按照位置一一对应绑定。
- 位置参数在绑定的时候,不能多也不景能少。
以上,为位置参数以及关键字参数内容所应该清楚的内容。
3. 默认参数
定义及特点:
默认参数--默认形参:函数在定义阶段就已经给形参赋值了。
- 该函数在调用阶段如果不给值,则使用默认的,
- 该函数在调用阶段也可以给值,则使用给的值。
ps:当某一个值变化不是很大的时候可以用。
易错笔试题1:
# 默认形参 如果绑定的是一个列表,那么指向的是一个固定的地址
def func(name, age, hobby=[]):
hobby.append(age)
print('{}:{}:{}'.format(name, age, hobby))
func('jason',18) # jason:18:[18]
func('duke',28) # duke:28:[18,28]
func('jack',38) # jack:38:[18,28,38]
# 可以这样解决
func('kk',22,[]) # 自己传入一个空列表
# 函数体中,每次结束前可以情况列表...等等一些方法。
易错笔试题2:
m = 200
def func(a, b, c=m):
print(a, b, c)
m = 400
func(1, 2) # 200
# 一定要注意
"""
如何去理解呢???
角度1
默认形参在函数定义阶段就已经固定死了,不会随着后续的变化而变化。
角度2
参考变量名与 值 的绑定关系在函数定义阶段,就已经将c与m=200所在地址进行绑定了,函数定义完成后,后面变量m与谁绑定都和参数c无关。
"""
4. 可变长参数(重点)
4.1 在形参中的用法
# 1. 函数无论传入多少 位置参数,都可以正常运行
def func1(*args):
print(args)
func1(1,2,3,4,5)
"""
*号在形参中的使用
用于接收 多余的 位置参数 ,并组织成 元组 的形式,
赋值给*号后面的变量名。
"""
# 2. 函数无论传入多少 关键字参数,都可以正常运行
def func2(**kwargs):
print(kwargs)
func(a=1, b=3, c=8)
"""
**号在形参中的使用
用于接收多余的 关键字参数,并组织成 字典 的形式,
赋值给**号后面的变量名。
"""
# 3. 定义一个函数无论传入多少位置参数和关键字参数都可以正常运行
def multiple(*args, **kwargs):
print(args, kwargs)
multiple() # (){}
"""
一般:
可变长形参 *与** 后面的变量名其实是可以随便定义的,
但是python中推荐使用
*args --> arguments
**kwargs --> keyword arguments
"""
4.2 在实参中的用法
def index(a, b, c):
print(a, b, c)
new_list = [1,2,3,4]
index(*new_list)
"""
*号在实参中的使用
会将列表,元组内的元素打散成位置参数的形式一一传值。
同理:
**号在实参中的使用
会将字典内的键值对打散成关键字参数的形式一一传值。
"""
5. 函数参数补充(作为了解,几乎用不到)
5.1 命名关键字参数
def register(name, age, *, sex, height): # sex,height为命名关键字参数
pass
def register(name, age, *args, sex, height):
pass
register('jason',11,sex='male',height='180cm')
"""
sex,height在传入实参的时候必须以关键字参数的形式
...该类型的参数几乎不用,也几乎很少遇到。
"""
def register1(name, age, *args, sex='male', height): # sex不是默认参数,height也不是位置参数。
名称空间
什么是名称空间namespaces???
名称空间是用于存放变量名与变量值绑定关系的地方(类似民政局)
1. 名称空间的分类(重点!!!):
- 内置名称空间
python解释器提前给定义好的
print()
len()
...
- 全局名称空间
所有在py文件中顶格写的代码运行之后都会存入全局名称空间,如下:
name = 'xxx' # name全局
def func(): # func全局
pass
if 1:
a = 123 # a全局
for i in range(10):
print(i)
while True:
b = 123
- 局部名称空间
函数体代码运行之后产生的都是局部名称空间。
2. 存活周期的不同
-
内置名称空间
随着python解释器启动与关闭而创建和销毁 -
全局名称空间
随着py文件的运行和结束而创建和销毁 -
局部名称空间
随着函数体代码的执行与结束而创建和销毁
3. 名字的查找顺序
len = '这是全局的len'
def index():
len = '这是局部的len'
print(len)
index() # 这是局部的len
局部的嵌套
x = 11
def f1():
x = 22
def f2():
x = 33
def f3():
x = 44
def f4():
x = 55
print(x)
f4()
f3()
f2()
# 通过调用f1,执行所有的函数
f1() # 55
笔试题:
x = 11
def f1():
x = 22
def f2():
x = 33
def f3():
x = 44
def f4():
print(x)
x = 55
f4()
f3()
f2()
f1() # 结果会报错。。。
结论:
# 在查找名字的时候,要先确定自己当前在哪里
1. 如果你在局部
局部>>>全局>>>内置
2. 如果你在全局
全局>>>内置
# 查看名字是否在函数体内部,注意特例:上面的笔试题。。。