01 定义函数
# 01 语法:
# def 函数名(参数1,参数2, ...):
# """
# 文档注释
# """
# 代码1
# 代码2
# 代码3
# ....
# return 返回值
#
# 02 定义函数时:只检测语法,不执行代码
# 03 定义函数的三种形式
# 定义函数的形式一:无参函数
# def foo():
# print('from fooo')
#
# foo()
# def print_msg():
# print('****************************************')
# print('============welcome to ATM==============')
# print('****************************************')
#
# def pay():
# print('from pay')
# def check():
# print('from check')
# def transfer():
# print('from transfer')
#
# def run():
# print("""
# 1 支付
# 2 查询
# 3 转账
# """)
# choice=input('>>:').strip()
# if choice == '1':
# pay()
# elif choice == '2':
# check()
# elif choice == '3':
# transfer()
#
# run()
# 定义函数的形式二:有参函数
# def bar(x,y):
# print(x,y)
#
# bar(1,2)
#
# def max(x,y):
# if x > y:
# print(x)
# else:
# print(y)
#
# max(20,30)
# 定义函数的形式三:空函数
# def foo(x,y):
# pass
# def get():
# pass
# def put():
# pass
# def auth():
# pass
# def ls():
# pass
# def cd():
# pass
02 调用函数
# 调用形式一:语句形式
# def foo():
# print('from foo')
#
# foo()
# 调用形式二:表达式形式
def max(x,y):
if x > y:
return x
else:
return y
# salary = max(3000,2000)
# annual_salary=salary * 12
# print(annual_salary)
# annual_salary=max(3000,2000) * 12
# print(annual_salary)
# 调用形式三:当做参数传给另外一个函数
def max(x,y):
if x > y:
return x
else:
return y
#3,2,1
res=max(max(3,2),1)
print(res)
03 函数的返回值
# 1、return
# 特点:return 是函数结束的标志,函数内可以有多个return
# 但是只要执行一个,函数就立即结束,并且把return后的值当做本次调用的结果返回
# def foo():
# print('first')
# return 1
# print('second')
# return 2
# print('third')
# return 3
#
# res=foo()
# print(res)
# 2、返回值注意:
# 2.1返回值没有类型限制
# def bar():
# return {'x':1}
#
# print(bar())
# 2.2返回值没有个数限制,可以用逗号分开多个值,一次返回
# def bar():
# return(1,'wxx',{'x':1})
#
# x,y,z=bar()
# print(x,y,z)
# 2.3 可以没有return,默认返回none
# def bar():
# pass
#
# res=bar()
# print(res)
04 函数参数
# 一:函数的参数分为两大类:形参与实参
# 形参:指的是在定义函数时括号的参数,形参即变量名
# def foo(x,y):
# print(x,y)
# 在调用函数时,实参的值会传给形参,这就是一个赋值操作
# 二:函数参数
# 1、位置参数:
# 1.1在定义函数时,按照从左到右的顺序依次定义的参数,称为位置形参
# 特性:位置形参必须被传值,多一个不行少一个也不行
# def foo(x,y,z):
# print(x,y,z)
# foo(1,2,3)
# foo(1,2) #报错TypeError: foo() missing 1 required positional argument: 'z'
# foo(1,2,3,4) #TypeError: foo() takes 3 positional arguments but 4 were given
# 1.2 在调用函数时,按照从左到右的顺序依次传入的值,称为位置实参
# 特点:与形参一一对应
# foo(1,2,3) #1 2 3
# foo(3,2,1) #3 2 1
# 2、关键字实参:
# 在调用函数时,按照key=value的形式定义的实参,称为关键实参
# 特点:可以完全打乱顺序,但仍然能指名道姓地为指定的参数传值
# def foo(x,y,z):
# print(x,y,z)
# foo(1,2,3) #1 2 3
# foo(z=3,x=1,y=5) #1 5 3
#位置实参与关键字实参可以混合使用
# 1、位置参数一定放到关键字参数的前面
# 2、同一个形参只能被赋值一次
# foo(1,2,z=3) #1 2 3
# foo(1,y=2,z=3) #1 2 3
# foo(1,z=3,y=2) #1 2 3
# foo(z=3,y=2,1) #报错,位置参数一定放到关键字参数的前面 SyntaxError: positional argument follows keyword argument
# foo(1,z=3,y=2) #1 2 3
# foo(1,z=3,y=2,z=30) #报错:同一个形参只能被赋值一次 SyntaxError: keyword argument repeated
# foo(1,x=3,y=2) #报错:位置参数一定放到关键字参数的前面 x等于是重复赋值了
# 3、默认参数:在定义函数时,就已经被赋值的参数,称为默认形参
# 注意
# 3.1在定义阶段就已经被赋值,意味着在调用阶段就可以不用传值
# def foo(x,y=10):
# print(x,y)
# foo(1) #1 10
# foo(1,3) #1 3
# foo(y=4,x=1) #1 4
# 3.2默认参数必须跟在位置形参的后面
# def foo(y=1,x):
# pass #报错,因为默认参数放在了前面SyntaxError: non-default argument follows default argument
# 3.3默认参数的值只在定义阶段被赋值一次就固定死了,定义之后改变没有影响
# m=10
# def func(x,y=m):
# print(x)
# print(y)
#
# m=11111
# func(1) #1
# #10
# 3.4默认参数的值应该设置成不可变类型
# def func(name,hobby,l=[]):
# l.append(hobby)
# print(name,l)
# func('egon','read') #egon ['read']
# func('alex','play') #alex ['read','play']
# func('wxx','eat') #wxx ['eat']
# def func(name,hobby,l=None):
# if l is None:
# l=[]
# l.append(hobby)
# print(name,l)
# func('egon','read',) #egon ['read']
# func('alex','play') #alex ['play']
# func('wxx','eat') #wxx ['eat']
# func('egon','read',['music','movie']) #egon ['music','movie','read']
# 位置形参与默认参数的应用:
# 1 大多数场景值都固定不变则需要定义成默认参数
# 2 大多数场景值都需要改变则需要定义成位置形参
# def register(name,password,gender='male'):
# print(name)
# print(password)
# print(gender)
#
# register('alex', '123') #alex
# #123
# #male
#
# register('wxx','wxx123') #wxx
# #wxx123
# #male
#
# register('lxx', 'lxx123', 'female') #lxx
# #lxx123
# #female
# 4 可变长参数 :
# 指的是在调用函数时,传入的实参个数可以不固定
# 而实参无非两种形式:1、位置实参 2、关键字实参
# 所以对应的,形参也必须对应两种解决方案,专门用于接收溢出位置实参和溢出的关键字实参
# *:接收溢出位置实参,存成元组形式,然后赋值给*后面跟的那个变量名
# 用法1:在形参中用*
# def foo(x,y,*z): #*z的形式是元组z=(3,4,5)
# print(x,y)
# print(z)
# foo(1,2,3,4,5) #1 2
#(3,4,5)
# foo(1,2,3,4,5,6,7,8,9) #1 2
#(3,4,5,6,7,8,9)
# 用法2:在实参中用*
# def foo(x,y,*z):
# print(x,y)
# print(z)
# foo(1,2,*(3,4,5,6,7,8,9)) #*后面全打散成未知参数 foo(1,2,3,4,5,6,7,8,9)
#1 2
#(3,4,5,6,7,8,9)
# foo(1,2,*[3,4,5]) #同上,打散成位置参数 foo(1,2,3,4,5)
#1 2
#(3,4,5)
# foo(1,2,*'abc') #相当于是个for循环foo(1,2,'a','b','c')
#1 2
#('a','b','c')
# def foo(x,y):
# print(x,y)
# foo(1,*(2,3,4,5)) #foo(1,2,3,4,5)会报错,传入的实参值超过TypeError: foo() takes 2 positional arguments but 5 were given
# foo(1,(2,3,4,5)) #1 (2,3,4,5)
# foo(*(1,2,3,4,5)) #foo(1,2,3,4,5)报错,传入的实参值超过TypeError: foo() takes 2 positional arguments but 5 were given
# def my_sum(*args):
# res=0
# for n in args:
# res+=n
# return res
#
#
# res1=my_sum(1,2,3) #6
# res2=my_sum(1,2,3,4) #10
# res3=my_sum(1,2,3,4,5) #15
# print(res1)
# print(res2)
# print(res3)
# **:接收溢出关键字实参,存成字典形式,然后赋值给**后面跟的那个变量名
# 用法1:在形参中用**
# def foo(x,y,**z): #**z中的z是字典形式,z={‘c’:4,‘b’:3,‘a’:1}
# print(x)
# print(y)
# print(z)
# foo(1,{'a':2,'c':4,'b':10,'y':999}) #1
#{'a':2,'c':4,'b':10,'y':999}
#{}
# foo(1,**{'a':2,'c':4,'b':10,'y':999}) #foo(1,y=999,b=10,c=4,a=2)
#1
#999
#{'b':10,'c':4,'a':2,} 运行结果的顺序不一样为什么???{'c': 4, 'b': 10, 'a': 2}
# foo(1,**{'a':2,'c':3}) #foo(1,a=2,c=3)报错,缺少实参y。TypeError: foo() missing 1 required positional argument: 'y'
# def foo(x,y,z):
# print(x)
# print(y)
# print(z)
# d={'x':1,'y':2,'z':3}
# foo(d['x'],d['y'],d['z']) #foo(1,2,3)
#1
#2
#3
# foo(**d) #foo(x=1,y=2,z=3)
# d={'x':1,'y':2}
# foo(**d) #foo(x=1,y=2) 缺少参数,报错。TypeError: foo() missing 1 required positional argument: 'z'
# def foo(*args,**kwargs): #x=(1,2,3,4,5)
# print(args)
# print(kwargs)
# foo(1,2,3,4,5,a=1,b=2,c=3,d=4) #*是元组(1,2,3,4,5)
#**是字典{'a':1,'b':2,'c':3,'d':4}
def index(name,gender):
print('welcome %s. gender is %s' %(name,gender))
def wrapper(*args,**kwargs):
index(*args,**kwargs)
# wrapper('alex', 'male') #args=('alex','male') welcome alex. gender is male
# wrapper(gender='male',name='alex') #kwargs={'gender':'male','name':'alex'} welcome alex. gender is male
wrapper('alex',gender='male') #args=('alex'),kwargs={'gender':'male'} welcome alex. gender is male
05 函数嵌套
# 1、函数的嵌套调用
# def max2(x,y):
# if x > y:
# return x
# else:
# return y
#
# def max4(x,y,z,m):
# res1=max2(x,y)
# res2=max2(res1,z)
# res3=max2(res2,m)
# return res3
# print(max4(2,3,4,5))
# 2 函数的嵌套定义
def f1():
print('from f1')
def f2():
print('from f2')
print(f2)
def f3():
print('from f3')
f3()
f2()
f1()
'''
from f1
from f2
f2内存地址:<function f1.<locals>.f2 at 0xb7097cd4>
from f3
'''
06 名称空间与作用域
'''
1、名称空间Namespaces:存放名字与值绑定关系的地方
2、名称空间的分类
内置名称空间:
存放Python解释器自带名字,比如内置的函数名:len,max,sum
创建:随着Python解释器启动而创建
销毁:随着Python解释器关闭而销毁
全局名称空间
存放文件级别的名字,比如x,f1,z
x=1
def f1():
y=2
if x == 1;
z=3
创建:文件开始执行时立即创建
销毁:文件开始执行完毕时则销毁
局部名称空间
存放函数内的名字,强调函数的参数也属于局部的
创建:函数执行时才临时创建
销毁:函数执行完毕则立即销毁
def f1();
x=1
y=2
z=3
f1()
3、名称空间的加载顺序
内置名称空间---》全局名称空间---》局部名称空间
加载的目的是为了把名字存起来,然而存起的目的就是为了取
但凡查找一个名字一定会从三种名称空间之一找到,不然报错
4、名称空间的查找名字顺序
局部名称空间---》全局名称空间---》内置名称空间
'''
# len=10
# def f1():
# # len=3 #len=3则从内置名称空间内找结果为3,注释则从全局名称空间找为10
# print(len)
#
# f1()
# len=1
# def f1():
# # len=10
# def f2():
# # len=100
# def f3():
# # len=1000
# print(len)
# f3()
# f2()
#
# # len=11111111
#
# f1()
'''
len=10,100,1000均不注释,则取局部名称空间f3中1000
注释len=1000,取局部名称空间f2中100,注释len=100,1000,取f1中10
len=10,100,1000均注释,则取全局变量11111111
len=11111111注释,则取1
'''
#名字的查找关系是在函数定义阶段就已经固定死的,与调用位置无关
# x=100
# def f1():
# x=10
# print(x)
#
# def f2():
# x=11111
# f1()
# f2()
#
# x=1000
# 结果为10
# 作用域:域=范围
# 全局范围:内置名称空间中的名字,全局名称空间中的名字
# 特点:全局有效,全局存活
# 局部范围:局部名称空间中的名字
# 特点:局部有效,临时存活
# 定义在全局作用域的名字称为全局变量
# 定义在局部作用域的名字称为局部变量
# x=1
# def f1():
# print(len)
# print(x)
# def f2():
# print(len)
# print(x)
# def f3():
# def f4():
# print(len)
# print(x)
# f4()
# x=111
# print(globals()) #查看全局作用域中的名字,包含内置的和文件级别的
#{'__spec__': None, 'f1': <function f1 at 0xb70a0d64>, '__cached__': None, '__name__': '__main__', 'x': 111, '__builtins__': <module 'builtins' (built-in)>, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0xb70d22ac>, '__file__': '/home/m/oldboy/hello world.py', '__package__': None, 'f2': <function f2 at 0xb70a0c8c>, '__doc__': None, 'f3': <function f3 at 0xb711a734>}
# print(locals() is globals()) #locals局部
# def f1():
# y=2
# z=3
# print(locals())
# f1() #{'z': 3, 'y': 2}
# global与nolocal
# l=[]
# def foo():
# l.append(2)
#
# foo()
# print(l) #2,当全局变量是可变类型的,局部变量可改变全局变量的值
# x=10
# def foo():
# x=100
# print(x)
#
# foo()
# print(x) #10,当全局变量为不可变类型,局部变量不能改变全局变量的值
# x=10
# def foo():
# global x
# x=100
#
# foo()
# print(x) #100,(global x)定义x为全局变量
x=1 #nonlocal不会在全局变量内进行寻找,f1中没有找到x,即报错
def f1():
#x=10 #x=10也注释状态下,报错SyntaxError: no binding for nonlocal 'x' found
def f2():
def f3():
nonlocal x #nonlocal会从当前函数外一层开始查找一直到最外层的函数,如果还没有则报错
#x=11 #x=11注释状态,nonlocal则外层找到f1中的x=10
f3()
f2()
print(x)
f1()
07 函数对象
# 函数对象:函数可以当变量去处理
# 函数可以:
# 1、被赋值
# def foo():
# print('from foo')
#
# f=foo
# print(f) #内存地址 <function foo at 0xb70df734>
# f() #from foo
# 2、当做参数传给一个函数
# def foo():
# print('from foo')
#
# def bar(func): #func=foo
# print(func)
# func()
#
# bar(foo)
# '''
# 内存地址<function foo at 0xb7007d64>
# from foo
# '''
# 3、当做函数的返回值
# def foo():
# print('from foo')
#
# def bar(func): #func=foo
# return func #return foo
#
# f=bar(foo) #from foo,f=foo
# print(f) #内存地址<function foo at 0xb7095d64>
# 4、当做容器类型元素
# def foo():
# print('from foo')
#
# l=[foo]
# print(l) #内存地址[<function foo at 0xb70a5734>]
#
# l[0]() #l[0]()=foo(), from foo
# d={'foo':foo}
#
# d['foo']() #d['foo']=foo, d['foo']()=foo(),from foo
def get():
print('from get')
def put():
print('from put')
def ls():
print('from ls')
def login():
print('from login')
def cd():
print('from cd')
func_dic={
"1":[get,'下载'],
"2":[put,'上传'],
"3":[ls,'查询'],
"4":[login,'登陆'],
"5":[cd,'切换目录']
}
def run():
while True:
for k in func_dic:
print(k,func_dic[k][1])
choice=input('>>>:').strip()
if choice == 'q':break
if choice in func_dic:
func_dic[choice][0]()
run()
08 闭包函数
'''
闭包函数:函数嵌套+名称空间与作用域+函数对象
什么是闭包函数
1、定义在函数内的函数
2、该函数体代码包含对该函数外层作用域中名字的引用,
强调:函数外层指的不是全局作用域
满足上述两个条件,该内部函数就称之为闭包函数
'''
# def outter():
# x=1
# def inner():
# print(x)
# return inner #利用函数对象的概念,讲一个内部函数返回并在全局中拿到并使用,从而打破了函数的层级限制
#
# f=outter() #f=inner
# print(f) #innner的内存地址<function outter.<locals>.inner at 0xb6fd4b6c>
# #
# # f() #1
#
# def foo():
# x=11111
# print('from foo')
# f()
#
# foo() #from foo
# #1
# 为函数体传值的方式
# 方式一:以参数的形式为函数体传值
import requests #pip3 install requests
#
# def get(url):
# response=requests.get(url)
# if response.status_code == 200: #status_code == 200代表访问成功。
# print(response.text)
#
# get('https://www.baidu.com')
# 方式二:包给函数
def outter(url):
# url='https://www.baidu.com'
def get():
response=requests.get(url)
if response.status_code == 200:
print(response.text)
return get #return了get函数的内存地址
baidu=outter('https://www.baidu.com') #baidu=get
douban=outter('https://www.douban.com')
baidu()
douban()
09 装饰器
'''
一、开放封闭原则
软件一旦上上线之后就应该遵循开放封闭原则
具体是指对修改是封闭的,但对扩展是开放的
二、什么是装饰器
装饰就是修饰,器指的就是工具
装饰器本身可以是任意可调用的对象
被装饰的对象也可以是任意可调用的对象
装饰器---》函数
被装饰的对象---》函数
装饰器是用来为被装饰对象添加新功能的一种工具
必须遵循:
1、不能修改被装饰对象的源代码
2、不能修改被装饰对象的调用方式
'''
import time
def index():
time.sleep(1) #延迟1秒
print('welcome to index')
def outter(func):
def wrapper():
start_time=time.time() #当前时刻
func()
stop_time=time.time()
print('run time is %s' %(stop_time - start_time))
return wrapper
index=outter(index) #index=wrapper
index()
'''
welcome to index
run time is 1.0011980533599854
'''
10 装饰器的修正
# import time
#
# def index():
# time.sleep(1)
# print('welcome to index')
# return 1234
#
# def outter(func):
# def wrapper():
# start_time=time.time()
# res=func()
# stop_time=time.time()
# print('run time is %s' %(stop_time - start_time))
# return res #本行注释则最后 返回值 None
# return wrapper
#
# index=outter(index) #index=wrapper,res=index()
# '''
# welcome to index
# run time is 1.0011405944824219
# '''
#
# res=index() #这里index调用的是wrapper
# print('返回值',res)
# '''
# 返回值 1234
# '''
# import time
#
# def index():
# time.sleep(1)
# print('welcome to index')
# return 1234
#
# def home(name):
# time.sleep(2)
# print('welcome %s to home page' %name)
#
# def outter(func):
#
# def wrapper(*args,**kwargs):
# start_time=time.time()
# res=func(*args,**kwargs)
# stop_time=time.time()
# print('run time is %s' %(stop_time - start_time))
# return res
#
# return wrapper
#
# #修饰home
# home=outter(home) #home=wrapper
#
# home('egon') #wrapper('egon'),res=home('egon')
# '''
# welcome egon to home page
# run time is 2.0017738342285156
# '''
#
# #修饰index
# index=outter(index) #index=wrapper
# index() #res=index() welcome to index
# '''
# welcome to index
# run time is 1.001117467880249
# '''
# 装饰器名:outter
# 被装饰对象:index,home
# 装饰语法糖:
# 在被装饰对象正上方单独一行写@装饰器的名字
import time
def timmer(func):
def wrapper(*args,**kwargs):
start_time=time.time()
res=func(*args,**kwargs)
stop_time=time.time()
print('run time is %s' %(stop_time - start_time))
return res
return wrapper
@timmer #index=timmer(index)
def index():
time.sleep(1)
print('welcome to index')
return 1234
@timmer #home=timmer(home)
def home(name):
time.sleep(2)
print('welcome %s to home page' %name)
index()
home('egon')
'''
welcome to index
run time is 1.0011608600616455
welcome egon to home page
run time is 2.0022692680358887
'''
11 有参装饰器
# import time
# current_user={'login':False}
#
# def outter(func):
# def wrapper(*args,**kwargs):
# if current_user['login']:
# return func(*args,**kwargs)
#
# user=input('username>>:').strip()
# pwd=input('password>>:').strip()
# if user == 'egon' and pwd == '123':
# current_user['login']=True
# return func(*args,**kwargs)
# return wrapper
# @outter #index=outter(index), index=wrapper
# def index(): #index()=wrapper()
# time.sleep(1)
# print('welcome to index')
# return 1234
# @outter #home=outter(home),home=wrapper
# def home(name): #home()=warpper()
# time.sleep(2)
# print('welcome %s to home page' %name)
# index()
# '''
# username>>:egon
# password>>:123
# welcome to index
# '''
# home('egon')
# '''
# username>>:egon
# password>>:123
# welcome egon to home page
# '''
#有参装饰器
import time
current_user={'login':False}
def auth(engine):
def outter(func):
def wrapper(*args,**kwargs):
if current_user['login']:
return func(*args,**kwargs)
user=input('username>>>:'.strip())
pwd=input('password>>>:').strip()
if engine == 'file':
if user == 'egon' and pwd == '123':
current_user['login']=True
return func(*args,**kwargs)
elif engine == 'mysql':
print('基于MySQL数据的认证')
# return func(*args,**kwargs)
elif engine == 'ldap':
print('基于ldap的认证方式')
return func(*args,**kwargs)
return wrapper
return outter
# @auth(engine='mysql') #@outter #index=outter(index) #index=wrapper
# def index():
# time.sleep(1)
# print('welcome to index')
# return 1234
@auth(engine='ldap') #@outter #home=outter(home) #home=wrapper
def home(name):
time.sleep(2)
print('welcome %s to home page' %name)
# index()
'''
username>>>:egon
password>>>:123
基于MySQL数据的认证'
welcome to index
'''
home('egon')
'''
username>>>:egon
password>>>:123
基于ldap的认证方式
welcome egon to home page
'''