#函数的嵌套调用:在调用一个函数的过程当中,又调用了其余函数python
def max2(x,y)web
if x > y:闭包
return xapp
else:函数
return y
url
def max4(a,b,c,d):spa
res1=max2(a,b)code
res2=max2(res1,c)
对象
res3=max2(res2,d)blog
return res3
print(max4(1,2,3,-1))
#函数嵌套定义:在一个函数的内部又定义了一个另外的函数
def f1():
x=1
def f2():
print('from f2')
print(x,f2)
f1()
函数内部定义 在外部访问不了,只能在内部访问
问题:为何在f1里面定义了f2 只能在内部使用 就是下面的名称空间的定义
2.名称空间与做用域
#名称空间:存放名字的地方,准确的说名称空间是存放名字与变量值绑定关系的地方
python中名称空间分为三种
1 内置名称空间 #print len max 存放python自带的名字,那么何时产生呢?显而易见确定是python解析器启动后产生
2 全局名称空间 #在执行文件时产生存放文件级别定义名字,那么什么是文件级别的名字?没有缩进基本都是
如下这些都属于全局名称空间
x=10
import os
def func():
pass
class Foo():
pass
if x==1:
z=3
3 局部名称空间 #在执行文件的过程当中若是调用了函数则会产生该函数的局部名称空间、
用来存放该函数内定义的名字,更名字在调用函数时生效,在函数调用结束后实效
那么这三个名称空间加载顺序 :内置名称空间->全局名称空间->局部名称空间
取值顺序或者说名字的查找顺序:局部名称空间->全局名称空间->内置名称空间
例子:
max=1
def foo():
max=2
print(max)
foo() #依次注释max 查看max值的变化
做用域:做用域即范围
做用域分两种
1 全局范围:全局存活,全局有效 #在任何位置都能访问globals()
2 局部范围:临时存活,局部有效 #只能在函数内部访问locals()
def f1():
x=1
y=2
def f2():pass
print(locals())#查看局部
print(globals())#查看全局
print(locals() is globals()) 外部调用 局部就是全局结果为true
print(dir(globals()))
#global nonlocal关键字
x=1
def f1():
x=2
def f2():
global x #在局部中不要尽可能不要改全局变量
nonlocal x #修改当前x的值为上一层的值 注意nonlocal只能修改局部不能修改全局,全局用global
x=3
print(x) #x=2
f1()
print(x)
-------------
l=[]
def f2():
l.append('f2') #l是可变类型全部能够修改 针对全局不可变类型须要加global
f2()
print(l)
#优先掌握:做用域关系,在函数定义时就已经固定了,
与调用位置无关
x=1
def f1():
def f2():
print(x)
return f2 #暂时不考虑递归
func=f1()
print(func)
3 闭包函数
大前提:做用域关系,在函数定义时就已经固定
,于调用位置无关,在调用函数时,必须必须必须
回到函数原来定义的位置去找做用域关系
#闭包函数:
#1. 定义在函数内部的函数
#2. 包含对外部做用域名字的引用,而不是对全局做用域名字的引用
#那么该内部函数就称为闭包函数
x=1
def f1():
x=11111111111 #最后x结果
def f2():
print(x)
return f2
func=f1()
x=1000 #闭包函数 只会打印函数内部的值 外部不会改变
func()
那么有什么用的?
def deco():
x=11
def wrapper():
print(x)
return wrapper # 须要打破层级在外部用 因此须要return
func=deco() #这时deco()是固定参数 不须要传参
func()
写一个爬取网页程序:闭包函数应用
import requests
def http_web(url):
#url='https://www.baidu.com'
def get():
return requests.get(url).text
return get
baidu_web=http_web('https://www.baidu.com')
python_web=http_web('https://www.python.org')
print(baidu_web())
print(python_web())
4 装饰器--->闭包函数的一种应用场景
#1 开放封闭原则:对扩展是开放的 对修改是封闭的
#2 装饰器:装饰器的目的是为其余人添加新功能
#装饰器自己能够是任意可调用对象,被装饰的对象自己也能够是任意可调用对象
ps若是有多个装饰器 也要按照前后顺序
#2.1 装饰器的遵循的原则 1 不修改被装饰对象的源代码 2 不修改被调用对象的调用方式
#2.2 装饰器的目的是:在遵循1和2原则的前提 为其余新功能函数添加
#@装饰器名,必须写在被装饰的对象的正上方,而且是单独一行
例子:
import time
def timmer(func):
# func=index
def wrapper():
start=time.time()
func()
stop=time.time()
print('run time is %s' %(stop-start))
return wrapper
@timmer # index=timmer(index)
def index():
time.sleep(3)
print('welcome to index')
@timmer # home=timmer(home)
def home():
time.sleep(2)
print('welcome to home page')
index()
home()
有参数装饰器
import time
def timmer(func):
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():
time.sleep(3)
print('welcome to index')
return 123
@timmer # home=timmer(home)
def home(name):
time.sleep(2)
print('welcome %s to home page' %name)
# res=index() #res=wrapper()
# print(res)
res1=home('egon') #wrapper('egon')
print(res1)
5 迭代器
#迭代:是一个重复的过程,每一次重复,都是基于上一次的结果而来 # while True: #单纯的重复 # print('你瞅啥') # l=['a','b','c','d'] # count=0 # while count < len(l): # print(l[count]) # count+=1 dic={'name':'egon','sex':'m',"age":18} #上述按照索引的取值方式,不适于没有索引的数据类型 #迭代器: #可迭代对象iterable:凡是对象下有__iter__方法:对象.__iter__,该对象就是可迭代对象 # s='hello' # 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__() #迭代器对象:可迭代对象执行内置的__iter__方法,获得的结果就是迭代器对象 # dic={'name':'egon','sex':'m',"age":18} # # i=dic.__iter__() # # print(i) #iterator迭代器 # # # i.__next__() #next(i) # print(next(i)) # print(next(i)) # print(next(i)) # print(next(i)) #StopIteration # # l=['a','b','c','d'] # # i=l.__iter__() # print(next(i)) # print(next(i)) # print(next(i)) # print(next(i)) # print(next(i)) #StopIteration #不依赖于索引的取值方式 # l=['a','b','c','d'] # dic={'name':'egon','sex':'m',"age":18} # iter_l=iter(l) # iter_dic=iter(dic) # while True: # try: # # print(next(iter_l)) # k=next(iter_dic) # print(k,dic[k]) # except StopIteration: # break #什么是迭代器对象: #1 有__iter__,执行获得仍然是迭代自己 #2 有__next__ #迭代器对象的优势 #1:提供了一种统一的(不依赖于索引的)迭代方式 #2:迭代器自己,比起其余数据类型更省内存 # l=['a','b','c','d'] # i=iter(l) # dic={'a':1,'b':2} # x=dic.keys() # print(x) # i=x.__iter__() # # with open('a.txt') as f: # # print(next(f)) # # print(next(f)) # # print(next(f)) # f.read() #迭代器对象的缺点 #1:一次性,只能日后走,不能回退,不如索引取值灵活 #2:没法预知何时取值结束,即没法预知长度 # l=['a','b','c','d'] # i=iter(l) # print(next(i)) # print(next(i)) # print(next(i)) #for循环原理 # # l=['a','b','c','d'] # 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__()) #补充:判断可迭代对象与迭代器对象(了解) from collections import Iterable,Iterator s='hello' l=['a','b','c','d'] t=('a','b','c','d') dic={'name':'egon','sex':'m',"age":18} set1={1,2,3} f=open('a.txt') # print(isinstance(s,Iterable)) # print(isinstance(l,Iterable)) # print(isinstance(t,Iterable)) # print(isinstance(dic,Iterable)) # print(isinstance(set1,Iterable)) # print(isinstance(f,Iterable)) print(isinstance(s,Iterator)) print(isinstance(l,Iterator)) print(isinstance(t,Iterator)) print(isinstance(dic,Iterator)) print(isinstance(set1,Iterator)) print(isinstance(f,Iterator))
6 生成器
#生成器:在函数内部包含yield关键,那么该函数执行的结果是生成器 #生成器就是迭代器 #yield的功能: # 1 把函数的结果作生迭代器(以一种优雅的方式封装好__iter__,__next__) # 2 函数暂停与再继续运行的状态是由yield # def func(): # print('first') # yield 11111111 # print('second') # yield 2222222 # print('third') # yield 33333333 # print('fourth') # # # g=func() # print(g) # from collections import Iterator # print(isinstance(g,Iterator)) # print(next(g)) # print('======>') # print(next(g)) # print('======>') # print(next(g)) # print('======>') # print(next(g)) # for i in g: #i=iter(g) # print(i) # def func(n): # print('我开动啦') # while True: # yield n # n+=1 # # g=func(0) # # # print(next(g)) # # print(next(g)) # # print(next(g)) # for i in g: # print(i) # # for i in range(10000): # print(i) # def my_range(start,stop): # while True: # if start == stop: # raise StopIteration # yield start #2 # start+=1 #3 # # g=my_range(1,3) # # # print(next(g)) # print(next(g)) # print(next(g)) # # # for i in my_range(1,3): # print(i) #yield与return的比较? #相同:都有返回值的功能 #不一样:return只能返回一次值,而yield能够返回屡次值 # python3 tail.py -f access.log | grep 'error' import time def tail(filepath): with open(filepath, 'r') as f: f.seek(0, 2) while True: line = f.readline() if line: yield line else: time.sleep(0.2) def grep(pattern,lines): for line in lines: if pattern in line: print(line,end='') grep('error',tail('access.log'))
7 三元表达式,列表解析,生成器表达式
# def foo(x): # if x > 3: # return 'ok' # else: # return 'no' # # x=10 # res=x if x > 3 else 'no' # print(res) # def max2(x,y): # return x if x > y else y # print(max2(1,3)) # name='xxx' # print('SB' if name == 'you' else 'your')