函数
函数的基本使用
1、什么是函数?
在程序中,函数就具备某一功能的工具
事先将工具准备好即函数的定义
遇到应用场景拿来就用即函数的调用
所以务必记住:#函数的使用必须遵循先定义,后调用的原则
2、为何要用函数
不用函数问题是:
1、程序冗长
2 程序的扩展性差
3 程序的可读性差
3 如何用函数:
函数的使用必须遵循先定义,后调用的原则
def 函数名(参数1,参数2,...):
函数功能的描述信息
:param 参数1: 描述
:param 参数2: 描述
:return: 返回值
'''
代码1
代码2
代码3
...
return 返回值
函数的分类
1、内置函数 为了方便我们的开发,针对一些简单的功能,python解释器已经为我们定义好了的函数即内置函数。对于内置函数,我们可以拿来就用而无需事先定义,如len(),sum(),max() ps:我们将会在最后详细介绍常用的内置函数。 2、自定义函数 很明显内置函数所能提供的功能是有限的,这就需要我们自己根据需求,事先定制好我们自己的函数来实现某种功能,以后,在遇到应用场景时,调用自定义的函数即可。
什么时候该有返回值? 调用函数,经过一系列的操作,最后要拿到一个明确的结果,则必须要有返回值 通常有参函数需要有返回值,输入参数,经过计算,得到一个最终的结果
什么时候不需要有返回值? 调用函数,仅仅只是执行一系列的操作,最后不需要得到什么结果,则无需有返回值 通常无参函数不需要有返回值
准备好工具=>函数的定义阶段
def register():
while True:
uname=input('username>>:').strip()
if uname.isalpha():
break
else:
print('用户名必须由字母组成傻叉')
while True:
pwd1=input('密码>>: ').strip()
pwd2=input('重复输入密码>>: ').strip()
if pwd1 == pwd2:
break
else:
print('两次输入的密码不一致,眼瞎吗')
with open('db.txt','at',encoding='utf-8') as f:
f.write('%s:%s\n' %(uname,pwd1))
f.flush()
def auth():
#认证功能
inp_uname=input('请输入你的账号:').strip()
inp_pwd=input('请输入你的密码:').strip()
with open('db.txt','rt',encoding='utf-8') as f:
for line in f:
info=line.strip('\n').split(':')
if inp_uname == info[0] and inp_pwd == info[1]:
print('login successfull')
break
else:
print('账号或密码错误')
拿来就用=>函数的调用阶段
print(register)
register()
auth()
register()
register()
register()
函数的定义阶段和调用阶段
函数的使用必须遵循先定义,后调用的原则,
没有事先定义函数,而直接引用函数名,就相当于在引用一个不存在的变量名
1、函数定义阶段:只检测函数体的语法,不执行函数体代码
def func():
print('1111')
print('222')
print('333')
2、函数调用阶段:执行函数体代码
func()
例1
def foo():
print('from foo')
bar()
foo()
例2
def bar():
print('from bar')
def foo():
print('from foo')
bar()
foo()
例3
def foo():
print('from foo')
bar()
def bar():
print('from bar')
foo()
例4
def foo():
print('from foo')
bar()
foo()
def bar():
print('from bar')
函数的定义
定义函数时的参数就是函数体接收外部传值的一种媒介,其实就一个变量名
1、无参函数:
在函数定义阶段括号内没有参数,称为无参函数
注意:定义时无参,意味着调用时也无需传入参数
应用:
如果函数体代码逻辑不需要依赖外部传入的值,必须定义无参函数
def func():
print('hello world')
func()
2、有参函数
在函数定义阶段括号内有参数,称为有参函数
注意:定义时有参,意味着调用时也必须传入参数
应用:
如果函数体代码逻辑需要依赖外部传入的值,必须定义成有参函数
def sum2(x,y):
# x=10
# y=20
res=x+y
print(res)
sum2(10,20)
sum2(30,40)
def check_user():
while True:
uname=input('username>>:').strip()
if uname.isalpha():
return uname
# break
else:
print('用户名必须由字母组成傻叉')
def check_pwd():
while True:
pwd1=input('密码>>: ').strip()
pwd2=input('重复输入密码>>: ').strip()
if pwd1 == pwd2:
return pwd1
else:
print('两次输入的密码不一致,眼瞎吗')
def db_hanle(uname,pwd1):
with open('db.txt','at',encoding='utf-8') as f:
f.write('%s:%s\n' %(uname,pwd1))
f.flush()
def register():
# 检测用户名是否合法
x=check_user() #x='EGON'
# 检测密码是否合法
y=check_pwd() #y='123'
# 写入数据文件
# db_hanle(合法的用户名,合法的密码)
db_hanle(x,y)
register()
3、空函数
def func():
pass
def check_user():
pass
def check_pwd():
pass
def write_db(x,y):
pass
def register():
#1 输入用户名,并进行合法性校验
#2 输入密码,并进行合法性校验
#3 将合法的用户名、密码写入文件
x=check_user()
y=check_pwd()
write_db(x,y)
'函数的返回值
1、什么是返回值
返回值是一个函数的处理结果,
2、为什么要有返回值
如果我们需要在程序中拿到函数的处理结果做进一步的处理,则需要函数必须有返回值
3、函数的返回值的应用
函数的返回值用return去定义
格式为:
return 值
注意:
1、return是一个函数结束的标志,函数内可以有多个return,
但只要执行一次,整个函数就会结束运行
2、return 的返回值无类型限制,即可以是任意数据类型
3、return 的返回值无个数限制,即可以用逗号分隔开多个任意类型的值
0个:返回None,ps:不写return默认会在函数的最后一行添加return None
1个:返回的值就是该值本身
多个:返回值是元组
'''
# def max2(x,y): #x=3000,y=2000
# if x > y:
# return x #return 3000
# else:
# return y #reuturn 2000
#
# res=max2(3000,2000)
#
# annual_salary=res * 12
#
# print(annual_salary)
# def foo():
# print(1)
# print(2)
# print(3)
# return [1,2,3],'a',('a','b'),{1,2}
# print(4)
# print(5)
# print(6)
#
# res=foo()
# print(res)
# def bar():
# print(1)
# print(1)
# print(1)
# print(1)
# return
# print(2)
# print(3)
# print(4)
#
# res=bar()
# print(res)
函数的调用
1 什么是调用函数
函数名(...)即调用函数,会执行函数体代码,直到碰到return结束或者一直运行完毕所有代码
2 为何要调用函数
用函数的功能
3、函数调用分为三种形式
max2(1,2)
res=max2(3000,2000) * 12
res=max2(max2(1000,2000),3000)
'''
# def foo():
# print(1)
# print(2)
# print(3)
# return None
# res=foo()
# print(res)
def max2(x,y):
if x > y:
return x
else:
return y
#形式一:
# max2(1,2)
#形式二:
# res=max2(3000,2000) * 12
# print(res)
#形式三:
res=max2(max2(1000,2000),3000)
print(res)
函数的参数
#总的分类:
# #1、形参:在函数定义阶段括号内定义的参数,称之为形式参数,简称形参,本质就是变量名
# def foo(x,y): #x=1,y=2
# print(x)
# print(y)
# #2、实参:在函数调用阶段括号内传入的值,称之为实际参数,简称实参,本质就是变量的值
# foo(1,2)
#
#详细的分类:
#一、位置参数:
#位置形参:在函数定义阶段,按照从左到右的顺序依次定义的形参,称之为位置形参
#特点:但凡是按照位置定义的形参,都必须被传值,多一个不行,少一个也不行
# def foo(x,y):
# print('x:',x)
# print('y:',y)
#位置实参:在函数调用阶段,按照从左到右的顺序依次定义的实参,称之为位置实参
#特点:按照位置为对应的形参依次传值
# foo(1,2)
# foo(2,1)
#二、关键字实参:在调用函数时,按照key=value的形式为指定的参数传值,称为关键字实参
#特点:可以打破位置的限制,但仍能为指定的形参赋值
# foo(y=2,x=1)
#注意:
#1、可以混用位置实参与关键字实参,但位置实参必须放在关键字实参的前面
# foo(1,y=2)
# foo(y=2,1) #SyntaxError: positional argument follows keyword argument
#2、可以混用,但不能对一个形参重复赋值
# foo(1,y=2,x=10)
#三:默认参数:在函数定义阶段,就已经为形参赋值,该形参称为默认形参
#特点:在定义阶段就已经被赋值,意味着在调用可以不用为其赋值
# def foo(x,y=10):
# print('x:',x)
# print('y:',y)
# foo(1)
# foo(1,3)
# 注意:
#1、位置形参必须放到默认形参的前面,否则报语法错误
# def foo(x=1,y):
# pass
#2、默认参数的值只在定义阶段赋值一次,即默认参数的值在函数定义阶段就已经固定死了
# m=10
# def foo(x=m,y=11):
# print(x)
# print(y)
# m=1111111111111111111111111111111111111111111111111111111111
# foo()
#3、默认参数的值通常应该定义不可变类型
# def register(name,hobby,hobbies=[]):
# hobbies.append(hobby)
# print('%s的爱好' %name,end=':')
# print(hobbies)
#
# register('egon','play')
# register('alex','piao')
# register('lxx','烫头')
# def register(name,hobby,hobbies=None):
# if hobbies is None:
# hobbies=[]
# hobbies.append(hobby)
# print('%s的爱好' %name,end=':')
# print(hobbies)
#
# register('egon','play')
# register('alex','piao')
# register('lxx','烫头')
#总结:
#实参的应用:取决于个人习惯,
#形参的应用:
#1、位置形参:大多数情况下的调用值都不一样,就应该将该参数定义成位置形参
#2、默认形参:大多数情况下的调用值都一样,就应该将该参数定义成默认形参
# def register(name,age,sex='male'):
# print(name)
# print(age)
# print(sex)
#
#
# register('egon',18,)
# register('大脑门',73,'female')
# register('小脑门',84,)
# register('大高个',18,)
#四:可变长参数:指的是在调用函数时,传入的参数个数可以不固定
#而调用函数时,传值的方式无非两种,一种位置实参,另一种时关键字实参
#所以对应着,形参也必须有两种解决方案,来分别接收溢出的位置实参(*)与关键字实参(**)
#1、形参中某个参数带*
#形参中的*会将溢出的位置实参全部接收,然后存储元组的形式,然后把元组赋值给*后的变量名
# def foo(x,y,*z): #x=1,y=2,z=(3,4,5,6,7)
# print(x)
# print(y)
# print(z)
# foo(1,2,3,4,5,6,7)
# 应用
# def my_sum(*nums):
# res=0
# for num in nums:
# res+=num
# return res
#
# print(my_sum(1,2,3,4,5))
# 2、实参中的参数也可以带*
# 实参中带*,*会将该参数的值循环取出,打散成位置实参
#ps:以后但凡碰到实参中带*的,它就是位置实参,应该立马打散成位置实参去看
# def foo(x,y,z):
# print(x,y,z)
# foo(1,*[2,3]) #foo(1,2,3)
# foo(1,*'he') #foo(1,'h','e')
# foo(1,*(2,3,4)) #foo(1,2,3,4)
# def foo(x,y,z,*args):
# print(x)
# print(y)
# print(z)
# print(args)
#
# foo(1,2,3,4,5,6,7,*[8,9,10,11]) #foo(1,2,3,4,5,6,7,8,9,10,11)
#注意:约定俗成形参中的*变量名的写法都是:*args
#1、形参中某个参数带**
#形参中的**会将溢出的关键字实参全部接收,然后存储字典的形式,然后把字典赋值给**后的变量名
# def foo(x,y,**z): #x=1,y=2,z={'c':5,'b':4,'a':3}
# print(x)
# print(y)
# print(z)
# foo(1,2,a=3,b=4,c=5)
# 2、实参中的参数也可以带**,该参数必须是字典
# 实参中带**,**会将该参数的值循环取出,打散成关键字实参
#ps:以后但凡碰到实参中带**的,它就是关键字实参,应该立马打散成关键字实参去看
# def foo(x,y,z):
# print(x)
# print(y)
# print(z)
# foo(1,2,**{'a':1,'b':2,'c':3,'z':3}) #foo(1,2,c=3,b=2,a=1,z=3)
# foo(**{'z':3,'x':1,'y':2}) #foo(y=2,x=1,z=3)
#注意:约定俗成形参中的**变量名的写法都是:**kwargs
# def index(name,age,sex):
# print('welecome %s:%s:%s to index page' %(name,age,sex))
#
# def wrapper(*args,**kwargs): #args=(1,),kwargs={'x': 1, 'y': 2, 'z': 3}
# index(*args,**kwargs) #index(*(1,),**{'x': 1, 'y': 2, 'z': 3}) #index(1,x=1,y=2,z=3)
#
# wrapper(name='egon',sex='male',age=18)
#
#五 命名关键字形参:在函数定义阶段,*后面的参数都是命名关键字参数(**)
# 特点:在传值时,必须按照key=value的传,并且key必须命名关键字参数指定的参数名
# def register(x,y,z,**kwargs): #kwargs={'b':18,'a':'egon'}
# if 'name' not in kwargs or 'age' not in kwargs:
# print('用户名与年龄必须使用关键字的形式传值')
# return
# print(kwargs['name'])
# print(kwargs['age'])
# register(1,2,3,a='egon',b=18)
# def register(x,y,z,*args,name='egon',age):
# print(args)
# print(name)
# print(age)
# register(1,2,3,4,5,6,7,age=18)
#
# def foo(x,y=1,*args,z=1,a,b,**kwargs):
# pass
# foo(1,*[1,2,3],a=1,**{'x':1,'y':2}) #foo(1,1,2,3,a=1,y=2,x=1)
# foo(1,2)
# foo(x=1,y=2)
open('a.txt','w',encoding='utf-8')
函数的对象
#函数是第一类对象的含义是函数可以被当作数据处理
def func(): #func=<function func at 0x0584BA50>
print('from func')
# print(func)
x='hello'
#1、引用
# y=x
# f=func
# print(f)
# f()
#2、当作参数传给一个函数
# len(x)
# def foo(m):
# # print(m)
# m()
#
# foo(func)
#3、可以当作函数的返回值
# def foo(x): #x=func
# return x #return func
#
# res=foo(func)
# print(res)
# res()
#4、可以当作容器类型的元素
# l=[x,]
# l=[func,]
# # print(l)
#
# l[0]()
def pay():
print('支付。。。')
def withdraw():
print('取款。。。')
def transfer():
print('转账。。。')
def check_balance():
print('查看余额。。。')
def shopping():
print('购物。。。')
func_dic={
'1':pay,
'2':withdraw,
'3':transfer,
'4':check_balance,
'6':shopping
}
while True:
msg="""
1 支付
2 取款
3 转账
4 查看余额
5 退出
6 购物
"""
print(msg)
choice=input('>>: ').strip()
if choice == '5':break
if choice not in func_dic:
print('输入的指令不存在傻叉')
continue
func_dic[choice]()
函数嵌套
#函数的嵌套定义
def f1():
def f2():
print('from f2')
f2()
f1()
# from math import pi
#
# def circle(radius,action='area'): #radius=10
# def area():
# return pi * (radius ** 2)
#
# def perimeter():
# return 2 * pi * radius
#
# if action == 'area':
# return area()
# elif action == 'perimeter':
# return perimeter()
#
# print(circle(10))
# print(circle(10,action='perimeter'))
#函数的嵌套调用
# def max2(x,y):
# if x > y:
# return x
# else:
# return y
#
# def max4(a,b,c,d):
# res1=max2(a,b)
# res2=max2(res1,c)
# res3=max2(res2,d)
# return res3
#
# print(max4(1,2,3,4))
名称空间和作用域
1、名称空间namespaces
存放名字与值绑定关系的地方
2、名称空间分为三大类
内置名称空间:
作用:存放python解释器自带的名字
生命周期:
在解释器启动时生效,在解释器关闭时失效
全局名称空间:
作用:除了内置的与局部的名字外,其余都是全局名字
生命周期:
在文件执行时生效,在文件执行完毕时失效
例如:x,func,y,l,z都是
x=1
def func():
a=1
y=2
l=[1,2]
if 3 > 2:
if
if
if
z=3
局部名称空间:
作用:用于存放函数调用期间函数体产生的名字
生命周期:
在文件执行过程
如果调用了某个函数才会临时生效,在函数执行完毕后失效
三种名称空间的加载顺序是:
内置-》全局-》局部
名称空间就是用来存放名字与值的绑定关系的,所以但凡要查找名字
一定是从三者之一找到,查找顺序:
从当前所在的位置倒着查找,如果当前所在的位置是局部名称空间,
则查找顺序是:
局部-》全局-》内置
3、作用域:
域指的是区域、范围,作用域即作用的范围
全局作用范围,全局作用域(内置名称空间与全局名称空间)
全局有效,全局存活
局部作用范围,局部作用域(局部名称空间)
局部有效,临时存活
'''
# x=1
# # len=100
# def func():
# y=2
# len=1000
# # print(len)
# print(a)
# # func()
#
# print(len)
# def func():
# y=2
# print(x)
#
# x=1
# func()
#
# x=10
# x=1
# def f1():
# def f2():
# def f3():
# zzz=333
# print(x)
# # x = 22222
# f3()
# # x=111111
# f2()
#
# def bar():
# print(x)
#
# f1()
# bar()
# 作用域关系是在函数定义阶段就固定死了,但凡调用函数都需要跑到定义阶段去找作用域关系
# x=1
# def f1():
# print(x)
#
# # f1()
# x=1000000000000000000000000000000000000000000000000000000000000000
# def f2():
# # print(f1)
# x=11111111111111111111111111111
# f1()
#
# f2()
#函数对象+作用域:******
# def f1():
# x=1
# def inner():
# print('from inner',x)
# return inner
#
# f=f1()
#
# # print(f)
#
# def bar():
# x=111111111111111111111111111111111111111111111
# f()
#
# bar()
#
# x=1
# def foo():
# global x
# x=2
#
# foo()
# print(x)
# x=1
# def f1():
# def f2():
# x=22222222
# def f3():
# global x
# x=11111111111111111
# f3()
# f2()
#
# f1()
# print(x)
# x=1
# def f1():
# # x=33333
# def f2():
# # x=22222222
# def f3():
# nonlocal x
# x=20000000000
# f3()
# print(x)
# f2()
#
# f1()
# print(x)
# 在局部如果想要修改全局的可变类型,不需要借助任何声明,可以直接修改
# 在局部如果想要修改全局的不可变类型,需要借助global声明,声明为全局的变量就可以直接修改了
# x=[]
# def f1():
# x.append(1)
# f1()
# f1()
# print(x)
闭包函数
#作用域关系在函数定义阶段时就已经固定死了,与调用位置无关
# 即:在任意位置调用函数都需要跑到定义函数时寻找作用域关系
# def f1():
# x=1
# def inner():
# print(x)
#
# return inner
#
# func=f1()
#
# def f2():
# x=111111
# func()
#
# f2()
# 闭包函数:
# 闭指的是:该函数是一个内部函数
# 包指的是:指的是该函数包含对外部作用域(非全局作用域)名字的引用
# def outter():
# x = 1
# def inner():
# print(x)
#
# return inner
#
# f=outter()
#
# def f2():
# x=1111111
# f()
#
# f2()
#
#
# def f3():
# x=4444444444444
# f()
#
# f3()
# 为函数体传值的方式一:使用参数的形式
# def inner(x):
# print(x)
#
# inner(1)
# inner(1)
# inner(1)
# 为函数体传值的方式二:包给函数
'''
def outter(x):
# x=1
def inner():
print(x)
return inner
f=outter(1)
f()
'''
# import requests
#
# def get(url):
# response=requests.get(url)
# if response.status_code == 200:
# print(response.text)
#
# get('https://www.baidu.com')
# get('https://www.baidu.com')
# get('https://www.baidu.com')
#
# get('https://www.python.org')
# get('https://www.python.org')
# get('https://www.python.org')
# get('https://www.python.org')
import requests
def outter(url):
# url='https://www.baidu.com'
def get():
response=requests.get(url)
if response.status_code == 200:
print(response.text)
return get
baidu=outter('https://www.baidu.com')
python=outter('https://www.python.org')
baidu()
baidu()
python()
python()
装饰器
'''
1、什么是装饰器
器指的是工具,而程序中的函数就具备某一功能的工具
装饰指的是为被装饰器对象添加额外功能
就目前的知识来看:
定义装饰器就是定义一个函数,只不过该函数的功能是用来为
其他函数添加额外的功能
其实:
装饰器本身其实可以是任意可调用的对象
被装饰的对象也可以是任意可调用的对象
2、为什么要用装饰器
软件的维护应该遵循开放封闭原则
开放封闭原则指的是:
软件一旦上线运行后对修改源代码是封闭的,对扩展功能的是开放的
这就用到了装饰器
装饰器的实现必须遵循两大原则:
1、不修改被装饰对象的源代码
2、不修改被装饰对象的调用方式
装饰器其实就在遵循1和2原则的前提下为被装饰对象添加新功能
3、如何用装饰器
'''
# import time
#
# def index():
# start=time.time()
# print('welcom to index')
# time.sleep(3)
# stop=time.time()
# print('run time is %s' %(stop-start))
# index()
# import time
#
# def index():
# print('welcom to index')
# time.sleep(3)
#
# def f2():
# print('from f2')
# time.sleep(2)
#
# start=time.time()
# index()
# stop=time.time()
# print('run time is %s' %(stop-start))
#
# start=time.time()
# f2()
# stop=time.time()
# print('run time is %s' %(stop-start))
# import time
#
# def index():
# print('welcom to index')
# time.sleep(3)
#
# def timmer(func):
# start=time.time()
# func()
# stop=time.time()
# print('run time is %s' %(stop-start))
#
# timmer(index)
'''
import time
def index():
print('welcom to index')
time.sleep(3)
def timmer(func): #func=最原始的index
# func=index
def inner():
start=time.time()
func()
stop=time.time()
print('run time is %s' %(stop-start))
return inner
# f=timmer(index)
# f()
# index=timmer(被装饰函数的内存地址)
index=timmer(index) #index=inner
index() #inner()
'''
import time
def index():
print('welcom to index')
time.sleep(3)
def timmer(func):
#func=最原始的index
def wrapper():
start=time.time()
func()
stop=time.time()
print('run time is %s' %(stop - start))
return wrapper
index=timmer(index) #index=wrapper函数的内存地址
index()
装饰器修正
无参装饰器
# import time
#
# def index():
# print('welcome to index')
# time.sleep(3)
# return 123
#
# def home(name):
# print('welcome %s to home page' %name)
# time.sleep(2)
#
#
# def timmer(func):
# #func=最原始的index
# 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=timmer(index)
# home=timmer(home)
#
# res=index()
# home('egon')
#装饰器语法糖
# 在被装饰对象正上方,并且是单独一行写上@装饰器名
# import time
# def timmer(func):
# #func=最原始的index
# 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=timmer(index)
# def index():
# print('welcome to index')
# time.sleep(3)
# return 123
#
# @timmer # home=timmer(home)
# def home(name):
# print('welcome %s to home page' %name)
# time.sleep(2)
#
# res=index()
# home('egon')
def deco(func):
def wrapper(*args,**kwargs):
res=func(*args,**kwargs)
return res
return wrapper
有参装饰器
import time
current_user={'user':None}
def deco(func):
def wrapper(*args,**kwargs):
if current_user['user']:
#已经登陆过
res = func(*args, **kwargs)
return res
user=input('username>>: ').strip()
pwd=input('password>>: ').strip()
if user == 'egon' and pwd == '123':
print('login successful')
# 记录用户登陆状态
current_user['user']=user
res=func(*args,**kwargs)
return res
else:
print('user or password error')
return wrapper
@deco
def index():
print('welcome to index page')
time.sleep(1)
@deco
def home(name):
print('welecome %s to home page' %name)
time.sleep(0.5)
index()
home('egon')
'''
'''
def f1():
x=1
def f2():
def f3():
print(x)
return f3
return f2
f2=f1()
f3=f2()
f3()
'''
import time
current_user={'user':None}
def auth(engine='file'):
def deco(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 successful')
# 记录用户登陆状态
current_user['user']=user
res=func(*args,**kwargs)
return res
else:
print('user or password error')
elif engine == 'mysql':
print('基于mysql的认证')
elif engine == 'ldap':
print('基于ldap的认证')
else:
print('无法识别认证来源')
return wrapper
return deco
@auth(engine='mysql') # @deco #index=deco(index) #index=wrapper
def index():
print('welcome to index page')
time.sleep(1)
@auth(engine='mysql')
def home(name):
print('welecome %s to home page' %name)
time.sleep(0.5)
index()
home('egon')
迭代器
'''
1、什么是迭代器
迭代器即迭代取值的工具
迭代:
迭代是一个重复的过程,每一次重复都是基于上一次的结果而来的
单纯的重复并不是迭代
while True:
print('1111')
迭代:
l=['a','b','c']
def iterator(item):
i=0
while i < len(item):
print(l[i])
i+=1
2、 为什么要有迭代器
基于索引的迭代器取值方式只适用于列表、元组、字符串类型
而对于没有索引的字典、集合、文件,则不在适用
所以必须找到一种通用的并且不依赖于索引的迭代器取值方式=》迭代器
迭代器适用于可迭代的类型
3、如何用迭代器
'''
# l=['a','b','c']
# i=0
# while i < len(l):
# print(l[i])
# i+=1
# l = ['a', 'b', 'c']
# s='hello'
#
# def iterator(item): #item='hello'
# i = 0
# while i < len(item):
# print(item[i])
# i += 1
# # iterator(l)
# iterator(s)
# 可迭代的对象:在python中但凡内置有__iter__方法的对象都是可迭代的对象
# 字符串、列表、元组、字典、集合、文件都是可迭代的对象
# num1=10
# num2=10.1
# s1='hello'
# l=[1,2,3]
# t=(1,2,3)
# d={'x':1}
# s2={1,2,3}
# f=open('a.txt','w')
#
# s1.__iter__
# l.__iter__
# t.__iter__
# d.__iter__
# s2.__iter__
# f.__iter__
#
#
# 迭代器对象:指的是既内置有__iter__方法,又内置有__next__方法的对象
#执行可迭代对象的__iter__方法得到的就是内置的迭代器对象
# 文件对象本身就是迭代器对象
#强调:
#1、迭代器对象一定是可迭代的对象,反之则不然
# info={'name':'egon','age':18,'is_beautiful':True,'sex':'male'}
# info_iter=info.__iter__()
# # print(info_iter)
#
# res1=info_iter.__next__()
# print(res1)
#
# res2=info_iter.__next__()
# print(res2)
#
# res3=info_iter.__next__()
# print(res3)
#
# res4=info_iter.__next__()
# print(res4)
#
# info_iter.__next__() # 一旦迭代器取值取干净,再继续取就会抛出StopIteration
# info={'name':'egon','age':18,'is_beautiful':True,'sex':'male'}
# # info=[1,2,3,4,5]
# info_iter=info.__iter__()
# while True:
# try:
# print(info_iter.__next__())
# except StopIteration:
# break
#for循环:迭代器循环
# info={'name':'egon','age':18,'is_beautiful':True,'sex':'male'}
#in后跟的一定要是可迭代的对象
# for k in info: # info_iter=info.__iter__()
# print(k)
# f=open('a.txt','r')
# for k in f:
# print(k)
# 迭代器对象:指的是既内置有__iter__方法,又内置有__next__方法的对象
# 执行迭代器对象的__next__得到的是迭代器的下一个值
# 执行迭代器对象的__iter__得到的仍然是迭代器本身
# iter_info=info.__iter__()
# # print(iter_info)
# print(iter_info is iter_info.__iter__() is iter_info.__iter__().__iter__().__iter__().__iter__().__iter__())
#
#总结迭代器对象的优缺点:
#优点:
1、提供了一种通用的、可以不依赖索引的迭代取值方式
2、迭代器对象更加节省内存
# 缺点:
#1、迭代器的取值不如按照索引的方式更灵活,因为它只能往后取不能往前退
#2、无法预测迭代器值的个数
# names=['egon','alex_SB','wxx_SB']
# iter_names=iter(names)
# print(next(iter_names))
生成器
'''
1 什么是生成器?
在函数内但凡出现yield关键字,再调用函数就不会执行函数体代码,会返回值一个值,该值称之为生成器
生成器本质就是迭代器
2、为什么要有生成器?
生成器是一种自定义迭代器的方式
3、如何用生成器
'''
# def func():
# print('first1')
# print('first2')
# print('first3')
# yield 1 #暂停
# print('second1')
# print('second2')
# print('second3')
# yield 2 #暂停
# print('third')
# yield 3 #暂停
# print('fourth')
#
# g=func()
# print(g)
# print(g.__iter__().__iter__().__iter__() is g)
# res1=next(g)
# print('第一次的返回值:',res1)
#
# print('='*100)
# res2=next(g)
# print('第二次的返回值:',res2)
#
# print('='*100)
# res3=next(g)
# print('第三次的返回值:',res3)
#
# print('='*100)
# res4=next(g)
# print('第三次的返回值:',res4)
# for item in g: #g=iter(g) #item=next(g)
# print(item)
# i=range(1,1000)
# for item in range(1,1000000000)
# def my_range(start,stop,step=1):
# while start < stop:
# yield start # 暂停
# start+=step
# g=my_range(1,5,2) #1 3
# print(next(g))
# print(next(g))
# print(next(g))
# print(next(g))
# print(next(g))
# print(next(g))
# print(next(g))
# for item in g:
# print(item)
#总结yield的功能
#1、提供一种自定义迭代器的方式
#2、yield可以暂停住函数,返回值
#yield VS return
#相同点:都是用在函数内,都可以返回值,没有类型限制,没有个数限制
#不同点:return只能返回一次值,yield可以返回多次值
# 了解知识
# yield 值
# x=yield
# x= yield 值
def dog(name):
food_list=[]
print('狗哥 %s 准备开吃' %name)
while True:
food=yield food_list#暂停 food=yield='一桶泔水'
print('狗哥[%s]吃了<%s>' %(name,food))
food_list.append(food)
alex_dog=dog('alex')
res1=next(alex_dog) # 初始化,即让狗准备好
print(res1)
# next(alex_dog) # 等同于alex_dog.send(None)
#
# next(alex_dog)
res2=alex_dog.send(('一泡翔','咖啡伴侣'))
print(res2)
res3=alex_dog.send('一桶泔水')
print(res3)
#
# 列表生成式
# l=[item**2 for item in range(1,11)]
# print(l)
# names=['alex','wxx','lxx']
# l=[]
# for name in names:
# l.append(name + 'SB')
# names=l
# names=[name+'SB' for name in names]
# print(names)
# names=['alex','wxx','egon','lxx','zhangmingyan']
# l=[]
# for name in names:
# if name != 'egon':
# l.append(name + 'SB')
# names=l
# names=[name+'SB' for name in names if name != 'egon']
# print(names)
# l=[item**2 for item in range(1,5) if item > 2]
# print(l)
# names=['egon','alex_sb','wupeiqi','yuanhao']
# names=[name.upper() for name in names]
# print(names)
# names=['egon','alex_sb','wupeiqi','yuanhao']
#
# nums=[len(name) for name in names if not name.endswith('sb')]
# print(nums)
#字典生成式
# s1='hello'
# l1=[1,2,3,4,5]
# res=zip(s1,l1)
# print(res)
# print(list(res))
# keys=['name','age','sex']
# values=['egon',18,'male']
# res=zip(keys,values)
# print(list(res))
# print(list(res))
# d={}
# for k,v in zip(keys,values):
# d[k]=v
# print(d)
# keys=['name','age','sex']
# values=['egon',18,'male']
# d={k:v for k,v in zip(keys,values)}
# print(d)
info={'name': 'egon', 'age': 18, 'sex': 'male'}
keys=info.keys()
# print(keys)
# iter_keys=keys.__iter__()
# values=info.values()
# print(values)
函数递归
1 什么是函数递归
函数递归调用(是一种特殊的嵌套调用):在调用一个函数的过程中,又直接或间接地调用了该函数本身
递归必须要有两个明确的阶段:
递推:一层一层递归调用下去,强调每进入下一层递归问题的规模都必须有所减少
回溯:递归必须要有一个明确的结束条件,在满足该条件时结束递推
开始一层一层回溯
递归的精髓在于通过不断地重复逼近一个最终的结果
2、为什么要用函数递归
3、如何用
'''
# import sys
# print(sys.getrecursionlimit())
# sys.setrecursionlimit(3000)
# def foo(n):
# print('from foo',n)
# foo(n+1)
# foo(0)
# def bar():
# print('from bar')
# foo()
#
# def foo():
# print('from foo')
# bar()
# foo()
# age(5) = age(4) + 2
# age(4) = age(3) + 2
# age(3) = age(2) + 2
# age(2) = age(1) + 2
# age(1) = 26
# age(n) = age(n-1) + 2 #n > 1
# age(1) = 26 #n = 1
# def age(n):
# if n == 1:
# return 26
# return age(n-1) + 2
#
# print(age(5))
# l=[1,[2,[3,[4,[5,[6,[7,[8,[9,]]]]]]]]]
#
# def tell(l):
# for item in l:
# if type(item) is list:
# #继续进入下一层递归
# tell(item)
# else:
# print(item)
#
# tell(l)
# 有一个从小到大排列的整型数字列表
# nums=[1,3,7,11,22,34,55,78,111,115,137,149,246,371]
# 10 in nums
# for item in nums:
# if item == 10:
# print('find it')
# break
# else:
# print('not exists')
nums=[1,3,7,11,22,34,55,78,111,115,137,149,246,371]
def search(search_num,nums):
print(nums)
if len(nums) == 0:
print('not exists')
return
mid_index=len(nums) // 2
if search_num > nums[mid_index]:
# in the right
nums=nums[mid_index+1:]
search(search_num,nums)
elif search_num < nums[mid_index]:
# in the left
nums=nums[:mid_index]
search(search_num,nums)
else:
print('find it')
匿名函数
# 有名函数:基于函数名重复使用
# def func():
# print('from func')
# func()
# func()
# func()
# 匿名函数:没有绑定名字的下场是用一次就回收了
# def func(x,y): #func=函数的内存地址
# return x + y
# res=(lambda x,y:x+y)(1,2)
# print(res)
# f=lambda x,y:x+y
# print(f)
# print(f(1,2))
#max min map filter sorted
salaries={
'egon':3000,
'alex':100000000,
'wupeiqi':10000,
'yuanhao':2000
}
# max的工作原理
#1 首先将可迭代对象变成迭代器对象
#2 res=next(可迭代器对象),将res当作参数传给key指定的函数,然后将该函数的返回值当作判断依据
# def func(k):
# return salaries[k]
#
# print(max(salaries,key=func)) #next(iter_s)
#'egon', v1=func('egon')
#'alex', v2=func('alex')
#'wupeiqi', v3=func('wupeiqi')
#'yuanhao', v4=func('yuanhao')
# salaries={
# 'egon':3000,
# 'alex':100000000,
# 'wupeiqi':10000,
# 'yuanhao':2000
# }
# print(max(salaries,key=lambda k:salaries[k])) #next(iter_s)
# print(min(salaries,key=lambda k:salaries[k])) #next(iter_s)
# l=[10,1,3,-9,22]
# l1=sorted(l,reverse=False)
# print(l1)
# l2=sorted(l,reverse=True)
# print(l2)
# salaries={
# 'egon':3000,
# 'alex':100000000,
# 'wupeiqi':10000,
# 'yuanhao':2000
# }
#
# print(sorted(salaries,key=lambda k:salaries[k],reverse=True))
names=['张明言','刘华强','苍井空','alex']
# map的工作原理
#1 首先将可迭代对象变成迭代器对象
#2 res=next(可迭代器对象),将res当作参数传给第一个参数指定的函数,然后将该函数的返回值当作map的结果之一
# aaa=map(lambda x:x+"_SB",names)
# print(aaa)
# print(list(aaa))
# print([name+"_SB" for name in names])
# filter的工作原理
#1 首先将可迭代对象变成迭代器对象
#2 res=next(可迭代器对象),将res当作参数传给第一个参数指定的函数,然后filter会判断函数的返回值的真假,如果为真则留下res
names=['alexSB','egon','wxxSB','OLDBOYSB']
# print([name for name in names if name.endswith('SB')])
aaa=filter(lambda x:x.endswith('SB'),names)
print(aaa)
print(list(aaa))
内置方法
abs() 求一个数字的最大值
bytes() 将一个字符串转换成一个bytes类型
bool()给出一个数据的布尔值
min()求出最小的值参数必须是可迭代对象 其中可跟lambda匿名函数的参数
max()求出最大的值参数必须是可迭代对象 其中可跟lambda匿名函数的参数
sum()求出总和参数必须是可迭代对象 其中可跟lambda匿名函数的参数
zip()将两个可迭代的数据每一次next取出一个数据将两者拼接成一个个的小元组
chr()将一个Ascll码转换成为一个对应的字符
ord()chr的反向操作
otc()讲一个十进制数字转换成八进制数字
bin()将一个十进制数字转换成二进制数字
hex() 讲一个十进制数字转换成十六进制数字
int()将一个字符串转换成一个十进制数字 或者将一个二进制八进制十六进制字符串 转换成十进制数字可以,通过int(‘101010101’,2)其中2代表字符串代表的是一个二进制字符数字,
list()讲一个可迭代对象里面的值一个个取出生成一个列表
__import__()与import不同的是该方法可以将字符串代表的模块名导入程序例如 x = __import('time')
eval()可以将一个字符串中的列表字典等数据提取出来
open()用于建立一个文件的读取管道
dir()获取模块中的方法名
help()获取函数中的注释
type()查看数据类型