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