1 函数嵌套
#函数的嵌套调用:在调用一个函数的过程中,又调用了其他函数
def max2(x,y)
if x > y:
return x
else:
return y
def max4(a,b,c,d):
res1=max2(a,b)
res2=max2(res1,c)
res3=max2(res2,d)
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 f2func=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+=1dic={ '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,Iterators='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 timedef 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')