函数

---恢复内容开始---

一、可变长参数:

指的是在函数调用时,传入的参数不固定

四种可变长参数:可变长形参 *  ,可变长实参 * ,可变长形参**,可变长实参**

1.可变长形参之 *  形参中*会将溢出的位置实参全部接收,,然后存储成元祖的形式,再把元祖赋值到给*后面的参数。约定为*args

def fun1(a,*args):
    print(a , args)
fun1(1,2)
fun1(1,2,3)
打印结果为:1(2,)
      1(2,3)  

 2.可变长实参之 * :实参中的*,会将*后面的参数循环取出来,打散成位置实参,,以后但凡看到实参前面带*,就看成是位置实参,马上打散成位置实参去看。

def fun1(a,b,c,d,*args):
    print(a,b,c,d,args)
       
    fun1(1,*(2,3,4),5,6)
打印结果为:1 2 3 4(5,6)

 3.可变长形参之 ** :形参中的**,会将溢出的关键字实参全部接收,然后存储成字典的形式,再赋值给**后的参数,约定为**kwargs

def fun1(a,**kwargs):
    print(a , kwargs)

fun1(1,b=2,c=3)
打印结果为:1{'b'=2,'c'=3}

4.可变长实参**:实参中的**,会将**后面的参数循环取出来,打散成关键字实参,以后但凡看到实参前带**,就是把它看成关键字实参,马上打散成关键字实参去看。

def fun1(x,y,**kwargs):
  print(x,y,kwargs)
  
fun1(
1,2,**{'a':1,'b':2}) 打印结果为:1 2 {'a': 1, 'b': 2}

  5.可变长参数应用:

def index(name,age,sex):
    print(f'name:{name},age:{age},sex:{sex}')

def wrapper(*args,**kwargs):
    print(f'args:{args}')
    print(f'kwargs:{kwargs}')
    index(*args,**kwargs)

wrapper(name='nick',age=19,sex='male')
打印结果为:
args:() # *arges只接受溢出的位置实参,但wrapper没有传入位置实参,为空元祖

       kwargs:{'name': 'nick', 'age': 19, 'sex': 'male'}接收所有溢出关键字实参
       name:nick,age:19,sex:male

 二、函数对象

函数是第一类对象,可以被当作数据处理

函数的四大功能:

1.引用

def func():
    print('from func')
print(func)
f = func #换了个名字,内存地址两者一样
print(f)
运行结果为:

<function func at 0x000001D3653E40D0>
<function func at 0x000001D3653E40D0>

2.当作函数传给一个函数

def func():
    print('from func')
def foo(m):
    m()
foo(func) #函数名称可以被当作参数来传递
打印结果为:from func

3.当作函数返回值

def func():
    print('from func')
def foo(m):
    return m
res = foo(func) #此时func被当作返回值,虽然它是一个函数
print(res)
res()
打印结果为:

<function func at 0x000001D3653E60D0>
from func


4.可以当作容器类型的元素

def func():
    print('from func')

l = [func] #放入到列表容器中
l[0]()
打印结果为:
from func

三、函数的嵌套

函数内部再定义函数,此时函数外部无法使用内部定义的函数

def f1():
    def f2():
        print('from f2')
    f2()
f2() 
此时报错:NameError: name 'f2' is not defined
def f1():
    def f2():
        print('from f2')
    f2()
f1() 
打印结果为: from f2

找出4个数的最大值:

def max2(x,y):
    if x>y:
        return x
    else:
      return y

def max4(a,b,c,d):
    res1 = max2(a,b)
    res2 = max2(c,d)
    res3 = max2(res1,res2)
    print(res3)

max4(1,2,3,4)
打印结果为:4

四、函数名称和作用域

名称空间:内存中存储的变量名誉变量间绑定关系的空间

1.内置名称空间  :存储python解释器自带的名字,解释器启动时生效,关闭无效,如 int,float,len

2.全局名称空间:除了内置和局部都叫全局,文件执行时生效,文件执行结束失效。

x = 1

def fun():
    pass
1 = [1,2]
if 3>2:
    if 4>3:
        z = 3
# x,fun,l,z都是全局名称空间

3.局部名称空间:存放函数调用时产生的名字

def f1():
    def f2():
        print('from f2')
    f2()
f1()
# f2是局部名称空间

4.加载顺序:.py文件由python解释器打开,因此,内置名称空间先加载,结束后文件才打开,此时产生全局名称空间,只有当函数被调用时,才会产生局部名称空间,因此名称空间加载顺序为: 内置---》全局----》局部

5.查找顺序:  先从当前位置查找,找不到就按照这种顺序查找-----局部>>全局>>内置不逆向查找

len = 10
def f1():
    len = 20
    print(len)
f1()
打印结果为:20 从局部开始查找,找到len = 20

作用域:作用的区域

1.全局作用域:全局有效,全局存活,包括内置名称空间和全局名称空间。

2.局部作用域:局部有效,临时存储,只包含局部名产空间。

注意:作用域关系在函数定义阶段就固定死了,与函数调用无关

x = 1
def f1():
    print(x)
def f2():
    x = 2
    f1()
f2() 打印结果为:
1

 global 和 nonlocal 关键字打破规则

x = 1
def f1():
    x = 2
    def f2():
        global x #把局部变量修改为全局变量
        x = 3
    f2()
    print(x)
f1()
print(x)
打印结果为:3
x = 1
def f1():
    x = 2
    def f2():
        nonlocal x   #修改上一个局部变量为3
        x = 3
    f2()
    print(x)
f1()
print(x,x)
打印结果为:3
     (1,1)

注意点:

1.在局部想要修改全局的可变类型,不需要任何声明,可以直接修改   如在函数中添加全局的列表的值

2.在局部如果想修改全局的不可变类型,需要借助global来声明为全局变量,即可直接修改

原文地址:https://www.cnblogs.com/fjn839199790/p/11562574.html