函数对象
在面向对象编程中 一切皆对象
具体的体现
1.函数可以被引用
2.函数可以作为函数的参数
3.函数可以作为函数的返回值
4.可以被存储到容器类型中
def pay(): print('支付') def save(): print('存钱') def cheak(): print('查看') dic={'1':pay,'2':save,'3':cheak} while True: l=['支付','存钱','查看'] for i,k in enumerate(l): print(i+1,k) cmd=input('>>>:') if cmd in dic: dic[cmd]() else: print('指令错误')
2.函数嵌套
1.嵌套调用 在一个函数中调用了另一个函数
2.嵌套定义 在一个函数中定义了另一个函数
定义在函数内的函数 只能函数内使用 外界不能访问
def func1(): print("func1") def func2(): print("func2") func1() func2()
def func1(): print("func1") def func2(): print("func2") func2() func1()
3.函数的名称空间
存储名称的空间
名称空间的分类
内置名称空间 存储解释器自带的一些名称与值的对应关系
(python解释器启动时创建 所有代码全部执行完毕 关闭解释器时 销毁)
print len max min
全局名称空间 哪些数据会存储在全局空间?
文件级别的名称 只要你的名字的定义是顶着最左边写的就在全局空间
除了内置的函数内的 都在全局中
(执行py文件创建全局名称空间 关闭解释器时 销毁)
局部名称空间 只要是函数内的名称就是局部的
(调用函数时创建 函数执行完毕就销毁)
名称空间的加载顺序
内置的 -> 全局的 ->局部的
名称的查找顺序
局部 -> 全局的 -> 内置的
4.函数的作用域
作用域(作用范围)
域 指的是区域 范围的的意思
全局的名称空间和内置的名称空间 在使用上没什么区别
局部的和全局的内置的 就区别了 局部定义的只能在局部使用
给三个空间划分范围
全局的和内置可以划分为同一个范围
global 表示的全局范围 就是所谓的全局作用域
局部的单独划分为一个范围
local 局部作用域
globals()
locals()
print(locals())#查看全局作用域,当locals在全局作用域时,功能和globes相同 print(globals()) def func(): a = 100 print(locals())#查看局部作用域 func()
age = 18 def func2(): # 明确声明 要使用全局中的age global age age = 19 print(age) func2() print(age)
a = 1 def func3(): a = 10 def inner(): # 明确声明 要使用上一中的 a 如果上一层没有 则找上上层 但是注意 不能找到全局中的 nonlocal a a = 100 print(a) inner() print("这是func3中a",a) func3() print(a)
5.闭包函数
age = 20 # 如下就是一个闭包函数 def fun1(): age = 18 def inner(): print("hello") print(age) # 在返回这个内部的函数时 不是单纯的返回函数 还把函数中访问到的局部名称一起打包了 # 相当于将内部函数与 访问的数据打包在一起了 闭包这个名字就是这么得来的 return inner f = fun1() # f 就是inner f() # 函数的作用域在定义时就固定了 与调用没有关系
# 闭包函数的模板 def func2(): a = 1 b = 10 def inner(): print(a) print(b) return inner
什么是闭包函数
1.定义在另一个函数内的函数
2.内部的的函数访问了外部的名称数据 注意 不包含全局的)
6.装饰器
什么是装饰器
什么是装饰 给一个已有的对象(一个函数) 添加新的功能
为什么要装饰 增强功能
器 指一个工具 在python中 值得是具备某个功能的函数
简单的说:装饰器就是 一个用于给其他函数增加功能的函数
import time def download(): print('开始下载xxx.mp4') time.sleep(2) print('xxxx.mp4 下载完成') # 请你统计下载耗时 start_time = time.time() download() end_time = time.time() print('下载耗时',(end_time-start_time)) def download2(): start_time = time.time() print("开始下载xxx.mp4") time.sleep(2) print("xxxx.mp4 下载完成!") end_time = time.time() print("下载耗时", (end_time - start_time)) download2()
def max2(x,y): if x > y: return x else: return y res=max2(10,20) x=10 y=20 # res=x if x > y else y # print(res) res='OK' if False else 'No' print(res)
def outter(func): def inner(): strat_time = time.time() func() end_time = time.time() print('下载耗时',(end_time-start_time)) return inner download=outter(download) download()
# 叠加多个装饰器 # 1. 加载顺序(outter函数的调用顺序):自下而上 # 2. 执行顺序(wrapper函数的执行顺序):自上而下 def outter1(func1): #func1=wrapper2的内存地址 print('加载了outter1') def wrapper1(*args,**kwargs): print('执行了wrapper1') res1=func1(*args,**kwargs) return res1 return wrapper1 def outter2(func2): #func2=wrapper3的内存地址 print('加载了outter2') def wrapper2(*args,**kwargs): print('执行了wrapper2') res2=func2(*args,**kwargs) return res2 return wrapper2 def outter3(func3): # func3=最原始的那个index的内存地址 print('加载了outter3') def wrapper3(*args,**kwargs): print('执行了wrapper3') res3=func3(*args,**kwargs) return res3 return wrapper3 @outter1 # outter1(wrapper2的内存地址)======>index=wrapper1的内存地址 @outter2 # outter2(wrapper3的内存地址)======>wrapper2的内存地址 @outter3 # outter3(最原始的那个index的内存地址)===>wrapper3的内存地址 def index(): print('from index') print('======================================================') index() '''
import time current_user={'user':None} def auth(engine='file'): def outter(func): def wrapper(*args,**kwargs): if current_user['user']: res=func(*args,**kwargs) return res user=input('username>>>: ').strip() pwd=input('password>>>: ').strip() if engine == 'file': # 基于文件的认证 if user == 'egon' and pwd == '123': print('login successfull') current_user['user']=user res=func(*args,**kwargs) return res else: print('user or password error') elif engine == 'mysql': # 基于mysql的认证 print('基于mysql的认证') elif engine == 'ldap': # 基于ldap的认证 print('基于ldap的认证') else: print('不知道engine') return wrapper return outter @auth('ldap') #@outter #index=outter(index) # index=wrapper def index(): time.sleep(1) print('from index') @auth('mysql') #@outter # home=outter(home) #home=wrapper def home(name): print('welcome %s' %name) index() home('egon')
def max2(x,y): if x > y: return x else: return y res=max2(10,20) x=10 y=20 # res=x if x > y else y # print(res) res='OK' if False else 'No' print(res)
# 列表生成式 # l=[] # for i in range(10): # if i > 4: # l.append(i**2) # # # # l=[i**2 for i in range(10) if i > 4] # print(l) # names=['egon','alex_sb','kevin_sb','hxx_sb','cxx_sb'] # sbs=[] # for name in names: # if name.endswith('sb'): # sbs.append(name) # sbs=[name.upper() for name in names if name.endswith('sb')] # print([name.upper() for name in names]) # print([name for name in names if name.endswith('sb')]) # 字典生成式 # res={i:i**2 for i in range(10) if i > 3} # print(res)
# func() # func() # func() # 匿名函数就是只定义了一个函数的内存地址,主要用于临时使用一次的场景 # func=lambda x,y:x+y # print(func) # print(func(1,2)) # res=(lambda x,y:x+y)(1,2) # print(res) # print(max([10,11,-3,23])) # salaries={ # 'egon':3000, # 'alex':100000000, # 'wupeiqi':10000, # 'yuanhao':2000 # } # def func(k): # return salaries[k] # print(max(salaries,key=lambda k:salaries[k])) # print(min(salaries,key=func)) # for循环的结果 比较依据 # 'egon' 3000 # 'alex' 100000000 # 'wupeiqi' 10000 # 'yuanhao' 2000 # l=[4,2,3] # l_new=sorted(l,reverse=True) # print(l_new) # # # print(sorted(salaries,key=lambda k:salaries[k],reverse=True)) #
迭代器
1. 什么是迭代器
什么是迭代?
迭代是一个重复的过程,但是每次重复都是基于上一次重复的结果而继续
#下列循环知识单纯的重复
while True:
print(1)
# 基于索引的迭代取值
l=['a','b','c']
i=0
while i < len(l):
print(l[i])
i+=1
什么是迭代器?
迭代取值的工具
2. 为什么要用迭代器
迭代器
优点
1. 提供一种不依赖索引的迭代取值方式
2. 更节省内存
缺点:
1. 不如按照索引的取值方式灵活
2. 取值一次性的,只能往后取,无法预测值的个数
3. 如何用迭代器
可迭代的对象:strlist upledictset文件对象
但凡内置有__iter__方法的对象都称之为可迭代对象
迭代器对象: 文件对象
既内置有__iter__方法又内置有__next__方法的对象都称之为迭代器对象
调用可迭代对象下__iter__方法,会有一个返回值,该返回值就是内置的迭代器对象
# s='abcdef' # l=['a','b','c'] # d={'k1':111,'k2':222,'k3':333} # iter_d=d.__iter__() # # print(iter_d) # # try: # print(iter_d.__next__()) # print(iter_d.__next__()) # print(iter_d.__next__()) # print(iter_d.__next__()) # except StopIteration: # print('取值完毕') d={'k1':111,'k2':222,'k3':333} # d={1,2,3,4,5} # d=[1,2,3,4] # iter_d=d.__iter__() # iter_d=iter(d) #d.__iter__ # print(next(iter_d)) #iter_d.__next__() # print(len(d)) print(d.__len__()) # print(iter_d.__iter__().__iter__().__iter__() is iter_d) # print(d.__iter__().__next__()) # print(d.__iter__().__next__()) # print(d.__iter__().__next__()) # while True: # try: # v=iter_d.__next__() # print(v) # except StopIteration: # break # # print('第二次取值') # # iter_d=d.__iter__() # while True: # try: # v=iter_d.__next__() # print(v) # except StopIteration: # break # # for k in d: # print(k) #for循环的底层原理: # 1. 调用in后面那个值/对象的__iter__方法,拿到一个迭代器对象iter_obj # 2. 调用迭代器对象iter_obj.__next__()将得到的返回值赋值变量名k,循环往复直到取值完毕抛出异常StopIteration # 3. 捕捉异常结束循环
生成器就是一种自定义的迭代器
如何得到生成器?
但凡函数内出现yield关键字,再去调用函数不会立即执行函数体代码,会得到一个返回值,该返回值就是生成器对象,
即自定义的迭代器
# def func(): # print('first') # yield 1 # print('second') # yield 2 # print('third') # yield 3 # # # g=func() # # print(g) # # res1=next(g) # print(res1) # # res2=next(g) # print(res2) # # res3=next(g) # print(res3) # # next(g) # 总结yield: # 1. 提供一种自定义迭代器的解决方案 # 2. yield & return # 相同点: 都可以返回值,返回值没有类型限制个数限制 # 不同点: return只能返回一次值,yield却可以让函数暂停在某一个位置,可以返回多次值 # def my_range(start,stop,step=1): # while start < stop: # 5 < 5 # yield start # 3 # start+=step #start=5 # range(1,5,2) # 1 3 # for i in my_range(1,5000000000000000000000000000000000000000000,2): # 1 3 # print(i)
函数的递归调用与二分法
1. 函数的递归调用:
在调用一个函数的过程又直接或者间接地调用该函数本身,称之为递归调用
递归必须满足两个条件:
1. 每进入下一次递归调用,问题的规模都应该有所减少
2. 递归必须有一个明确的结束条件
递归有两个明确的阶段:
1. 回溯
2. 递推
# age(5)=age(4)+2 # age(4)=age(3)+2 # age(3)=age(2)+2 # age(2)=age(1)+2 # age(1)=18 # age(n)=age(n-1)+2 # n > 1 # age(1)=18 # n = 1 # def age(n): # if n == 1: # return 18 # return age(n-1)+2 # # print(age(5)) # l=[1,[2,[3,[4,[5,[6,[7,[8,[9,]]]]]]]]] # # def func(list1): # for item in list1: # if type(item) is not list: # print(item) # else: # # 如果是列表,应该... # func(item) # # func(l) # nums=[3,5,7,11,13,23,24,76,103,111,201,202,250,303,341] # # find_num=203 # for num in nums: # if num == find_num: # print('find it') # break # else: # print('not exists') nums=[3,5,7,11,13,23,24,76,103,111,201,202,250,303,341] def binary_search(list1,find_num): print(list1) if len(list1) == 0: print('not exist') return mid_index=len(list1) // 2 if find_num > list1[mid_index]: # in the right binary_search(list1[mid_index + 1:],find_num) elif find_num < list1[mid_index]: # in the left binary_search(list1[:mid_index],find_num) else: print('find it') binary_search(nums,203)
res=[i for i in range(10) if i > 5]
print(res)#这是列表生成式
g=(i for in range(10) if i >5)
print(g)
print(next(g))
print(next(g))
print(next(g))
print(next(g))#这是生成器表达式
with open('a.txt','rt,encoding='utf8')as f: #print(len(f.read())) 统计文件中字符个数 res = sum(len(line) for line in f) print(res) #用生成器表达式的方法统计文件字符个数