third day -- 02--函数
复习
1 # 函数 2 # 定义 3 # 关键字 def 函数名(形参): 4 # 参数 : 5 # 位置参数 6 # *args 动态传参 :接收在调用的时候传过来的多余的所有按位置传的参数 7 # 关键字参数 默认参数,如果不传会有一个默认的值,如果传了会覆盖默认的值 8 # **kwargs 动态传参 :接收在调用的时候传过来的多余的所有按关键字传的参数 9 # 返回值 10 # return 停止一个程序的运行,返回参数 11 # 没有返回值 默认返回None 12 # 有一个返回值 13 # 返回多个值 14 # 调用 15 # 调用的关键字 函数名(实参) 16 # 传参数 : 17 # 按照位置传 18 # 按照关键字传 19 # 接收返回值 20 # 没有返回值 不接受 21 # 有一个返回值 用一个变量接收 22 # 有多个返回值 23 # 用一个变量接收 所用返回值都会被组织成一个元组 24 # 用多个变量接收 有多少个返回值 就必须用多少个变量接收 25 # 函数是第一类对象的概念 26 # 函数名 --> 函数的内存地址 27 # 函数名可以作为 容器类型的元素 函数的参数、返回值 还能进行赋值 --> 变量 28 29 # 闭包和装饰器 30 # 闭包的定义 : 内部函数引用外部函数的变量 31 # 闭包的应用 :装饰器
1,函数的初识。
函数的定义,函数体,函数名。
函数的返回值return。
函数的参数。
实参:
三种
形参:
三种。
动态参数。
#一、函数概念
1.未引入函数时:代码重复;可读性差
1 # li = [1, 2, 3, 43, 'fdsa', 'alex'] 2 # count = 0 3 # for i in li: 4 # count += 1 5 # print(count) 6 # 7 # s1 = 'fdsgdfkjlgdfgrewioj' 8 # 9 # count = 0 10 # for i in s1: 11 # count += 1 12 # print(count)
2.def 函数名 (): #函数名定义与变量相同
函数体
3.函数名+() 执行函数
4.print(len(s1)) 未调用函数,打印长度
5.函数中一般不加print
6.函数的返回值:
return
1.遇到return,函数结束 与break相似
def func1(): print(11) return print(22) func1()
2.给函数的调用者(执行者)提供返回值 #函数调用者:函数名()整体
1.无return返回None
s1='lijie123456' def my_len(): count=0 for i in s1: count+=1 print(my_len()) #None
2.return不写或者None 返回None
3.return返回单个数
s1='lijie123456' # def my_len(): # count=0 # for i in s1: # count+=1 # return 666 # print(my_len(),type(my_len())) #666 <class 'int'>
4.return返回多个数将放在元祖中返回
s1='lijie123456' # def my_len(): # count=0 # for i in s1: # count+=1 # return 666,count,'丽姐' # print(my_len(),type(my_len())) #(666, 11, '丽姐') <class 'tuple'>
5:return分别赋值功能!!!
s1='lijie123456' # def my_len(): # count=0 # for i in s1: # count+=1 # return 666,222,count # ret1,ret2,ret3=my_len() (666,222,11) # print(ret1) #666 # print(ret2) #222 # print(ret3) #11
基本实现了等同于len的功能,但s1改变,for循环中in后就要改变,引入参数的概念
s1='123' # def my_len(): # count = 0 # for i in s1: # count += 1 # return count # print(my_len()) # print(len(s1))
3.函数的传参:函数的定义,形参;函数的执行,实参
#函数的传参 li = [1, 2, 3, 43, 'fdsa', 'alex'] s1 = 'fdsgdfkjlgdfgrewioj' # def my_len(a): # 函数的定义()放的是形式参数,形参 # count = 0 # for i in a: # count += 1 # return count # ret = my_len(li) # 函数的执行() 实际参数,实参 # print(ret) # print(len(s1))
二、参数传值方法
我们告诉mylen函数要计算的字符串是谁,这个过程就叫做 传递参数,简称传参,我们调用函数时传递的这个“hello world”和定义函数时的s1就是参数。
实参与形参
参数还有分别:
我们调用函数时传递的这个“hello world”被称为实际参数,因为这个是实际的要交给函数的内容,简称实参。
定义函数时的s1,只是一个变量的名字,被称为形式参数,因为在定义函数的时候它只是一个形式,表示这里有一个参数,简称形参。
传递多个参数
参数可以传递多个,多个参数之间用逗号分割。
'''
从实参角度:
1.位置参数 必须一一对应,按顺序
def f(x,y): print(x,y) f(1,2)
2.关键字参数 必须一一对应,不分顺序
def f(x,y,z): print(x,y,z) f(y=1,x=2,z=3)
#输出最大值
def max_number(x,y): #注意传值 if x>y: return x else: return y print(max_number(110,1)) #三元运算符 def max(a,b): ret=a if a>b else b #print(ret) print(max(1,2)) #为什么结果为None??max中无返回值 正确写法: def max(a,b): return a if a>b else b print(max(1,2))
3.混合参数:一一对应且关键字参数在位置参数后
# def func2(argv1,argv2,argv3): # print(argv1) # print(argv2) # print(argv3) # func2(1,2,argv3=4)
从形参角度
1.位置参数 同实参,必须一一对应,按顺序
# def func1(x,y): # print(x,y) # func1(1,2)
2.默认参数 必须在位置参数后面
1 # def regedit(name,sex): 2 # with open('regedit',encoding='utf-8',mode='a') as f1: 3 # f1.write('{} {}\n'.format(name,sex)) 4 # 5 # while True: 6 # name=input('请输入名字:/q 或Q退出') 7 # if name.upper()=='Q':break 8 # sex=input('请输入性别;') 9 # regedit(name,sex) 10 # #默写加默认参数 11 def regedit(name,sex='male'): 12 with open('regedit',encoding='utf-8',mode='a')as f1: 13 f1.write('{} {} \n'.format(name,sex)) #注意) 的位置 14 while True: 15 name=input('请输入名字:/q或Q退出') 16 if name.upper()=='Q':break 17 if 'a' in name: 18 sex=input('请输入性别:') 19 regedit(name,sex) 20 else: 21 regedit(name)
3.动态参数 *args,**kwargs 万能参数
*args元祖(所有位置参数) **kwargs字典(所有关键字参数)
def func2(*args,**kwargs): print(args) print(kwargs) func2(1,2,3,4,5,6,7,11,'alex','老男孩',a='ww',b='qq',c='222') #(1, 2, 3, 4, 5, 6, 7, 11, 'alex', '老男孩') #{'a': 'ww', 'b': 'qq', 'c': '222'}
三种类型顺序:位置参数---*args----默认参数---**kwargs
def func3(a,b,*args,sex='男',**kwargs): print(a) print(b) print(sex) print(args) print(kwargs) func3(1,2,'老男孩','alex','wusir',sex='n',name='alex',age=46) # 1 # 2 # n # ('老男孩', 'alex', 'wusir') # {'name': 'alex', 'age': 46} func3(1,2,'老男孩','alex','wusir',name='alex',age=46) # 1 # 2 # 男 # ('老男孩', 'alex', 'wusir') # {'name': 'alex', 'age': 46}
一定要记住!!
函数的执行 在实参中加* 打散
函数的定义 加* 聚合
不加**,字典可以放在元祖里
def func1(*args,**kwargs): # 函数的定义 * 聚合。 print(args) print(kwargs) # l1 = [1,2,3,4] # l11 = (1,2,3,4) # l2 = ['alex','wusir',4] # func1(*l1,*l2,*l11) # 函数的执行:* 打散功能。 # # func1(1,2,3,4,'alex','wusir',4,1,2,3,4) # 函数的执行:* 打散功能。 dic1 = {'name1':'alex'} dic2 = {'name2':'laonanhai'} func1(dic1,dic2) #({'name1': 'alex'}, {'name2': 'laonanhai'}) /{} func1(*dic1,**dic2) #('name1',) #{'name2': 'laonanhai'} func1(**dic1,**dic2) #() #{'name1': 'alex', 'name2': 'laonanhai'}
2,函数的进阶。
名称空间,全局名称空间,局部名称空间,内置名称空间,
作用域。
globals locals
global,nonlocal
作用域链。
函数的名字。
闭包。
'''
函数的进阶
1.名称空间:
全局名称空间
局部名称空间
内置名称空间
2.作用域
全局作用域:全局名称空间和内置名称空间
局部作用域:作用于局部名称空间
3.加载顺序:内置名称空间--全局名称空间--局部作用空间(函数执行时)
取值顺序:局部名称空间---全局名称空间---内置名称空间
# name = 'alex' # age = 12 # def func1(): # name1 = 'wusir' # age1 = 34 # func1() # print(name1) #会报错,name1没有被定义 #临时名称空间:临时名称空间,局部名称空间,存入函数里面的变量与值的关系,随着函数的执行结束,临时名称空间消失。 #名称空间:全局名称空间,局部名称空间,内置名称空间。 #作用域: # 全局作用域:全局名称空间,内置名称空间。 # 局部作用域:局部名称空间 #加载顺序,取值顺序。 #加载顺序:内置名称空间 ----> 全局名称空间----> 局部名称空间(函数执行时) #取值顺序:局部名称空间 ---> 全局名称空间 ----> 内置名称空间 # name1 = 'wusir' # def func1(): # print(name1) # def func2(): # print('****',name1) # func2() # func1() # name1 = 'wusir' # def func1(): # name2 = 'laonanhai' # print(globals()) #所有的方法{'__name__': '__main__', '__doc__': "\n文件\n操作文件\n1.文件路径\n2.编码方式\n3,动作mode\n\n代码\n# f1 = open('D:\\空姐护士老师主妇.txt', encoding='utf-8', mode='r')\n# content = f1.read()\n# print(content)\n# f1.close()\n解释\n 1,打开文件,产生文件句柄。\n 2,操作文件句柄。\n3.关闭文件!!\n\n", '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000000001DCA208>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'F:/Users/venv/third day/0415课上笔记.py', '__cached__': None, 's1': 'lijie123456', 'name1': 'wusir', 'func1': <function func1 at 0x0000000001D22EA0>} # print(locals()) #查看本地的方法{'name2': 'laonanhai'} # func1()
4.关键字 global nonlocal
局部名称变量可以引用全局变量,但不能做改变,会报错;要用到关键字
1 name = 'alex' 2 age = 12 3 def func1(): 4 global name1 5 name1= 'wusir' 6 age1 = 34 7 func1() 8 print(name1)
global
1.声明全局变量
2.更改全局变量
fun1() 执行函数!
#关键字:global nonlocal # count = 1 # def func1(): # count = count + 1 # print(count) #未执行,执行会报错 #global 1,声明一个全局变量 #2,更改一个全局变量 # name = 'wusir' # def func1(): # global name # name = 'alex' # return #在此处写不写都可以 # func1() # print(name) #alex
nonlocal 用处少,改变局部变量
1,不能修改全局变量。
2,在局部作用域中,对父级作用域(或者更外层作用域非全局作用域)的变量进行引用和修改,并且引用的哪层,从那层及以下此变量全部发生改变。
def func1(): name1 = 'alex' print('+',name1) def inner(): nonlocal name1 name1= 'wusir' print('*',name1) def inner1(): pass inner() print('%',name1) func1() 结果: + alex * wusir % wusir
5.函数名
1.可以互相赋值
# def func1(): # print(666) # # f1 = func1 # f1()
2.函数名可以当成函数的参数
def func1(): print(666) def func2(argv): argv() print(777) func2(func1)
3.可以当成容器类 数据类型的参数
# def func1(): # print(666) # # def func2(): # print(777) # # def func3(): # print(888) # # l1 = [func1, func2, func3] # for i in l1: # i()
4.函数名可以当成函数的返回值
777 666!!!
加()就执行
def func1(): print(666) def func2(argv): print(777) return argv #func1() ret = func2(func1) ret() #执行func2(func1)
方法,查看全局变量、局部变量,返回在字典中
globals()
locals()
#执行inner函数 # def wrapper(): # def inner(): # name1 = 'alex' # print(name1) # inner() # wrapper() # #练习理解 def wrapper(): def inner(): name1 = 'alex' print(name1) return inner #相当于inner() ret=wrapper() ret()
ret=wrapper() #inner
6.闭包:内层函数对外层函数非全局变量的引用
1.判断是不是闭包
函数名.__closure__ #None 不是 cell是
一般会有面试题
闭包的好处:如果python检测到闭包,它有一个机制,
局部作用域不会随着程序的结束而结束
# 闭包 内层函数对外层函数非全局变量的引用,叫做闭包 #闭包的好处:如果python 检测到闭包, # 他有一个机制,你的局部作用域不会随着函数的结束而结束。 # def wrapper(): # name1 = '老男孩' # def inner(): # print(name1) # inner() # print(inner.__closure__) # cell # wrapper() # 判断是不是闭包 # name1 = '老男孩' # def wrapper(): # def inner(): # print(name1) # inner() # print(inner.__closure__) # None # wrapper() # name = 'alex' # def wrapper(argv): # def inner(): # print(argv) # inner() # print(inner.__closure__) # cell # wrapper(name)
index()() #第一个()返回return get,再加一个()执行get
一般用于爬虫、装饰器
有回收机制
from urllib.request import urlopen # def index(): # url = "http://www.cnblogs.com/jin-xin/articles/8259929.html" # def get(): # return urlopen(url).read() # return get # name1 = 'alex' # content1 = index()() #第一个()返回return get,再加一个()执行get # content2 = index()() # print(content1)
'''
3,装饰器。
'''
装饰器
1.梳理调用inner例子--最简单版的装饰器
2.语法糖 @
在不改变原函数即原函数的调用的情况下,为原函数登录增加一些特殊功能,打印日志、执行时间、登录认证
1 import time 2 def func1(): 3 print('晚上回去吃烧烤....') 4 time.sleep(0.5) 5 6 def timer(f1): # f1 = func1 7 def inner(): 8 start_time = time.time() 9 f1() 10 end_time = time.time() 11 print('此函数的执行效率%s' %(end_time-start_time)) 12 return inner 13 #方法1 14 # f1=func1 15 # func1=timer 16 # func1(f1)() #timmer(func1) 17 #方法2 18 # func1=timer(func1) #inner 19 # func1() #inner() 20 #方法3 21 @timer 22 def func1(): 23 print('晚上回去吃烧烤....') 24 time.sleep(0.5) 25 func1()
3.带参数的装饰器
两个* **
1 import time 2 # def wrapper(): 3 # def inner(): 4 # name1 = 'alex' 5 # print(name1) 6 # inner() 7 # wrapper() 8 9 # def wrapper(): 10 # def inner(): 11 # name1 = 'alex' 12 # print(name1) 13 # return inner 14 # ret = wrapper() # inner 15 # ret() 16 def func1(): 17 print('晚上回去吃烧烤....') 18 time.sleep(0.3) 19 20 def func2(): 21 print('晚上回去喝啤酒....') 22 time.sleep(0.3) 23 24 # 最简单版的装饰器 25 # def timer(f1): # f1 = func1 26 # def inner(): 27 # start_time = time.time() 28 # f1() 29 # end_time = time.time() 30 # print('此函数的执行效率%s' %(end_time-start_time)) 31 # return inner 32 ''' 33 # f = func1 34 # func1 = timer 35 # 36 # func1(f) # timmer(func1) 37 ''' 38 # func1 = timer(func1) # inner 39 # func1() # inner() 40 41 42 # @ 43 def timer(f1): # f1 = func1 44 def inner(): 45 start_time = time.time() 46 f1() 47 end_time = time.time() 48 print('此函数的执行效率%s' %(end_time-start_time)) 49 return inner 50 51 @timer # func1 = timer(func1) 52 def func1(): 53 print('晚上回去吃烧烤....') 54 time.sleep(0.3) 55 @timer # func2 = timer(func2) 56 def func2(): 57 print('晚上回去喝啤酒....') 58 time.sleep(0.3) 59 func1() # inner() 60 func2() # inner()
1 #装饰器:在不改变原函数即原函数的调用的情况下, 2 # 为原函数增加一些额外的功能,打印日志,执行时间,登录认证等等。 3 4 #被装饰函数带参数 5 # def timer(f1): # f1 = func1 6 # def inner(*args,**kwargs): 7 # start_time = time.time() 8 # f1(*args,**kwargs) # func1() 9 # end_time = time.time() 10 # print('此函数的执行效率%s' %(end_time-start_time)) 11 # return inner 12 # 13 # @timer # func1 = timer(func1) inner 14 # def func1(a,b): 15 # print(a,b) 16 # print('晚上回去吃烧烤....') 17 # time.sleep(0.3) 18 # func1(111,222) # inner(111,222) 19 20 #被装饰函数带参数 21 # def timer(f1): # f1 = func1 22 # def inner(*args,**kwargs): 23 # start_time = time.time() 24 # ret = f1(*args,**kwargs) # func1() 25 # end_time = time.time() 26 # print('此函数的执行效率%s' %(end_time-start_time)) 27 # return ret 28 # return inner 29 # 30 # @timer # func1 = timer(func1) inner 31 # def func1(a,b): 32 # print(a,b) 33 # print('晚上回去吃烧烤....') 34 # time.sleep(0.3) 35 # return 666 36 # ret2 = func1(111,222) # inner(111,222) 37 # print(ret2)
结构: def wrapper(f1): def inner(*args,**kwargs): '''执行函数之前的操作''' ret = f1(*args,**kwargs) '''执行函数之后的操作''' return ret return f1 # @wrapper # def func1(): # print(222) # return 333 # print(func1())
'''
4,装饰器的进阶。