Python3中函数进阶

1:动态传参
首先看下下列代码,实现对2个整数进行求和 运算;如果只有两个参数的话,函数m_sum是能够很好地运行,但是如果要对3个,4个甚至更多的整数进行求和运算时,函数m_sum将不能工作。

def m_sum(a,b):
	ret = a + b
	return ret 

print(m_sum(1,3))

那么要怎样定义函数才能接收多个个数可变的参数呢,在python中提供了动态传参,即可以接收任意个参数,代码如下:

def m_sum(*args):
	print(args)	
	ret = 0
	for x in args:
		ret += x	
	return ret 

print(m_sum(1,3))
print(m_sum(1,3,4,5))

"""
(1, 3)
4
(1, 3, 4, 5)
13
"""

Python中的动态传参:
*args 位置参数 接收到的是元组;把位置参数没有接收的,都被收集到args中;
**kwargs 关键字的动态传参, 接收到的是字典;把关键字参数没有变接收的,都被收集到kwargs中;

"""
形参声明顺序:位置 *args 默认值 **kwargs  ;不能是其它顺序;

"""
def func( a,b,*args,c = 100,**kwargs ): 
    print(a, b, c, args,kwargs)

"""
1:调用实参传递顺序:位置参数,关键字参数;(可以全部是关键字参数;但不能全部是位置参数)
2:其中位置参数 传递给 a,b,*args;a,b被赋值后剩下的以元组的形式给args;
3:关键字参数传递给 c = 100,**kwargs;匹配默认参数之后,剩下的以字典的形式给kwargs;
4:关键字参数之后不能有位置参数传递;
5:*args之后的默认值参数必须以关键字参数的形式传递,不然会永远都接收不到值,因为多余的位置参数会传递给args;

"""
# 1,2,3,4,5,6,8 给a,b,*args
# a2 = 20,c = 200 给 c = 100,**kwargs
func(1,2,3,4,5,6,8,a2 = 20,c = 200)  # 输出 1 2 100 (3, 4, 5, 6, 8) {'a2': 20}

# 1, 2, 5, 给a,b,*args
# aa="hello", bb="python", cc="ixusy88" 给 c = 100,**kwargs
func(1, 2, 5, aa="hello", bb="python", cc="ixusy88") # 输出 1 2 10 (5,) {'aa': 'hello', 'bb': 'python', 'cc': 'ixusy88'}

#下面的调用方式是错误的,关键词参数之后不能有位置参数
# func(bb="python",1, b = 2, c=5, aa="hello",  cc="ixusy88")  

# 全部都是关键字参数
func(bb="python",a = 1, b = 2, c=5, aa="hello",  cc="ixusy88")   #  1 2 5 () {'bb': 'python', 'aa': 'hello', 'cc': 'ixusy88'}

无敌模式. 所有的参数都能接收

def func(*args, **kwargs):
    print(args)
    print(kwargs)

"*" 和"**" :
在函数定义中:收集参数
在函数调用中:解包参数


# 函数定义的时候:
# *args :收集所有位置参数 ,最终会收集为一个元祖
# **kwargs:收集所有关键字参数,最终会收集为一个字典
def func(*args, **kwargs):
    print(args)
    print(kwargs)

func(1,2,3,a=20,b=30) 
"""
输出:
(1, 2, 3)
{'a': 20, 'b': 30}
"""



# 在函数调用的时候:
# * : 会解包参数的集合,它会将序列解包成相应的参数
# ** :会以键/值对的形式把一个字典解包为独立的关键字参数

lst = [1,2,3]
# 作为一个参数传递
func(lst) 
"""
输出:
([1, 2, 3],)
{}
"""


# 把lst中的元素作为值传递
func(*lst)  #  与 func(1,2,3) 调用是一样的
"""
输出:
(1, 2, 3)
{}
"""


dic = {'name':'ixusy88','age':18}
# 作为一个参数传递
func(dic) 
"""
输出:
({'name': 'ixusy88', 'age': 18},)
{}
"""


# 把dic中的键/值对解包为关键字传递
func(**dic)  #  与 func(name='ixusy88',age=18) 调用是一样的
"""
输出:
()
{'name': 'ixusy88', 'age': 18}
"""

2:作用域

Python中有如下作用域:

内置作用域(B):在内置名称模块中预先赋值好的名称(就是在builtins模块中定义的)。

全局作用域(G):在一个模块文件顶层被赋值的变量,或者在文件中def 语句内通过global 关键字声明的变量。全局作用域仅限于                             单个文件。

外层作用域(E):在外层函数(def或lambda)的局部作用域中的变量,由内向外。

局部作用域(L):在一个函数(def或lambda)中被赋值的变量,不包括那些被global关键字声明的变量。


Python中一个变量的作用域总是由它在代码中被赋值的位置决定的,而与函数调用无关。

一个变量可以在3个不同的地方被赋值:

a:在def内赋值,它对该函数而言是局部的;
b:在外层的def中赋值,对于内层函数来说,它是非局部的;
c:在所有def外赋值,它对整个文件来说是全局的;
 

变量名解析规则:LEGB

LEGB :局部作用域(L)  ---->  外层作用域(E) ---->   全局作用域(G)  ---->  内置作用域(B)  ,即对一个变量的引用,会由内到外来查找;

# 全局作用域
a = 100

def func():
	# print('1---a=',a)  # 此处对a的引用会报错,因为a是局部的,引用之前没有进行赋值操作。
	a = 200   # 此处的a为func的局部作用域,对其赋值,a指向了新的对象,不影响全局作用域中的a
	print('2---a=',a)

func()
print('3---a=',a)

"""
2---a= 200
3---a= 100
"""


# global : 在函数局部中声明变量为全局的
b = 100
def func():
	global b # 在局部作用域中 声明全局变量b,
	print('1---b=',b)  # 修改之前
	b = 200   # b是全局变量,对其修改就是修改全局作用域中的b
	print('2---b=',b)

func()
print('3---a=',b)

"""
1---b= 100
2---b= 200
3---a= 200
"""

3:函数嵌套
在Python中可以对函数进行嵌套,即在函数中也可以定义函数:

# 函数可以互相嵌套
def outer():
    def inner():
        print("in--inner")
    print("in--outer")
    inner()

outer()

"""
输出结果
in--outer
in--inner
"""

# 可以多层嵌套
def outer(cnt):
    print(' '*cnt,"outer--开始")
    def inner_1(cnt):
        print(' '*cnt,"inner_1--开始")
        def inner_2(cnt):
            print(' '*cnt,"inner_2--")
        inner_2(cnt+4)
        print(' '*cnt,"inner_1--结束")
    inner_1(cnt + 4)
    print(' '*cnt,"outer--结束")

outer(0)

"""
输出结果:
 outer--开始
     inner_1--开始
         inner_2--
     inner_1--结束
 outer--结束
"""

nonlocal 引入上层局部变量:

# global 引入全局变量, 可以定义全局变量
# nonlocal 引入局部中离他最近的外层变量


a = 100
def outer():
    a = 200    # 此处的a为 outer的局部变量
    def inner():
        nonlocal a # 找的是局部当中, 离他最近的上层的那个变量,也就是outer中的局部变量。
        a = 300    # 修改的是离他最近的上层的那个变量,
        print(a)  # 300
    print(a) # 200,
    inner()  # 调用内部函数,
    print(a) # 300,outer中的局部变量,在inner中被修改。
outer()
print(a)  # 100 全部变量

"""
输出结果:
200
300
300
100
"""


a = 1
def fun_1():
    a = 2
    def fun_2():
        nonlocal a   # 引入局部中离他最近的外层变量,及fun_1中的局部变量a
        a = 3        # 修改fun_1中的局部变量a的值为3
        def fun_3():
            a = 4    # fun_3中的局部变量,对其赋值不影响外部的变量
            print('4---',a)  # fun_1 中的局部变量a,值在fun_2中被修改为3,
        print('3---',a)  # fun_1 中的局部变量a,值在fun_2中被修改为3,
        fun_3()   # 此调用没有修外部的变量
        print('5---',a)  # fun_1 中的局部变量a,值在fun_2中被修改为3,
    print('2---',a)  # fun_1 中的局部变量a,值为2
    fun_2()   # 此调用把fun_1 中的局部变量a,修改为3啦; 
    print('6---',a)   # fun_1 中的局部变量a,值在fun_2中被修改为3,
print('1---',a) # 全局变量a,值为1
fun_1()
print('7---',a) # 全局变量a,值为1


"""
输出结果:
1--- 1
2--- 2
3--- 3
4--- 4
5--- 3
6--- 3
7--- 1
"""

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章