- 名称空间与作用域
- 闭包函数
- 装饰器
- 迭代器
- 生成器
- 三元表达式、列表解析、生成器表达式
名称空间与作用域
函数的嵌套调用:在调用一个函数的过程中,又调用了其他函数
def bar():
print('from bar')
def foo():
print('from foo')
bar()
foo()
函数的嵌套定义:在一个函数的内部,又定义了另外一个函数
def f1():
x=1
def f2()
print('from f2')
f2()
f1()
在函数内部定义的变量或者函数只能在内部调用,除非通过return的方式返回在外面调用
名称空间:专门用来存放名字与变量值绑定关系的地方
内置名称空间:python自带的名称空间,在python解释器启动时产生
全局名称空间:在执行文件时产生,存放文件级别定义的名字;不是内置的,也不是函数中定义的名字,就是全局的
局部名称空间:在执行文件的过程中,如果调用了函数,则会产生该函数的局部名称空间,用来存放该函数定义的名字,在函数调用时生效,结束后释放。
加载顺序:内置》全局》局部 查找顺序:局部》全局》内置 从里到外
x=0
def f1():
x=1
def f2():
x=2
def f3():
x=3
print(x)
f3()
f2()
print('f1========',x)
f1()
作用域:作用的范围
全局作用域:可以理解为内置和全局名称空间
局部作用域:可以理解为局部名称空间,临时存活,局部有效
locals()可以查看局部作用域
globals()可以查看全局作用域
global 局部位置设置全局变量;nonlocal 局部设置外层变量
LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> __builtins__
locals 是函数内的名字空间,包括局部变量和形参
enclosing 外部嵌套函数的名字空间(闭包中常见)
globals 全局变量,函数定义所在模块的名字空间
builtins 内置模块的名字空间
优先掌握:作用域关系,在函数定义时就已经固定,与调用位置无关,除非是调用前已经被修改
闭包函数
定义在函数内部的函数,包含对外部作用域名字的引用,而不是对全局作用域名字的引用,那么该内部函数就成为闭包函数
闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域
闭包函数的应用:
惰性计算
装饰器
开放封闭原则:对拓展是开放的,对修改是封闭的
装饰器本身可以是任意调用对象
装饰器遵循的原则:
1、不修改被装饰对象的源代码;2、不修改被调用对象的调用方式
目的:
在遵循原则的前提下为其他函数添加新功能
@装饰器名,必须写在需要被装饰的函数de正上方
装饰器的固定形式
def login(func):
def wrapper(*args,**kwargs):
res=func(*args,**kwargs)
return res
return wrapper
执行login函数,将下方的函数传入auth函数并将结果赋值给函数
import timeView Code
def timmer(func):
def warrper(*args,**kwargs):
start_time=time.time()
res=func(*args,**kwargs)
end_time=time.time()
print(end_time-start_time)
return res
return warrper
@timmer
def get():
url='http://www.baidu.com'
def MyGet():
time.sleep(1)
return requests.get(url).text
return MyGet()
@timmer
def my_print(name):
time.sleep(0.5)
print('print %s'%name)
get()
my_print('Tianle')
编写简单身份验证的装饰器
import timeView Code
current_user={'user':None}
def login(func):
def warrper(*args,**kwargs):
i=0
while i<3:
if current_user['user']:
res = func(*args, **kwargs)
return res
user=input('plz input your name:')
password=input('plz input your password:')
with open('db.txt',encoding='utf-8') as f:
user_dic=eval(f.read())
if user in user_dic and password==user_dic[user]:
print('认证通过')
res=func(*args,**kwargs)
return res
else:
print('用户密码密码错误,请重试')
i+=1
if i==3:
print('失败次数过多')
break
return warrper
@login
def my_print(name):
time.sleep(0.5)
print('print %s'%name)
my_print('Tianle')
@login
def my_print1(name):
time.sleep(0.5)
print('print %s'%name)
my_print1('Lele')
有参装饰器:简单的理解就是闭包函数外面再包一层,包三层就够了
import timeView Code
current_user={'user':None}
def auth(auth_type='file'):
def login(func):
def warrper(*args,**kwargs):
if auth_type=='file':
i=0
while i<3:
if current_user['user']:
res = func(*args, **kwargs)
return res
user=input('plz input your name:')
password=input('plz input your password:')
with open('db.txt',encoding='utf-8') as f:
user_dic=eval(f.read())
if user in user_dic and password==user_dic[user]:
print('认证通过')
res=func(*args,**kwargs)
return res
else:
print('用户密码密码错误,请重试')
i+=1
if i==3:
print('失败次数过多')
break
elif auth_type=='mysql':
print('mysql')
else:
print('auth_type error')
return warrper
return login
@auth()
def my_print(name):
time.sleep(0.5)
print('print %s'%name)
my_print('Tianle')
@auth
def my_print1(name):
time.sleep(0.5)
print('print %s'%name)
my_print1('Lele')
装饰器补充:
1、wraps #在使用装饰器时保留被装饰函数的文档;也就是将被装饰的函数文档传给装饰器
import requestsView Code
from functools import wraps #导入模块
import time
def timmer(func):
@wraps(func)#引用
def warrper(*args,**kwargs):
start_time=time.time()
res=func(*args,**kwargs)
end_time=time.time()
print(end_time-start_time)
return res
return warrper
@timmer
def get():
'''爬虫'''
url='http://www.baidu.com'
def MyGet():
time.sleep(1)
return requests.get(url).text
return MyGet()
print(get.__doc__)
2、一个函数添加多个装饰器:先运行的装饰器先生效
import requestsView Code
import time
def timmer(func):
def warrper(*args,**kwargs):
start_time=time.time()
res=func(*args,**kwargs)
end_time=time.time()
print(end_time-start_time)
return res
return warrper
def login(func):
def warrper(*args,**kwargs):
i=0
while i<3:
user=input('plz input your name:')
password=input('plz input your password:')
if user=='Tianle' and password=='123':
print('认证通过')
res=func(*args,**kwargs)
return res
else:
print('用户密码密码错误,请重试')
i+=1
if i==3:
print('失败次数过多')
break
return warrper
@timmer
@login
def get():
'''爬虫'''
url='http://www.baidu.com'
def MyGet():
time.sleep(1)
return requests.get(url).text
return MyGet()
get()
迭代器
重复的过程称为迭代,每次重复即一次迭代,并且每次迭代的结果是下一次迭代的初始值
凡是对象有__iter__方法:对象.__iter__, 该对象就是可迭代对象
什么是迭代器对象:
1:有__iter__,执行得到仍然是迭代本身
2:有__next__
#迭代器对象的优点
1:提供了一种统一的(不依赖于索引的)迭代方式
2:迭代器本身,比起其他数据类型更省内存
# s='hello'View Code
# l=['a','b','c','d']
# t=('a','b','c','d')
# dic={'name':'egon','sex':'m',"age":18}
# set1={1,2,3}
# f=open('db.txt')
# s.__iter__()
# l.__iter__()
# t.__iter__()
# dic.__iter__()
# set1.__iter__()
# f.__iter__()
l=[1,3,4,5,6,7]View Code
d={'name':'Tianle','age':18}
l_iter=l.__iter__()
# print(l_iter.__next__())
# print(l_iter.__next__())
# print(l_iter.__next__())
#
d_iter=d.__iter__()
# print(d_iter.__next__())
# print(d_iter.__next__())
while True:
try:
i=next(l_iter)
print(i)
except StopIteration:
break
while True:
try:
k=next(d_iter)
print(k,d[k])
except StopIteration:
break
#迭代器对象的缺点
1:一次性,只能往后走,不能回退,不如索引取值灵活
2:无法预知什么时候取值结束,即无法预知长度
l=['a','b','c','d']View Code
for item in l: #iter_l=l.__iter__()
print(item)
for item in {1,2,3,4}:
print(item)
with open('a.txt') as f:
# for line in f: #i=f.__iter__()
# print(line)
print(f is f.__iter__())
生成器
在函数内部包含yield关键字,那么该函数执行的结果就是生成器
生成器其实就是迭代器
yield和return的比较
功能:1、把函数的结果做成迭代器 2、函数暂停与再继续运行的状态是由yield
相同:都有返回值
不同:return只能返回一次值,而yield可以返回多次值
三元表达式:
x=1
y=2
if x > y:
print(x)
else:
print(y)
print(x) if x > y else print(y)
print('True') if True and False else print('False')
列表解析
l=[]
for i in range(10):
l.append(i)
print(l)
#只允许一个判断条件的情况下使用列表解析
print([i for i in range(10) if i >5] )
nums=[1,2,3,4,5,6]
print([i**2 for i in nums if i >3])
names=['a_sb','b_sb','c','d_sb']
print([i for i in names if i.endswith('sb')])
生成器表达式
g=('egg%s' %i for i in range(1000))
print(g)
print(next(g))
print(next(g))
print(next(g))
with open('a.txt',encoding='utf-8') as f:
# res=max((len(line) for line in f))
res=max(len(line) for line in f)
print(res)
print(max([1,2,3,4,5,6]))
with open('a.txt',encoding='utf-8') as f:
g=(len(line) for line in f)
print(max(g))
print(max(g))
print(max(g))