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声明
      如果是可变类型(字典,列表) 则无需关键字声明
----------------------例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('没有该功能编号')
posted @ 2022-07-04 18:30  名字长的像一只老山羊  阅读(43)  评论(0编辑  收藏  举报