python:函数

函数:以功能为导向,减少重复的代码量

在函数中,遇到return 就直接结束函数,并且将值返回给 函数调用者

函数定义

函数名也是一个变量,函数名就是在内存中指向一个内存地址,这个内存地址对应的是一个函数。

def func():    # 用 def 来定义一个函数,func 是函数名
    print(123)
func()    #  调用函数func,函数调用方式就是函数名+(),执行函数内的代码

def a():    # 函数名为a,a作为一个变量,在内存中,指向这个定义的函数的内存空间
    print(‘a‘)
def b():
    print(‘b‘)
k = a
k()        # a
a = b
a()        # b

名称空间

在python中分为三个空间:
    内置名称空间(builtins.py)
    全局名称空间(当前py文件)
    局部名称空间(函数,函数执行时才会在内存中开辟 )
加载顺序:内置名称空间---->全局名称空间----->局部名称空间
取值顺序(就近原则),单向不可逆

两个作用域
    全局作用域:内置名称空间、全局名称空间
    局部作用域:局部名称空间
# globals() 返回字典:内容是全局作用域的所有内容
# locals()  返回字典:内容是当前作用域的所有内容
a = 1
b = 2
def fun():
    c = 3
    d = 4
    print(globals())
    print(locals())
print(globals())
print(locals())
fun()
# 在函数中,如果定义一个变量,但是在定义这个变量之前对其引用了,解释器会认为;语法错误
n = 1 
def fun():
    print(n)    # 这里会报错,因为python解释器会首先在局部名称空间中寻找n,n在定义引用语句后面定义了
    n = 3
fun()
# 统计一个可迭代对象的元素个数,并将结果返回给调用者
s1 = [1,2,3,4,5,6]
def count(s,c=0):
    for i in s:
        c += 1
    return c
res = count(s1)

‘‘‘   在函数中遇到  return ,就结束函数,return后面的代码不执行 ‘‘‘
def test():
    s = ‘abcde‘
    while 1:
        for i in s:
            return s     # 第一次循环到这里的时候,函数就会技术执行,返回字符串s
            print(i)  # 这里不会输出
a = test()
print(a)    # ‘abcde‘

‘‘‘  当return返回多个元素时,是以 元祖 的形式返回给函数调用者  ‘‘‘
def test():
    return ‘a‘,‘b‘,[1,2,3]
print(test())    # (‘a‘, ‘b‘, [1, 2, 3])
# 位置参数:在调用函数的时候,根据形参的位置来给参数赋值
def con(i,j):
    return i if i>j else j
s = con(2,5)    # 这里根据参数位置给形参赋值,i=2,j=5
print(s)

# 关键字参数:调用函数的是,传参是根据形参的关键字来赋值
def fun(sex,age,skill,hight):
    print(f‘性别:{sex},年龄:{age},技能:{skill},身高:{hight}‘)
fun(sex=‘女‘,skill=‘python‘,hight=155,age=73) #性别:女,年龄:73,技能:python,身高:155

# 混合传参:位置参数要一一对应,关键字参数,需要变量名相同
def fun(sex,age,skill,hight):
    print(f‘性别:{sex},年龄:{age},技能:{skill},身高:{hight}‘)
fun(‘女‘,73,hight=155,skill=‘python‘)

当默认参数是可变的诗句类型的时候,那么无论引用多少次该默认参数,都是引用同一个。前提是

引用函数的时候,不能给该默认参数传参,传参就会改变默认参数指向的内容,

def fun(name,alist=[]):
    alist.append(name)
    return alist
ret = func(‘alex‘)
print(ret)
ret2 = func(‘wusir‘)
print(ret2)
print(ret)


def func(name,alist=[]):
    alist.append(name)
    return alist
ret = func(‘alex‘,)        # ret = [‘alex‘],这里没有alist传参,所有alist指向的是默认值
ret1 = func(‘jackma‘,[])    # ret1 = [‘jackma‘],这里给alist传递了一个空list,重新赋值
ret2 = func(‘wusir‘,)        # ret2 = [‘alex‘,‘wusir‘],这里有没有给alist传参,所有沿用默认值
ret3 = func(‘tonyma‘,[])    # ret3 = [‘tonyma‘],这里给alist传递了一个空list,重新赋值了
print(ret)        # [‘alex‘,‘wusir‘]
print(ret1)        # [‘jackma‘]
print(ret2)        # [‘alex‘,‘wusir‘]
print(ret3)        # [‘tonyma‘]

*args:接受所有位置参数,聚合成一个元祖

def func(*args):
    print(args)        # 调用函数,这里会输出 (1, 2, 3, 4, 5)
    count = 0
    fo i in args:
        count += i
    return count
a = fun(1,2,3,4,5)
print(a)        # 15

**kwargs:在函数定义时,**将所有关键字聚合到一个字典中,赋值给kwargs

def func(**kwargs):
    print(kwargs)        #{‘name‘: ‘jay‘, ‘age‘: 40}
fun(name=‘jackma‘,age=30)

万能参数

def func(*args,**kwargs):
    print(args)
    print(kwargs)
fun(1,2,3,4,name=‘jackma‘,age=40)

形参角度的参数的顺序:位置参数>*args>默认参数>仅限关键字参数>**kwargs

def fun(a,b*args,sex=‘男‘,**kwargs):
    print(a,b)    # 1,2
    print(sex)    # 女
    print(args)    # (3,4,5)
    print(kwargs)    #{‘name‘:‘alex‘,‘age‘:75}
fun(1,2,3,4,5,sex=‘女‘,name=‘alex‘,age=75)

# 仅限关键字参数
def func(a,b,*args,sex=‘男‘,c,**kwargs):
    print(a,b)    # 1,2
    print(sex)    # 女
    print(c)    # 555
    print(args)    #(3,4,5)
    print(kwargs)    #{‘name‘:‘alex‘,‘age‘:73}
func(1,2,3,4,5,sex=‘女‘,name=‘alex‘,age=73,c=‘555‘)

在调用函数的时候,* 代表打散

def fun(*args):
    print(args)    # (1,2,3,22,33)
fun(*[1,2,3],*[22,33])    # 等同于 fun(1,2,3,22,33)

def fun(*args,**kwargs):
    print(args)
    print(kwargs)    # {‘name‘: ‘alex‘, ‘age‘: 22}
fun(**{‘name‘:‘alex‘},**{‘age‘:22})

golobal:在局部作用域定义一个全局变量,函数内部就是局部作用域

# global
name = ‘jackma‘
def func():
    global name        # 定义一个全局变量name,如果name已经存在全局作用域中,这样就可以在局部作用域中修改全局变量的值。如果全局变量中没有name,这样在局部作用域用global定义的变量,就可以再全局作用域中引用
    name = ‘tonyma‘    # 重新给全局变量赋值
    print(name)        # 代码执行到这里,name的值已经被修改
print(name)  # 代码执行到这里,函数只是被定义还没有被执行。所有name的值没有改变
fun()         # 这里调用函数,执行函数内的代码。
print(name)

nonlocal :不能操作全局变量。主要用在内层函数对外层函数局部变量的引用

count = 5
def wrapper():
    count = 1        #局部变量
    def inner():
        nonlocal count    # 定义一句局部变量,这个如果外层函数存在同名变量,那么就可以对这个变量进行修改
        count += 1
    inner()
    print(count)    
wrapper()
a,b,*c=(1,2,3,4,5,6,7)
print(a,b,c)    # 1 2 [3,4,5,6,7]

a,*b,c = [1,2,3,4,5,6,7]
print(a,b,c)    #1 [2,3,4,5,6] 7