函数对象
函数是第一类对象,即函数可以当作数据传递。具体用法分成以下四类:
1. 可以被引用
1 def foo(): 2 print('from foo') 3 func=foo 4 print(foo) ---> <function foo at 0x00386C48> --> foo函数在内存中地址 5 print(func) ---> <function foo at 0x00386C48> 6 foo() ---> from foo 7 func() ---> from foo
2. 可以当作参数传递
1 def foo(): 2 print('from foo') 3 def bar(func): 4 print(func) ---> <function foo at 0x00306DF8> --> func函数在内存中地址 5 func() ---> from foo 6 bar(foo)
3. 返回值可以是函数
1 def foo(): 2 print('from foo') 3 def bar(func): 4 return func ---> 作为返回值 5 f=bar(foo) 6 print(f) ---> <function foo at 0x002E6DF8> 7 f() ---> from foo
4. 可以当作容器类型的元素
1 def foo(): 2 print('from foo') 3 dic={'func':foo} ---> 在字典中作为键值存在 4 print(dic['func']) ---> <function foo at 0x00556C48> 5 dic['func']() ---> from foo
5. 应用实例
SQL语句操作判定
1 def select(sql): 2 print('========>select') 3 def insert(sql): 4 print('========>add') 5 def delete(sql): 6 print('========>delete') 7 def update(sql): 8 print('========>update') 9 func_dic={'select':select, 'update':update, 'insert':insert, 'delete':delete} 10 def main(): 11 while True: 12 sql = input('>>: ').strip() 13 if not sql:continue 14 l = sql.split() 15 cmd=l[0] ---> 读取SQL语句首单词 16 if cmd in func_dic: 17 func_dic[cmd](l) ---> 当作容器类型的元素 18 main()
简易姓名查询数据库
1 def init(database): 2 database['first'] = {'Jia':{'Jia Xiao Liang'}} 3 database['middle'] = {'Xiao':{'Jia Xiao Liang'}} 4 database['last'] = {'Liang':{'Jia Xiao Liang'}} 5 6 def lookup(database, lable, name): 7 return database[lable].get(name) 8 9 def store(database, full_name): 10 names = full_name.split(' ') 11 if len(names) == 2: 12 names.insert(1,' ') 13 lables = 'first','middle','last' 14 for lable, name in zip(lables,names): 15 people = lookup(database, lable, name) 16 print(people) 17 if people: 18 database[lable][name].add(full_name) 19 else: 20 database[lable][name] = {full_name} 21 22 if __name__ == '__main__': 23 storage = dict() 24 print(type(storage)) 25 init(storage) 26 while True: 27 print('Store:',storage) 28 name = input('>>>').strip() 29 store(storage,name)
函数嵌套
1. 函数的嵌套调用
1 def max2(x,y): 2 return x if x > y else y 3 def max4(a,b,c,d): 4 res1=max2(a,b) 5 res2=max2(res1,c) 6 res3=max2(res2,d) 7 return res3 8 print(max4(10,99,31,22))
2. 函数的嵌套定义
1 def f1(): 2 def f2(): 3 print('from f2') 4 def f3(): 5 print('from f3') 6 f3() 7 f2() 8 f1()
命名空间
1. 三种命名空间
1. 内置名称空间:随着Python解释器的启动而产生
1 print(sum) ---> <built-in function sum> 2 print(max) ---> <built-in function sum> 3 print(min) ---> <built-in function sum> 4 import builtins 5 for i in dir(builtins): 6 print(i) ---> 打印出所有内置函数
2. 全局名称空间:文件的执行会产生全局名称空间,指的是文件级别定义的名字都会放入该空间
1 x=1 2 def func(): 3 money=2000 ---> 局部名称空间中的变量 4 x=2 5 print('func x = ', x) 6 print(x) 7 print(func) 8 func() 9 # print(money) ---> 报错,money是函数中定义的变量,属于局部名称空间
3. 局部名称空间:函数被调用时会产生局部名称空间,只是在函数调用时临时绑定,调用结束后绑定自动解除(可参考上段代码)
作用域
1. 全局作用域:
a.)内置命名空间,全局命名空间
b.)查看全局作用域内的名字方法globals()
c.)全局有效,在任何位置都能访问到,除非del删除,否则会一直存活到文件执行完毕
2. 局部作用域
a.)局部命名空间
b.)查看局部作用域内的名字方法locals()
c.)局部有效,只能在局部范围内调用,只在函数被调用时有效,调用结束后自动失效
变量名字的查找顺序:局部命名空间 ---> 全局命名空间 ---> 内置命名空间
1 x=1 ---> 属于全局作用域,内部函数也可以调用 2 def func(): 3 x=2 ---> 函数内变量属于局部作用域,函数外部不可调用 4 print('local.x = ',x) ---> x = 2 5 sum=123123 6 print('local.sum = ',sum) ---> sum = 123123 7 print(globals()) ---> {'__doc__': None, '__cached__': None, '__package__': None, 'func': <function func at 0x00456C48>, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00415AB0>, '__spec__': None, '__file__': 'C:/Users/ajiax/PycharmProjects/Python17/Day04/fortest.py', '__builtins__': <module 'builtins' (built-in)>, 'x': 1, '__name__': '__main__'} 8 print(locals()) ---> {'x': 2, 'sum': 123123} 9 print(globals() is locals()) ---> False 10 func() 11 print('global.x = ',x) 12 print(globals()) ---> {'__doc__': None, '__cached__': None, '__package__': None, 'func': <function func at 0x00456C48>, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00415AB0>, '__spec__': None, '__file__': 'C:/Users/ajiax/PycharmProjects/Python17/Day04/fortest.py', '__builtins__': <module 'builtins' (built-in)>, 'x': 1, '__name__': '__main__'} 13 print(locals()) ---> {'__doc__': None, '__cached__': None, '__package__': None, 'func': <function func at 0x00456C48>, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00415AB0>, '__spec__': None, '__file__': 'C:/Users/ajiax/PycharmProjects/Python17/Day04/fortest.py', '__builtins__': <module 'builtins' (built-in)>, 'x': 1, '__name__': '__main__'} 14 print(globals() is locals()) ---> True
闭包函数
定义:1. 定义在函数内部
2. 包含对外部作用域而非全局作用域的引用 ,形象点可以说闭包函数是由外部作用域而非全局作用域包裹在里面的函数,它可以使用其外部作用域的变量,但是无法使用更外一层即全局作用域的变量
下划线部分可以理解为一个有外部作用域形成的包裹,并将函数f2()包裹在里面,从而形成闭包函数
1 x = 11 ---> 全局作用域变量,闭包函数无法调用 2 def f1(): 3 x = 1 ---> 外部作用域的变量,闭包函数可以调用 4 def f2(): ---> 闭包函数 5 print(x) 6 return f2 7 f=f1() 8 print(f) ---> <function f1.<locals>.f2 at 0x002D6C48> 9 f() ---> 1 ---> 很明显结果是由闭包函数f2()调用其外部作用域的变量x的结果,而非全局变量的x
闭包函数应用
惰性计算,爬取网页内容
1 from urllib.request import urlopen 2 3 def index(url): 4 def get(): 5 return urlopen(url).read().decode('utf-8') ---> 将从网页上爬取下来的内容由字节形式转化为urf-8 6 return get 7 web = index(input('>>>')) ---> 输入需要爬取的网页地址 8 print(web()) ---> 打印爬取到的网页内容
print(web.__closure__[0].cell_contents) ---> 将闭包函数引用的外部命名空间的变量显示出来,多个变量以元组的形式存在
1 x=11 2 y=22 3 def f1(): 4 x=1 5 y=2 6 def f2(): 7 print('x = %s and y = %s' % (x,y)) 8 return f2 9 f=f1() 10 f() ---> x = 1 and y = 2 11 print(f.__closure__[0].cell_contents,f.__closure__[1].cell_contents) ---> 1 2 12 print(f.__closure__) ---> (<cell at 0x00245AF0: int object at 0x66115910>, <cell at 0x00245B50: int object at 0x66115920>)
装饰器
定义:修饰其他函数的工具,修饰添加功能,工具指的是函数,装饰器本身可以是任何可调用对象,被装饰的对象也可以是任意可调用的对象
为什么使用装饰器:
1. 开放封闭原则:对修改是封闭的,对扩展是开放的
2. 装饰器是为了在不修改被装饰对象的源代码及其调用方式的前提下,为其添加更多的功能
无参数装饰器的简单实现
1 import time 2 def timmer(func): 3 def wrapper(): 4 start_time=time.time() 5 func() 6 stop_time=time.time() 7 print('run time is %s' %(stop_time-start_time)) 8 return wrapper 9 @timmer #index=timmer(index)将他正下方的函数的函数名作为参数传给timer函数,固定只有一个参数,让后再讲timer函数的返回值再重新绑定给index函数 10 def index(): 11 time.sleep(3) 12 print('welcome to index') 13 index() #实际上已经是wrapper() ---> 已经不是原来的index()函数,指向的内存地址为wrapper函数的内存地址
多参数装饰器的简单实现
1 import time 2 def timer(func): 3 def wrapper(*args,**kwargs): 4 start_time=time.time() 5 res = func(*args,**kwargs) 6 stop_time=time.time() 7 print('run time is %s' %(stop_time-start_time)) 8 return res 9 return wrapper 10 @timer #index=timmer(index)将他正下方的函数作为参数传入 11 def index(name,age): 12 time.sleep(3) 13 print('welcome to index') 14 return name,age 15 res = index('Albert',30) #wrapper() 16 print(res)
多层装饰器嵌套
1 import time 2 def timer(func): 3 def wrapper(*args,**kwargs): 4 print('====>timmer.wrapper') 5 start_time=time.time() 6 res=func(*args,**kwargs) #auth_wrapper 7 stop_time=time.time() 8 print('run time is %s' %(stop_time-start_time)) 9 return res 10 return wrapper 11 12 login_user = {'name':None,'status':False} 13 def out_auth(driver = 'file'): 14 def auth(func): 15 def wrapper(*args,**kwargs): 16 print('====>auth.wrapper') 17 if driver == 'file': 18 if login_user['name'] and login_user['status']: 19 res = func(*args,**kwargs) 20 return res 21 else: 22 name = input('>>>') 23 psw = input('>>>') 24 if name == 'Albert' and psw =='123': 25 login_user['name'] = 'Albert' 26 login_user['status'] = True 27 print('