python基础16-函数-名称空间
今日学习
*号**在实参中的作用
命名关键字参数(冷门了解)
名称空间
名称空间的作用域
global与nonlocal关键字
函数的嵌套定义与调用
*与**在实参中的作用
定义回顾
1.形参:在定义函数阶段定义的参数称之为形式参数,简称形参,相当于变量名
2.实参:在调用函数阶段传入的值称之为实际参数,简称实参,相当于变量值
在调用阶段,实参(变量值)会绑定给形参(变量名);这种绑定关系只能在函数体内使用;绑定关系在函数调用时生效,调用结束后解除绑定关系
名称 | 形参 | 实参 |
---|---|---|
* | *号会把溢出的位置存成元组,然后赋值其后的形参名 | *号会把值打散,字符串会变成单个字符.... |
** | **号会把溢出来的关键字实参存成字典,然后赋值其后的形参名 | **只能跟字典,只能将字典的key进行打散 |
----------------形参--------------------------
def func(*args, **kwargs):
print(args)
print(kwargs)
print(type(args),type(kwargs))
func()
---------结果-----------
()
{}
<class 'tuple'> <class 'dict'>
---------------- *形参---------------------------
def func(x, y, *z):
print(x, y, z)
print(type(z))
func(1, 2, 3, 4, 5, 6, 7, 8) # 1,2 为位置参数,传给x,y; 3,4,5,6,7,8被*z保存成元组输出
----------结果--------------
1 2 (3, 4, 5, 6, 7, 8)
---------------- *实参-------------------------
def func(x,y,z):
print(x,y,z)
#
func(*[11,22,33])
----------结果-------------
11 22 33
---------------**实参-----------------
def func(n1, n2, n3, n4, n5):
return n1, n2, n3, n4, n5
d = {'n1': 5, 'n2': 6, 'n3': 7, 'n5': 8, 'n4': 9}
print(func(**d), type(d))
-------------结果-----------------
(5, 6, 7, 9, 8) <class 'dict'>
命名关键字参数
def func(a,b,*args):
pass
func(1,2)
func(a=1,b=2)
func(1,b=222)
------------------------------
需要形参在传实参的时候 必须按照关键字参数才可以
------------------------------
-----------------------------
# 在形参*args的后面需要用到命名关键字
# def func(a, b, *args, c):
# print(a, b, args, c)
# func(1,2,3,4,5,6,7) # 报错
# func(1, 2, 3, 4, 5, 6, c=666)
# 如果形参中还有**kwargs 那必须在它的前面
def func(a,b,*args,c,**kwargs):
pass
func(1,2,3,4,5,6,c=123,name='jason')
---------------例---------------------
def func(x,y,*args,z,**kwargs):
print(x,y,args,z,kwargs)
print(type(args),type(kwargs))
func(*[11,22,33],z='hello world',**{'a':1,'b':2,'c':3,'d':4,'e':5})
--------结果---------
11 22 (33,) hello world {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
<class 'tuple'> <class 'dict'>
名称空间
用来存放变量名与数据值之间绑定关系的地方
名称 | 存活周期 |
---|---|
内置名称空间 | python解释器运行到结束 |
全局名称空间 | 文件代码运行开始到结束 |
局部名称空间 | 函数体代码运行开始到结束 |
-
内置名称空间
python解释器运行就会立刻创建的空间
写代码过程中可以直接使用的名字都在该空间中
eg:len() print() input() ...
-
全局名称空间
普通代码里面的变量名
分支结构里面的变量名
循环结构里面的变量名
定义函数的函数名
定义类的类名
---------------------------例---------------------------------------
import sys #模块名sys
x=1 #变量名x
if x == 1:
y=2 #变量名y
def foo(x): #函数名foo
y=1
def bar():
pass
Class Bar: #类名Bar
pass
-
局部名称空间
函数体代码运行过程中产生的名字都会存在该空间,函数调用时才会写入。
--------------------例-----------------------------
def foo(x):
y=3 #调用函数时,才会执行函数代码,名字x和y都存放于该函数的局部名称空间中
名称空间的查找顺序
查找名字之前一定要先看自己在那个名称空间
名称 | 顺序[按照优先级从上到下排序] |
---|---|
局部名称空间 | 1.最先查找 |
全局名称空间 | 2.然后全局 |
内置名称空间 | 3.最后内置 |
查找位置之前一定要先看自己在哪个命名空间
---------------------查找顺序-----------------------------------------
len = '我是全局名称空间里面的len'
def func():
len = '我是局部名称空间里面的len'
print(len) #此时查找的len在局部名称空间
func()
print(len) #查找的len在全局名称空间
---------结果----------------
>>func()我是局部名称空间里面的len
print(len) 我是全局名称空间里面的len
----------总结------------------------
名字查找时一定要确认自己的命名空间位置
-------------------------------------------
'函数在定义阶段其实名字的查找顺序就已经固定死了
-----------------例---------------------
name = 'jason'
def func():
print(name)
name = 'jasonNB'
func()
名称空间的作用域
1.内置名称空间
在程序任意位置都可以使用(全局有效)
2.全局名称空间
在程序任意位置都可以使用(全局有效)
3.局部名称空间
在各自的局部空间可以使用(局部有效)
局部名称空间特殊情况
-
各自局部名称空间默认情况下不能彼此共享名字
def func1():
name = 'jason'
print(age)
def func2():
age = 18
print(name)
func1()
func2()
--------结果-----------
NameError: name 'age' is not defined
global与nonlocal关键字
关键字 | 作用 |
---|---|
global | 将变量标记声明为全局变量 |
nonlocal | 函数体中,在内层局部名称空间修改外层局部名称空间中的不可变类型 |
-
global
- 局部修改全局名称空间中不可变类型(str,int,float,元组)的数据 需要使用关键字global声明
如果是可变类型(字典,列表) 则无需关键字声明
- 局部修改全局名称空间中不可变类型(str,int,float,元组)的数据 需要使用关键字global声明
----------------------例1-----------------------------
money = 999 #全局变量
def func():
global money # 声明 将局部变量money=1000标记修改为全局变量
money = 1000
print(money)
func() #调用打印局部变量
print(money) #打印全局变量
---------执行结果-----------
1000
1000
--------------------------
总结:如果需要将局部变量改为全局变量,需要使用global关键字
---------------例2----------------------------
l1 = [1, 2, 3, 4, 5] #可变类型
s = '$jason$' #不可变类型
def func():
# global s #不可变类型没有通过global声明
s = 'jason' #不可变类型(str)就无法修改成为全局变量
res = s.strip('$')
l1.append(113123)
l1.append(666)
func()
print(s)
print(l1)
----------------结果----------------------------
$jason$
[1, 2, 3, 4, 5, 113123, 666]
----------------------------------------
总结:不可变类型(str,int,float)如果想把局部变量改为全局变量,一定要加global 关键字
可变类型(list,dic)如果想把局部变量改为全局变量,可以不用加global关键字.
-
nonlocal
- 函数体中,在内层局部名称空间修改外层局部名称空间中的不可变类型
----------例------------------
def func1():
x = 1 #int 不可变类型
l1 = [1,2]
def func2():
nonlocal x #一定需要加nonlocal
x = 999 #不可变类型,将x = 999整型修改为上级的局部变量
l1.append(666) #不可变类型,可以加nonlocal,可以不加
func2()
print(x)
print(l1)
func1()
---------结果------------
999 #此时局部名称空间变量已经改变.
[1, 2, 666]
函数名的多种使用方式
# def func():
# print('from func')
# 1.函数名也可以被用来多次赋值(函数名与变量名使用一致)
# name = func
# name()
# name1 = name
# name1()
# 2.函数名还可以当做函数的实参
# def index(a):
# print(a)
# a()
# index(123)
# name = 'jason'
# index(name)
# index(func)
# 3.函数名还可以当做函数的返回值
# def index():
# return func
# res = index()
# print(res)
# res()
# 4.函数名还可以当做容器类型里面的数据值
# l1 = [1,2,3,4,func]
# print(l1)
# l1[-1]()
def register():
print('注册功能')
def login():
print('登录功能')
def check_account():
print('查看账户余额')
def withdraw():
print('体现功能')
def shopping():
print('购物功能')
def transfer():
print('转账功能')
# 提前构造功能字典
func_dict = {'1': register,
'2': login,
'3': check_account,
'4': withdraw,
'5': shopping,
'6': transfer
}
while True:
print("""
1.注册功能
2.登录功能
3.查看余额
4.提现功能
5.购物功能
6.转账功能
""")
choice = input('>>>:').strip()
if choice in func_dict:
func_name = func_dict.get(choice)
func_name()
else:
print('没有该功能编号')