函数,返回值,参数,空间,作用域,函数名的运用,新版格式化输出。
函数,返回值,参数,空间,作用域,函数名的运用,新版格式化输出。
-
函数的优势:
- 减少代码的重复性
- 代码可读性高
- 将功能进行封装
-
函数的结构及调用:
def fun(): print(10) fun() ### #def:定义函数关键字 #func:函数名,跟定义变量一样(函数名只能包含字符串、下划线和数字且不能以数字开头) #():传递参数 #: 语句结束 #函数体:缩进。函数中尽量不要出现 print #fun():函数名()进行调用,多次调用就是执行多次,可以循环调用。 -
函数的返回值:return
def meet(): print('打开tantan') print('左滑一下') return print('右滑一下') print('找美女') print('悄悄话....') print('约....走起...') meet() return: 在函数中遇到return直接结束函数。def meet(): print('打开tantan') print('左滑一下') print('右滑一下') print('找美女') print('悄悄话....') print('约....走起...') # return '妹子一枚' return '妹子', 123, [22, 33] ret= meet() # ret,ret1,ret2 = meet() print(ret,type(ret)) # return 返回多个元素 是以元组的形式返回给函数的执行者。#返回值总结: # return:返回一个内容(内容本身),可以返回多个值 # 返回多个内容,以元组的形式返回 # return终止函数,(切记不能终止循环) # return下方的代码不执行 # return不写返回值或者空内容就返回None,或者没有return也返回None # return 将内容返回给了函数的调用 -
函数的参数:
-
形参:写在函数声明的位置的变量叫形参
- 位置参数:位置参数其实与实参角度的位置参数是一样的,从左至右,一一对应
- 默认参数:函数声明的时候,可以给出函数参数的默认值. 默认值参数一般是这个参数使用率较高
- (位置,默认) 混合参数:默认参数一定在位置参数后面。
- 优先级 位置 > 默认参数
-
实参:在函数调用的时候给函数传递的值
- 位置参数:从左至右,实参与形参一一对应。
- 关键字参数:不需要记住每个参数的位置. 只要记住每个参数的名字就可以了。
- (位置,关键字)混合参数:关键字参数一定在位置参数后面。
- 优先级 位置 > 关键字参数
-
形参,实参的第三种:动态参数*,**
-
动态接受位置参数*args:
-
args,args就是一个普通的形参,但是如果你在args前面加一个*,那么就拥有了特殊的意义。
-
函数定义时,*代表聚合。他将所有的位置参数聚合成一个元组,赋值给了args。
#写一个函数:计算传入函数的所有数字的和 def fun(*args) count = 0 for i in args: count + = i return count print(fun(1,2,3,77,88,99,23,78,99)) -
函数执行时,代表打散,再赋值给形参*动态参数聚合。
def fun1(*args) count = 0 for i in args: count += i return count print(fun1(*[1,2,3,4,5,6],*(9,8,7,6,5,4,3)))
2.动态接收关键字参数**kwargs:
-
函数定义时,**代表聚合。他将所有的关键值参数聚合成一个字典,赋值给了args。
def func(**kwargs): print(kwargs) func(name='ale',age=73,sex='laddyboy') -
函数执行时,**代表打散,将再赋值动态万能参数聚合
def func(**kwargs) print(kwargs) func(**{'a':13},**{'b':19}#{'a':13,'b':19} -
*处理剩下的元素
-
*除了在函数中可以这样打散,聚合外,函数外还可以灵活的运用:
#1.元组,以及列表可以分别拆包赋值 a,b=(1,2) print(a, b) # 1 2 #其实还可以这么用: a,*b = (1, 2, 3, 4,) print(a, b) # 1 [2, 3, 4] *rest,a,b = range(5) print(rest, a, b) # [0, 1, 2] 3 4 print([1, 2, *[3, 4, 5]]) # [1, 2, 3, 4, 5]
-
-
形参的第四种参数:仅限关键字参数
-
位置要放在*args后面,kwargs前面(如果有kwargs),也就是默认参数的位置,它与默认参数的前后顺序无所谓
# 这样传参是错误的,因为仅限关键字参数c只接受关键字参数 def func(a,b,*args,c): print(a,b) # 1 2 print(args) # (4, 5) # func(1, 2, 3, 4, 5) # 这样就正确了: def func(a,b,*args,c): print(a,b) # 1 2 print(args) # (3, 4) print(5) func(1, 2, 3, 4, c=5)
-
-
形参的顺序
- 位置参数 > *args >默认参数(关键字参数)>**kwargs
# 这样位置参数a,b始终接收不到实参了,因为args全部接受完了 def func(*args,a,b,sex='男'): print(args) print(a,b) func(1, 2, 3, 4, 5) #实参的第三个参数始终都会将sex覆盖掉 def func(a,b,sex='男',*args,): print(args) # (4, 5) print(sex) # 3 print(a,b) # 1 2 func(1, 2, 3, 4, 5) #**kwargs 位置 def func(a,b,*args,sex= '男',**kwargs,): print(a,b) print(sex) print(args) print(kwargs) # func(1,2,3,4,5,6,7,sex='女',name='Alex',age=80)
-
-
-
5.名称空间:
- 在python解释器开始执行之后, 就会在内存中开辟一个空间, 每当遇到一个变量的时候, 就把变量名和值之间的关系记录下来, 但是当遇到函数定义的时候, 解释器只是把函数名读入内存, 表示这个函数存在了, 至于函数内部的变量和逻辑, 解释器是不关心的. 也就是说一开始的时候函数只是加载进来, 仅此而已, 只有当函数被调用和访问的时候, 解释器才会根据函数内部声明的变量来进行开辟变量的内部空间. 随着函数执行完毕, 这些函数内部变量占用的空间也会随着函数执行完毕而被清空.
- 内置名称空间:存放的是内置函数的特殊变量。
- 全局名称空间:只存放名字于值(内存地址)的关系
- 临时名称空间:运行中开辟的临时的空间叫做局部命名空间也叫做临时名称空间。
- 加载顺序:
- 内置>>全局>>局部(临时)
- 取值顺序:(就近原则LEGB)
- 局部>>全局>>内置
6.作用域:
-
作用域就是作用范围, 按照生效范围来看分为全局作用域和局部作用域
-
全局作用域: 包含内置命名空间和全局命名空间. 在整个文件的任何位置都可以使用(遵循 从上到下逐⾏执行).
-
局部作用域: 在函数内部可以使用.
-
内置函数globals(),locals()
#在全局作用域下打印,则他们获取的都是全局作用域的所有的内容。 a = 2 b = 3 print(globals()) print(locals()) # 在局部作用域中打印。 a = 2 b = 3 def foo(): c = 3 print(globals()) # 和上面一样,还是全局作用域的内容 print(locals()) # {'c': 3} foo()
4.局部作用域可以引用全局作用域的变量
# 局部作用域可以引用全局作用域的变量,全局作用域不能引用局部作用域 # date = '周五' # def func(): # a = 666 # print(date) # print(a) # func() # print(a)5.局部作用域不能改变全局变量。
count = 1 def func(): count += 2 print(count) func() # local variable 'count' referenced before assignment # 局部作用域不能改变全局作用域的变量,当python解释器读取到局部作用域时,发现了你对一个变量进行修改的操作, # 解释器会认为你在局部已经定义过这个局部变量了,他就从局部找这个局部变量,报错了。 -
7.函数的嵌套(高阶函数):不调用不执行
# 例1:
def func1():
print('in func1')
print(3)
def func2():
print('in func2')
print(4)
func1() #'in func1'
#3
print(1)#1
func2()#'in func2'
#4
print(2)#2
# 例2:
def func1():
print('in func1')
print(3)
def func2():
print('in func2')
func1()
print(4)
print(1) #1
func2() #'in func2'
#'in func1'
#3
#4
print(2) #2
# 例3:
def fun2():
print(2)
def fun3():
print(6)
print(4)
fun3()
print(8)
print(3) #3
fun2() #2
#4
#6
#8
print(5) #5
8.关键字global,nonlocal
-
golobal作用。
- 声明一个全局变量。
- 在局部作用域想要对全局作用域的全局变量进行修改时,需要用到 global(限于字符串,数字)。
-
局部作用域对全局作用域的变量(此变量只能是不可变的数据类型)只能进行引用,如果需要改变需要golobal声明变量 并修改:
count = 1 def search(): global count count = 2 search() print(count) -
利用global在局部作用域也可以声明一个全局变量。
def func(): global a a = 3 func() print(a) -
nonlocal局部作用域如果想对父级作用域的变量进行改变时,需要用到nonlocal
def add_b(): b = 42 def do_global(): b = 10 print(b)#10 def dd_nonlocal(): nonlocal b b = b + 20 print(b) #30 dd_nonlocal() print(b) #30 do_global() print(b) #42 add_b() -
global nonlocal
-
默认参数的陷阱:
def func(name,**kwargs) print(name) print(kwargs) fun('xiaoming',sex='男') ###陷阱值针对于默认参数是可变的数据类型 def func(name,alist=[]): alist.append(name) return alist ret1 = func('alex') print(ret1,id(ret1)) # ['alex'] ret2 = func('太白金星') print(ret2,id(ret2)) # [’alex',太白金星'] # 如果你的默认参数指向的是可变的数据类型,那么你无论调用多少次这个默认参数,都是同一个。 def func(a, list=[]): list.append(a) return list print(func(10,)) #[10] print(func(20,[])) #[20] print(func(100,)) #[10,100] l1 = [] l1.append(10) print(l1)#[10] l2 = [] l2.append(20)#[20] print(l2)# l1.append(100) print(l1)#[10,100] def func(a, list= []): list.append(a) return list ret1 = func(10,) # ret = [10,] ret2 = func(20,[]) # [20,] ret3 = func(100,) # ret3 = [10,100] print(ret1) # [10,] [10,100] print(ret2) # 20,] [20,] print(ret3) # [10,100] [10,100] -
局部作用域的坑
#在函数中,如果定义一个变量,但是不是在定义变量之前对其引用,解释器认为,语法错误。 a = 10 def func(): print(a) a = 30 print(func()) #golobal:在局部作用域声明一个全局变量。 name = 'xiaoming' def func(): golobal name name = "小红" return name print(func())#小红 print(name)#小红 ### count = 1 def func(): # print(count) global count count += 1 print(count) func() print(count) ########### nonlocal: #1.不能修改全局变量,只能修改局部作用域的父级变量的值: count = 1 def func(): nonlocal count count += 1 func() #2. 局部作用域:内层函数对外层函数的局部变量进行修改。 def wrapper(): count = 1 def inner(): nonlocal count count += 1 print(count) inner() print(count) wrapper()
-
-
函数名的运用
-
函数名的定义和变量的定义几乎一致,在变量的角度,函数名其实就是一个变量,具有变量的功能:可以赋值;但是作为函数名他也有特殊的功能就是加上()就会执行对应的函数。
-
函数的内存地址
def func1(): pass def func2(): pass print(id(func2)#function func2 at 0x000002765C13E550 print(id(func1)#function func1 at 0x000002765C13E3A0> -
函数名可以赋值给其他变量
def func(): print("呵呵") print(func) a = func # 把函数当成一个变量赋值给另一个变量 a() # 函数调用 func() -
函数名可以当作容器类的元素
def func1(): print("in func1: 嘻嘻") def func2(): print("in func2: 哈哈") def func3(): print("in func3: 咯咯") def func4(): print("in func4: 吱吱") lst = [func1, func2, func3, func4] for i in lst: i()5.函数名可以当作函数的参数
def func1(): print('in func1') def func2(f): print('in func2') f() func2(func1) -
函数名可以作为函数的返回值
def func1(): print('in func1') def func2(f): print('in func2') return f ret = func2(func1) ret() # ret, f, func1 都是指向的func1这个函数的内存地址
-
-
f-string格式化输出
-
结构就是F(f)+ str的形式,在字符串中想替换的位置用{}展位,与format类似,但是用在字符串后面写入替换的内容。
#旧版格式化输出: #msg = '我叫%s,今年%s' %(name,age) #msg = '我叫{},今年{},format(name,age)' name = '金星' age = 18 sex = '男' msg = F'姓名:{name},性别:{age},年龄:{sex}' # 大写字母也可以 msg = f'姓名:{name},性别:{age},年龄:{sex}' print(msg) ''' 姓名:金星,性别:18,年龄:男 ''' -
任意表达式
print(f'{3*21}') # 63 *** name = 'barry' print(f"全部大写:{name.upper()}") ****字典: dic = {'name':'alex','age': 73} # msg = f'我叫{dic["name"]},今年{dic["age"]}' # print(msg) *****列表: a =[1,2,3,4,5] print(f'最小数{a[0],最大数{a[-1]})#1,5 ##计算最终结果 count = 7 print(f'最终结果:{count**2}') ###转换成大写 name = 'barry' msg = f'我的名字是{name.upper()}' print(msg) **** ###插入表达式 def sum_a_b(a,b): return a + b a = 1 b = 2 print('求和的结果为' + f'{sum_a_b(a,b)}')# #多行f name = 'barry' age = 18 ajd = 'handsome' speaker = f'Hi {name}.'\ f'You are {age} years old.'\ f'You are a {ajd} guy!' print(speaker) ##### # ! , : { } ;这些标点不能出现在{} 这里面。
-

浙公网安备 33010602011771号