Day05:装饰器,三元表达式,函数的递归,匿名/内置函数,迭代器,模块,开发目录

时间:2023-03-09 16:48:39
Day05:装饰器,三元表达式,函数的递归,匿名/内置函数,迭代器,模块,开发目录

上节课复习:
1.函数的对象
    函数可以被当作数据取处理
2.函数嵌套
    嵌套调用:在调用一个函数时,函数体代码又调用了其他函数
    嵌套定义:在一个函数内部又定义了另一个函数

         def foo()
def inner():
pass
return inner #拿到inner的内存地址
f=foo() #foo全局变量可以通过返回的inner地址调用inner

3.名称空间与作用域
    名称空间:存放名字与值的内存地址绑定关系的地方
    x=1
    x
    内置名称空间
    全局名称空间
    局部名称空间
    查找顺序:当前所在的位置往上依次查找
    全局作用范围:全局存活,全局有效

         def f1():
def f1_inner1():
def f1_inner2():
pass
def f2():
def f2_inner1():
def f2_inner2():
pass

局部作用范围:临时存活,局部有效
    强调:作用域关系在函数定义阶段就已经固定死了,与调用关系无关
4.闭包函数
    闭:封闭在函数内部,即定义在函数内部的函数
    包:该内部包含对外部函数作用域名字的引用

     x=1
def outter():
x=111
def inner():
print (x)
return inner
f=outter()

今日内容:
1.装饰器剩余(*****)
    有参装饰器
2.三元表达式,列表生成式,字典生成式(*****)
3.函数的递归调用,二分法(*****)
4.匿名函数lambda+内置函数(*****)
5.迭代器(****)
6.模块的使用(*****)
7.软件开发的目录规范(*****)

一.装饰器
    1.定义:器指的是工具,装饰指的是为被装饰的对象添加新功能
        装饰器即使为被装饰对象添加新功能的工具
        装饰器本身可以是任意可调用的对象
        被装饰对象本身也可以是任意可调用的对象
    2.开放封闭原则:
    软件一旦上线以后,就应该对修改(源代码+调用方式)封闭,对扩展开放的
        1.不修改被装饰对象的源代码
        2.不修改被装饰对象的调用方式
    3.如何实现

 #原先的调用方式
import time
def index():
print('welcom to index page')
time.sleep(1)
start=time.time()
index()
stop=time.time()
print ('run time is %s' %(stop - start))

输出:

welcom to index page
run time is 1.0005970001220703

 import time
def index():
print('welcom to index page')
time.sleep(1)
def wrapper(func):
start=time.time()
func()
stop=time.time()
print ('run time is %s' %(stop - start)) wrapper(index)

输出:

welcom to index page
run time is 1.000910758972168

 import time
def index():
print('welcom to index page')
time.sleep(1)
def outter(func):
def wrapper():
start=time.time()
func()
stop=time.time()
print ('run time is %s' %(stop - start))
return wrapper
index=outter(index)
index()

输出:
welcom to index page
run time is 1.0008034706115723

 #加了装饰器,目的是不改变原来的调用方式,对使用者是透明的
import time
def index():
print('welcom to index page')
time.sleep(1)
def outter(func):
def wrapper(*args,**kwargs):
start=time.time()
res=func(*args,**kwargs)
stop=time.time()
print ('run time is %s' %(stop - start))
return res
return wrapper
index=outter(index)
index() #wrapper() 为实际调用函数,需模拟原先的内部逻辑

输出:

welcom to index page
run time is 1.0013582706451416

 #加了装饰器,目的是不改变原来的调用方式,对使用者是透明的
import time
def index():
print('welcom to index page')
time.sleep(1)
def home(name):
print('welcom to home page')
time.sleep(2)
def outter(func):
def wrapper(*args,**kwargs):
start=time.time()
res=func(*args,**kwargs)
stop=time.time()
print ('run time is %s' %(stop - start))
return res
return wrapper
index=outter(index)
home=outter(home)
index() #wrapper() 为实际调用函数,需模拟原先的内部逻辑
home('andy') #wrapper('andy')

welcom to index page
run time is 1.0008716583251953
welcom to home page
run time is 2.0003538131713867

#加了装饰器,目的是不改变原来的调用方式,对使用者是透明的
import time def timmer(func):
def wrapper(*args,**kwargs):
start=time.time()
res=func(*args,**kwargs)
stop=time.time()
print ('run time is %s' %(stop - start))
return res
return wrapper
@timmer #index=timer(index)
def index():
print('welcom to index page')
time.sleep(1)
@timmer #home=timer(home)
def home(name):
print('welcom to home page')
time.sleep(2)
return 123 index() #wrapper() 为实际调用函数,需模拟原先的内部逻辑
res=home('andy') #wrapper('andy')

输出:

welcom to index page
run time is 1.0023157596588135
welcom to home page
run time is 2.000333309173584

 #模板
def outter(func):
def inner(*args,**kwargs):
res=func(*args,**kwargs)
return res
return res

输出:

 #认证功能装饰器实现
import time current_userinfo={'user':None}
def outter(func): # func为被装饰对象
def wrapper(*args,**kwargs):
if current_userinfo['user']: #判断是否已登陆
return func(*args,**kwargs)
else:
user=input('please input username:').strip()
pwd=input('please input password:').strip()
if user == 'andy' and pwd =='':
print('login successfully')
#保存登陆状态
current_userinfo['user']=user
res=func(*args,**kwargs)
return res
else:
print ('user or password wrong')
return wrapper
@outter #index=outter(index)
def index():
print('welcom to index page')
time.sleep(1)
@outter #home=outter(home)
def home(name):
print('welcom to home page')
time.sleep(2)
return 123 index() #wrapper() 为实际调用函数,需模拟原先的内部逻辑
res=home('andy') #wrapper('andy')

输出:

please input username:andy
please input password:123
login successfully
welcom to index page
welcom to home page

 #添加多个装饰器
import time
current_userinfo={'user':None}
def timmer(func): #func=wrapper1
def wrapper2(*args,**kwargs):
print('wrapper2 run...')
start=time.time()
res=func(*args,**kwargs) #调到outter内的wrapper1
stop=time.time()
print ('run time is %s' %(stop - start))
return res
return wrapper2 def outter(func): # func=最原始的index
def wrapper1(*args,**kwargs):
print('wrapper1 run...')
if current_userinfo['user']: #判断是否已登陆
return func(*args,**kwargs)
else:
user=input('please input username:').strip()
pwd=input('please input password:').strip()
if user == 'andy' and pwd =='':
print('login successfully')
#保存登陆状态
current_userinfo['user']=user
res=func(*args,**kwargs) #调用最原始的index
return res
else:
print ('user or password wrong')
return wrapper1
@timmer #index=timmer(wrapper1),将下方返回的wrapper1传入
@outter #outter(最原始的index) ==> wrapper1=outter(最原始的index)
def index():
print('welcom to index page')
time.sleep(1)
index() #index==>wrapper2

输出:

wrapper2 run...
wrapper1 run...
please input username:andy
please input password:123
login successfully
welcom to index page
run time is 8.713418006896973

 #添加多个装饰器
import time
current_userinfo={'user':None}
def timmer(func): #func=wrapper1
def wrapper2(*args,**kwargs):
print('wrapper2 run...')
start=time.time()
res=func(*args,**kwargs) #调到outter内的wrapper1
stop=time.time()
print ('run time is %s' %(stop - start))
return res
return wrapper2 def outter(func): # func=最原始的index
def wrapper1(*args,**kwargs):
print('wrapper1 run...')
if current_userinfo['user']: #判断是否已登陆
return func(*args,**kwargs)
else:
user=input('please input username:').strip()
pwd=input('please input password:').strip()
if user == 'andy' and pwd =='':
print('login successfully')
#保存登陆状态
current_userinfo['user']=user
res=func(*args,**kwargs) #调用最原始的index
return res
else:
print ('user or password wrong')
return wrapper1
# 可以连续写多个装饰器,处于最顶层的装饰器先执行,解释语法自下而上,执行时则自上而下
@outter #
@timmer #
def index():
print('welcom to index page')
time.sleep(1)
index() #index==>wrapper2

输出:

wrapper1 run...
please input username:andy
please input password:123
login successfully
wrapper2 run...
welcom to index page
run time is 1.0009920597076416

 #有参装饰器
#认证功能装饰器实现
import time current_userinfo={'user':None}
def auth(engine='file'):
def outter(func): # func为被装饰对象
def wrapper(*args,**kwargs):
if engine == 'file':
if current_userinfo['user']: #判断是否已登陆
return func(*args,**kwargs)
else:
user=input('please input username:').strip()
pwd=input('please input password:').strip()
if user == 'andy' and pwd =='':
print('login successfully')
#保存登陆状态
current_userinfo['user']=user
res=func(*args,**kwargs)
return res
else:
print ('user or password wrong')
elif engine == 'mysql':
print ('mysql 的认证机制')
elif engine == 'ldap':
print ('ldap 的认证机制')
else:
print('不支持该engine')
return wrapper
return outter
@auth(engine='mysql')
#@outter #index=outter(index) #index=wrapper
def index():
print('welcom to index page')
time.sleep(1)
@auth(engine='file')
def home(name):
print('welcom to home page')
time.sleep(2)
return 123 index() #wrapper() 为实际调用函数,需模拟原先的内部逻辑
res=home('andy') #wrapper('andy')

输出:
mysql 的认证机制
please input username:andy
please input password:123
login successfully
welcom to home page

 #加了装饰器,目的是不改变原来的调用方式,对使用者是透明的
import time
from functools import wraps def timmer(func):
@wraps(func)
def wrapper(*args,**kwargs):
start=time.time()
res=func(*args,**kwargs)
stop=time.time()
print ('run time is %s' %(stop - start))
return res
#wrapper.__doc__=func.__doc__
#wrapper.__name__=func.__name__
return wrapper
@timmer #index=timer(index)
def index():
"""
这是一个index函数
:return
"""
print('welcom to index page')
time.sleep(1)
return 123
print(help(index))
#print(index.__name__)

输出:
Help on function index in module __main__:

index()
    这是一个index函数
    :return

None

 #三元表达式
def max2(x,y):
if x>y:
return x
else:
return y
res=max2(1,2) res=True if x>y else False
print (res) #列表生成式
l=[]
for i in range(10):
l.append(i)
print(l) l1=[i for i in range(10)]
print(l1) #字典生成式
s={i:i for i in range(10) if i>3}
print (s) info=[
['name','alex'],
('age',18)
['sex','male']
]
d={item[0]:item[1] for item in info}
print(d) d={k.upper():v for k,v in d.items()}
print(d)

二.函数递归
    函数递归调用,在调用一个函数的过程中又直接或间接地调用了自己称之为函数的递归调用
    本质就是一个重复的过程,递归必须要满足两个阶段
    1.回溯:一层一层地递归调用下去
    2.递推:递归必须要有一个明确的结束条件,在满足该条件下终止递归,往回一层一层地结束调用
    递归vs while循环
    递归只需要把控住结束或进入递归的条件即可,至于循环次数无需考虑

 #直接递归
def foo(n):
print('from foo',n)
foo(n+1)
foo(0) #间接递归
def bar():
print('from bat') def foo():
print('from foo')
bar()
foo()
 def age(n):
if n==1:
return 18
return age(n-1) +2 print(age(5))

输出:26

 l=[1,[2,[3,]]]
def tell(l):
for item in l:
if type(item) is not list:
print(item)
else:
#再次调用本身的逻辑,传入item
tell(item)
tell(l)

输出:

1
2
3

 nums=[3,11,13,15,23,27,43,51,72,81,93,101]
#算法,就是高效解决某个具体问题的方法
#find_num=23
def binary_search(nums,find_num):
print(nums)
if len(nums) == 0:
print('not exists')
return
mid_index=len(nums) // 2
if find_num>nums[mid_index]:
nums=nums[mid_index+1:]
binary_search(nums,find_num)
elif find_num < nums[mid_index]:
nums=nums[:mid_index]
binary_search(nums,find_num)
else:
print('find it')
binary_search(nums,99)
binary_search(nums,3)

输出:
[3, 11, 13, 15, 23, 27, 43, 51, 72, 81, 93, 101]
[51, 72, 81, 93, 101]
[93, 101]
[93]
[]
not exists
[3, 11, 13, 15, 23, 27, 43, 51, 72, 81, 93, 101]
[3, 11, 13, 15, 23, 27]
[3, 11, 13]
[3]
find it

三.匿名函数

  匿名函数lambda:只用一次以后不会再用了

(lambda x,y:x+y)(4,5)

输出:9

#原方法
salaries={
'andy':1000,
'alex':2000,
'lily':400
}
def func(k):
return salaries[k]
print(max(salaries,key=func))
#使用匿名函数
salaries={
'andy':1000,
'alex':2000,
'lily':400
} print(max(salaries,key=lambda x:salaries[x]))

输出:alex

 num=[3,1,4,9]
l=sorted(num)
print (l)
l=sorted(num,reverse=True)
print (l)

输出:
[1, 3, 4, 9]
[9, 4, 3, 1]

 salaries={
'andy':1000,
'alex':2000,
'lily':400
} print(sorted(salaries,key=lambda x:salaries[x]))

输出:

['lily', 'andy', 'alex']

 #了解map,reduce,filter
#map映射
names=['andy','alex','tom']
res=map(lambda x:x+'_dsb',names)
print (list(res))

输出:

['andy_dsb', 'alex_dsb', 'tom_dsb']

 #filter过滤
names=['andy_dsb', 'alex_dsb', 'tom_dsb']
res=filter(lambda x:x.endswith('dsb'),names)
print (res)
for item in res:
print(item)
l=[name for name in names if name.endswith('dsb')]
print(l)

输出:

<filter object at 0x0000023BB55D6A58>
andy_dsb
alex_dsb
tom_dsb
['andy_dsb', 'alex_dsb', 'tom_dsb']

 #reduce合并
from functools import reduce
l=['a','b','c','d','e']
res=reduce(lambda x,y:x+y,l,'AAA')
print(res)

输出:

AAAabcde

 from functools import reduce
l=['a','b','c','d','e']
res=reduce(lambda x,y:x+y,l)
print(res)

输出:

abcde

四.模块
1.什么是模块
    模块就是一系列功能的集合体,
    模块分为三大类:
        1.自定义模块
        2.内置模块:time,sys
        3.第三方的模块
    模块的表现形式有
        1.使用python编写的.py文件
        2.已被编译为共享库或DLL的C或C++扩展
        3.把一系列模块组织到一起的文件夹(注:文件夹下有一个__init__.py文件,该文件夹称之为包)
        4.使用C编写并链接到python解释器的内置模块
2.为何要用模块
    1.可以拿来内置或第三方的模块,然后直接使用,这种拿来主义,会极大地提高开发效率
    2.将程序中公用的一些功能组织到一个文件中,然后程序个部分功能可以重用该文件的功能
    优点是减少代码冗余,增强程序的组织结构性和可维护性
3.如何用模块
    一个py文件就是一个模块
4.首次导入模块会发生三件事:
    1.创建一个模块spam.py的名称空间
    2.执行模块对应的spam.py,将产生的名字丢到模块的名称空间
    3.在当前执行的名称空间中拿到一个名字spam,该名字就是指向模块spam.py的名称空间的内存地址
    import spam #spam=spam.py
    import spam #后续的导入执行引用之前导入的结果spam=spam.py名称空间的内存地址
    print (spam.money)
两种导入方式的优缺点:
from import vs import
相同点:函数的作用域关系在定义阶段就规定死了,与调用位置无关
from import
优点:可以不用加前缀而直接引用名字,更简洁
缺点:容易与当前执行文件中的名字冲突
import
优点:指名道姓跟某一个名称空间要名字,肯定不会与当前名称空间的名字相冲突
缺点:必须加上前缀

#一个python文件有两种用途
1.可以执行: __name__ =='__main__'
2.可以被当作模块导入:__name__=='模块名'
模块的搜索优先级:
1.内存
2.内置的模块
3.sys.path

 import sys
print(sys.path)