1.名称空间 python有三种名称空间 内置名称空间: 随着python解释器的启动而产生 print(sum) print(max) 全局名称空间: 文件的执行会产生全局名称空间,指的是文件级别的定义名字都会放入该空间 x = 11 if x == 11: print(x) 局部名称空间: 调用函数时会产生局部名称空间,只在函数调用时临时绑定,调用结束时解绑 x = 1000 def foo(): x = 1 print(x) foo() print(x) 作用域: 1.全局作用域: 内置名称空间,全局名称空间,全局有效,在任何位置都能被访问到, 除非del删除,否则存活到文件结束。 2.局部作用域: 局部名称空间,局部有效,只能在局部范围调用,调用结束失效。 名字的查找顺序: 局部名称空间-->全局名称空间-->内置名称空间 x = 1000 def func(): x = 2 print(locals()) #locals()查看局部作用域内的名字 print(globals()) #globals()查看全局作用域内的名字 2.函数对象 1.可以被引用 2.可以当作参数传递 3.返回值可以是函数 4.可以当作容器类型的元素 例子: def foo(): print("from foo") func = foo print(foo) print(func) foo() func() def foo(): print("from foo") def bar(func): print(func) func() bar(foo) def foo(): print("from foo") dic = {‘func‘: foo} print(dic[‘func‘]) dic[‘func‘]() 3.闭包函数 闭包: 1.定义在内部函数 2.包含对外部作用域而非全局作用域的引用 该内部函数就称作闭包函数 例子: def f1(): x = 1 def f2(): #f2称作闭包函数 print(x) return f2 f = f1() print(f) #打印f2函数的内存地址 f() #打印1 例子: from urllib.request import urlopen def index(url): def get(): return urlopen(url).read() return get oldboy = index(‘http://www.baidu.com‘) print(oldboy().decode(‘utf-8‘)) print(oldboy.__closure__[0].cell_contents) #打印外部引用而非全局引用对象 4.装饰器 修饰其他对象的工具,修饰添加功能,工具指的是函数。 装饰器本身是任何可调用对象,被装饰的对象也可以是任何可调用的对象。 为什么要用装饰器? 开放封闭原则,对修改是封闭的,对扩展是开放的。 装饰器就是为了在不修改被装饰对象源代码以及调用方式的前提下,为其添加新功能 装饰器相当于闭包的实现 例子: 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 {0}".format(stop_time - start_time)) return wrapper @timmer #相当于index = timmer(index) def index(): time.sleep(3) print("welcome to index") return 1 index() #其实相当于执行了timmer(index) 例子: 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 {0}".format(stop_time - start_time)) return wrapper def index(): time.sleep(3) print("welcome to index") f = timmer(index) print(f) f() #f()<=====>wrapper() 认证用户登录 login_user = {‘user‘: None, ‘status‘: False} def auth(func): def wrapper(*args, **kwargs): if login_user[‘user‘] and login_user[‘status‘]: res = func(*args, **kwargs) return res else: name = input("请输入姓名:") passwd = input("请输入密码:") if name == "hyh" and passwd == "123": login_user[‘user‘] = "hyh" login_user[‘status‘] = True print("\033[45mlogin successful\033[0m") res = func(*args, **kwargs) return res else: print("\033[45mlogin err\033[0m") return wrapper @auth def index(): print("welcome to index page") @auth def home(name): print("%s welcome to home page" % (name)) index() home("hyh") 5.迭代器 迭代器的概念: 重复上一次迭代的结果为下一次迭代的初始值,重复的过程称为迭代, 每次重复即一次迭代 为什么要有迭代器? 对于没有索引的数据类型,必须提供一种不依赖索引的迭代方式 可迭代对象: 内置__iter__方法的都是可迭代对象 [1,2].__iter__() ‘hello‘.__iter__() (1,2).__iter__() {"a":1, "b": 2}.__iter__() {1,2,3}.__iter__() 迭代器: 执行__iter__()方法,得到的结果就是迭代器,迭代器有__next__()方法 i = [1,2,3].__iter__() print(i.__next__()) #打印1 print(i.__next__()) #打印2 print(i.__next__()) #打印3 print(i.__next__()) #抛出异常 i__iter__() <==>iter(i) i__next__() <==>next(i) 如何判断一个对象是可迭代对象,还是迭代器对象 from collections import Iterable, Iterator print(isinstance(‘abc‘,Iterable)) print(isinstance([],Iterable)) print(isinstance((),Iterable)) print(isinstance({‘a‘:1},Iterable)) print(isinstance({1,2},Iterable)) f=open(‘a.txt‘,‘w‘) f.__iter__() print(isinstance(f,Iterable)) #只有文件是迭代器对象 可迭代对象:只有__iter__方法,执行该方法得到的迭代器对象 迭代协议: 对象有__next__ 对象有__iter__,对于迭代器对象来说,执行__iter__方法,得到的结果仍然是它本身 迭代器的优点和缺点 优点: 1.提供了一种不依赖下标的迭代方式 2.就跌迭代器本身来说,更节省内存 缺点: 1. 无法获取迭代器对象的长度 2. 不如序列类型取值灵活,是一次性的,只能往后取值,不能往前退
时间: 2024-10-27 15:47:55