python之闭包、装饰器、生成器、反射
1. 函数的作用域
1.在函数定义时候就固定,与调用位置无关,在调用的时候返回到函数定义的位置
x=1 #全局作用 def f1(): #整个f1函数是定义阶段 def f2(): print(x) return f2 def foo(func): x=3 func() #func()调用阶段 x=200 #这样定义x又变成全局了 foo(f1()) #执行foo(f1()) 返回到F1函数里找x所以打印是1不是3
生成器
2.名称空间
内置名称空间:在python解释器启动产生的空间,简单理解就是python自带的方法比如:max()len()
全局名称空间 :在全局定义的好的名称空间,文件级别的产生的 比如:
x=1 #全局作用 def test():
x=2 #局部作用 print(x) test()
if x=1 y=2 #全局作用
#在执行test()调用的时候先加载内置查找有没有test这个内置函数,如果去全局里查找test这个函数方法,最后局部
局部名称空间:在调用函数时候产生局部名称空间 y=2,在调用teset()立马产生了局部作用空间
nonlocal x 函数正上方的x的变量
global x 改成全局的变量
3.闭包函数
闭包函数的作用主要在与装饰器
函数式编程里面闭包只是给函数捆绑死一个值或者状态
1.定义在函数内部的函数
2. 包含对外部作用域名字的引用,而不是对全局作用域名字的引用
3.该内部函数就称为闭包函数
import requests #第一种传参闭包 def re(func): def get(): return requests.get(func).text return get baidu=re('http://www.baidu.com') baidu1=re('http://www.souhu.com') print(baidu()) #第二种自定义固定值闭包函数 def test(): url='http://www.baidu.com' def gett(): #gett()是闭合函数外面包裹这个url return requests.get(url).text return gett func=test() print(func())
def ff():
url=‘nq.com’
func() #此时的func已经一种状态就是url这个百度地址不会
ff() #得到的结果是url='http://www.baidu.com'
4.装饰器
装饰器的定义:1.在不变动主功能函数的前提下,为其添加上新的功能或者状态。
例:比如抓数据时候,我们需要添加计时器,显示抓取用了多少时间,
写一个te函数是计时器功能,这样可以给爬取baidu、搜狐网站添加上这个计时器。
第一种装饰器写法,其实是给闭包函数添加了一个功能
import requests improt time #第一种传参闭包,这里当主功能函数 def re(func): def get(): return requests.get(func).text return get baidu=re('http://www.baidu.com') baidu1=re('http://www.souhu.com') print(baidu()) #装饰器,给获取百度数据添的用时 def te(func): def timer(): start=time.time() func() stop=time.time() print("获取数据的时间%s"%(stop-start)) return timer baidu=te(baidu) baidu()
第二种写法
这种方法适合用@装饰器函数名称,上面例子是闭包函数,已经闭包了是不可以种@的来装饰建议使用 函数调用方式
n是表示给传参的函数,以防万一最要用*args,**kwargs的方式
1 import psutil 2 def count(func): 3 def timer(): 4 fu=psutil.cpu_count() 5 print(fu) 6 func(1) 7 return timer 8 9 10 #查看cpu使用情况的一个函数 11 @count 12 def main(n): 13 res=psutil.cpu_times() 14 print(res) 15 print(n) 16 17 #查看Process的一个函数n 18 @count 19 def test(t): 20 fl=psutil.Process 21 print(fl) 22 print(t) 23 24 25 test() 26 main()
装饰器的细节问题:
from functools import wraps 在装饰器中添加显示备注信息,如下代码
import psutil from functools import wraps def count(func): @wraps(func) #这里需要添加wraps这个装饰器 def timer(): fu=psutil.cpu_count() print(fu) func(1) return timer #查看cpu使用情况的一个函数 @count def main(n): ''' 这个是mian函数的 ''' res=psutil.cpu_times() print(res) print(n)
#return 123 如果函数里有return 打印这个函数结果时候显示空 因为,main显示已经被conunt函数装饰了,所以要在timer里面retrun才对 print(main.__doc__) #这里是打印上面的备注信息
生成器
生成器:不断调用和返回值,生成器
迭代器:可以被next()函数调用并不断返回下一个值的对象称为迭代器,可以直接作用于for循环的对象统称为可迭代对象
# def Pycharm(name): # food_list = [] # food = yield food_list # print("%s想吃%s" % (name, food)) # food_list.append(food) # print(food_list) # # # res = Pycharm('alex') # next(res) #next 会停留在 food=yield这里,send传送后继续执行下面的内容 # res.send('fangfood')
python之反射
反射即想到4个内置函数分别为:getattr、hasattr、setattr、delattr 获取成员、检查成员、设置成员、删除成员下面逐一介绍先看例子
它的核心本质其实就是利用字符串的形式去对象(模块)中操作(查找/获取/删除/添加)成员,一种基于字符串的事件驱动
class func(): def __init__(self): self.teacher='teacher' self.student='student' self.age='ee' self.name='name' def test01(self): print('反射机智显示test01功能%s' %self.teacher) def test02(self): print('反射机智显示test02功能%s' %self.student) func=func() def run(): ''' :return:通过res用户输入相对应的变量、函数方法 通过反射机制来判断、增删添改 ''' res=input('>>我想执行里面的函数:').strip() hasa=hasattr(func,res) #hasattr 可以判断func类中是否存在res传入的变量或者函数方法 res=getattr(func,res,'not find') #getattr 可以获取传入方法或者函数的执行结果, # 得到是内存地址需要通过res()来展示内容 #not find意思 如果没有找到相对应的变量和函数 通过print(res())来打印出notfind # print(res()) tom=setattr(func,res,18) #setattr 可以修改传入变量的结果 比如self age=17 通过setattr可以修改成18 print(func.age) delattr(func,'age') #delattr 删除age这个变量 print(func.age) # setattr(func,res,18) run()