装饰器是程序开发中经常会用到的一个功能,用好了装饰器,开发效率如虎添翼,所以这也是Python面试中必问的问题,但对于好多小白来讲,这个功能 有点绕,自学时直接绕过去了,然后面试问到了就挂了,因为装饰器是程序开发的基础知识,这个都 不会,别跟人家说你会Python, 看了下面的文章,保证你学会装饰器.
①.、先明白这段代码
####?第一波?####
def?foo():
print?'foo'
foo??#表示是函数
foo()?#表示执行foo函数
####?第二波?####
foo?=?lambda?x:?x?◆?1
foo()?#?执行下面的lambda表达式,而不再是原来的foo函数,因为函数?foo?被重新定义了
初创公司有N个业务部门,1个基础平台部门,基础平台负责提供底层的功能,如:数据库操作、redis调用、监控API等功能.业务部门使用基础功能时,只需调用基础平台提供的功能即可.如下:
###############?基础平台提供的功能如下?###############
def?f1():
print?'f1'
###############?业务部门A?调用基础平台提供的功能?###############
f1()
###############?业务部门B?调用基础平台提供的功能?###############
目前公司有条不紊的进行着,但是,以前基础平台的开发人员在写代码时候没有关注验证相关的问题,即:基础平台的提供的功能可以被任何人使用.现在需要对基础平台的所有功能进行重构,为平台提供的所有功能添加验证机制,即:执行功能前,先进行验证.
老大把工作交给 Low B,他是这么做的:
跟每个业务部门交涉,每个业务部门自己写代码,调用基础平台的功能之前先验证.诶,这样一来基础平台就不需要做任何修改了.
当天Low B 被开除了...
老大把工作交给 Low BB,他是这么做的:
#?验证1
###############?业务部门不变?###############
###?业务部门A?调用基础平台提供的功能###
###?业务部门B?调用基础平台提供的功能?###
过了一周 Low BB 被开除了...
老大把工作交给 Low BBB,他是这么做的:
只对基础平台的代码进行重构,其他业务部门无需做任何修改
def?check_login():
pass
check_login()
老大看了下Low BBB 的实现,嘴角漏出了一丝的欣慰的笑,语重心长的跟Low BBB聊了个天:
老大说:
写代码要遵循开发封闭原则,虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,它规定已经实现的功能代码不允许被修改,但可以被扩展,即:
封闭:已实现的功能代码块
def?w1(func):
def?inner():
return?func()
return?inner
@w1
Low BBB心惊胆战的问了下,这段代码的内部执行原理是什么呢?
老大正要生气,突然Low BBB的手机掉到地上,恰恰屏保就是Low BBB的女友照片,老大一看一紧一抖,喜笑颜开,交定了Low BBB这个朋友.详细的开始讲解了:
单独以f1为例:
当写完这段代码后(函数未被执行、未被执行、未被执行),python解释器就会从上到下解释代码,步骤如下:
def w1(func): ?==将w1函数加载到内存
没错,从表面上看解释器仅仅会解释这两句代码,因为函数在没有被调用之前其内部代码不会被执行.
从表面上看解释器着实会执行这两句,但是 @w1 这一句代码里却有大文章,@函数名?是python的一种语法糖.
执行w1函数,并将 @w1 下面的?函数?作为w1函数的参数,即:@w1 等价于 w1(f1)
所以,内部就会去执行:
def inner:
#验证
return f1() ? # func是参数,此时 func 等于 f1
return inner ? ? # 返回的 inner,inner代表的是函数,非执行函数
其实就是将原来的 f1 函数塞进另外一个函数中
w1函数的返回值是:
return 原来f1() ?# 此处的 f1 表示原来的f1函数
然后,将此返回值再重新赋值给 f1,即:
新f1 =?def inner:
return 原来f1()
所以,以后业务部门想要执行 f1 函数时,就会执行 新f1 函数,在 新f1 函数内部先执行验证,再执行原来的f1函数,然后将 原来f1 函数的返回值 返回给了业务调用者.
如此一来, 即执行了验证的功能,又执行了原来f1函数的内容,并将原f1函数返回值 返回给业务调用着
Low BBB 你明白了吗?要是没明白的话,我晚上去你家帮你解决吧!!!
先把上述流程看懂,之后还会继续更新...
问题:被装饰的函数如果有参数呢?
#一个参数
def?inner(arg):
return?func(arg)
def?f1(arg):
#两个参数
#三个参数
问题:可以装饰具有处理n个参数的函数的装饰器?
def?inner(*args,**kwargs):
return?func(*args,**kwargs)
问题:一个函数可以被多个装饰器装饰吗?
问题:还有什么更吊的装饰器吗?
#!/usr/bin/env?python
def?Before(request,kargs):
print?'before'
def?After(request,kargs):
print?'after'
def?Filter(before_func,after_func):
def?outer(main_func):
def?wrapper(request,kargs):
before_result?=?before_func(request,kargs)
if(before_result?!=?None):
return?before_result;
main_result?=?main_func(request,kargs)
if(main_result?!=?None):
return?main_result;
after_result?=?after_func(request,kargs)
if(after_result?!=?None):
return?after_result;
return?wrapper
return?outer
@Filter(Before,?After)
def?Index(request,kargs):
print?'index'
一般来说是一个函数名或者是一个变量,没有什么特别的意思,大家都这么写.就像说某人时会叫他张三李四是一样的...
? 你的意思是不是指如果 foo 这个函数里的 a 变量如果获取到的是 True 的时候,要让 foo 这个函数外面的传入的变量的 b 值变成 False?
如果是,那么代码如下(注意程序缩进):
a=False
b=True
def foo():
global a # 将变量提档,使用公共变量而不是私有变量
global b
if a:
b=False
if b:
a=True
print(foo())
print('Now B is: ' ◆ str(b))
主要问题是公共变量与私有变量的问题.
装饰器(decorator)是Python中的高级语法.装饰的意思就是动态扩展被装饰对象的功能.装饰器可以用于装饰函数、方法和类.
一 嵌套函数
# 定义一个外层函数def foo(): # 定义了一个内部函数 def bar(): print("hello world")
函数bar是一个定义在foo函数内部的函数.
Python中的函数是支持嵌套的,也就是可以在一个函数内部再定义一个函数.
然后,我们还知道函数是可以当作变量的,于是我们就可以在foo函数中把定义的这个bar函数返回.就像下面这样:
# 定义一个外层函数def foo(): # 定义了一个内层函数 def bar(): print("hello world") return
barfunc = foo()func() # func -- bar,这里执行func其实就相当于执行了在foo函数内部定义的bar函数
二 闭包形态1
# 闭包形态1def foo(): name = "Andy" # 外部函数的局部变量 # 定义了一个内部函数 def bar():
print(name) # 虽然bar函数中没有定义name变量,但是它可以访问外部函数的局部变量name return barfunc =
foo()func() # func -- bar -- 除了是一个函数,还包含一个值(它外层函数的局部变量)的引用
print(name) # 内部函数同样可以获取到传到外部函数的变量(参数) return barfunc = foo("Andy") #
把"Andy"当成参数传入foo函数 -- 其内部定义的bar函数也能拿到这个"Andy"func() # func -- bar --
除了是一个函数,还包含一个值(它外层函数的参数)的引用
四 装饰器形态1
# 还是定义一个外层函数def foo(name): # 我接收的参数是一个函数名 # 定义了一个内部函数 def bar():
print("这是新功能...") # 新功能 name() # 函数名加()就相当于执行-- 我传进来原函数的函数名,这里就相当于执行了原函数
return bar# 定义一个被装饰的函数def f1(): print("hello world.") # 用foo函数装饰f1函数f1 =
foo(f1)# 不改变f1的调用方式f1() # -- 此时函数已经扩展了新功能
# 还是定义一个外层函数def foo(name): # 接收的参数是一个函数名 # 定义了一个内部函数 def bar():
print("这是新功能...") # 新功能 name() # 函数名加()就相当于执行-- 传进来原函数的函数名,这里就相当于执行了原函数
不改变f1的调用方式f1() # -- 此时函数已经扩展了新功能.
你装饰器的用法不对,你要的功能大概的写法如下:
====
def?tsfun(func,?*args,?**kwargs):
print?"%s,%s,?called"?%(ctime(),func.__name__)
func(*args,?**kwargs)
如果Origin指定的源不在许可范围内, 服务器会返回一个不带有Access-Control-Allow-Origin字段的响应 . 浏览器解析时发现缺少了这个字段, 就会报错.
修改Django中的views.py文件修改views.py中对应API的实现函数,给返回值加上响应头Access-Control-Allow-Origin,允许其他域通过Ajax请求数据:
满足以下两个条件的请求.
(1) 请求方法是以下三种方法之一:
非简单请求就是复杂请求.
非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight).
预检请求为OPTIONS请求,用于向服务器请求权限信息的.
预检请求被成功响应后,才会发出真实请求,携带真实数据.
请求时,接口地址是作为构建出的脚本标签的src的,这样,当脚本标签构建出来时,最终的src是接口返回的内容
这时,只要浏览器定义了foo函数,该函数就会立即调用.作为参数的JSON数据被视为JavaScript对象,而不是字符串,所以呢避免了使用JSON.parse的步骤.
JSONP使用注意
基于JSONP的实现原理,所以JSONP只能是"GET"请求,不能进行较为复杂的POST和其它请求,所以遇到那种情况,就得参考下面的CORS解决跨域了(所以如今它也基本被淘汰了).
前面讲了JSONP的实现原理,现在我们可以自己写JS来实现JSONP功能.
一般情况下,我们希望这个script标签能够动态的调用,而不是像固定在html里面所以没等页面显示就执行了,很不灵活.
我们可以通过页面的触发事件操作后,通过javascript动态的创建script标签,这样我们就可以灵活调用远程服务.实例如下:
如上,jQuery框架也当然支持JSONP,可以使用 $.getJSON(url,[data],[callback]) 方法.
上述这种方法,很方便,不需要我们自己定义回调函数和指定回调函数名,但是,如果说我们想指定自己的回调函数名,或者说服务上规定了固定回调函数名该怎么办呢?
我们可以使用$.ajax方法来实现.如下例:
在上小节中jsonp: 'callbacks'就是定义一个存放回调函数的键,jsonpCallback是前端定义好的回调函数方法名,server端接受callback键对应值后就可以在其中填充数据打包返回.
但是,jsonpCallback参数可以不定义,jquery会自动定义一个随机名发过去,那前端就得用回调函数来处理对应数据了.利用jQuery可以很方便的实现JSONP来进行跨域访问.
如此,我们的跨域处理即完成,支持所有的请求.
以上就是土嘎嘎小编为大家整理的foo函数python相关主题介绍,如果您觉得小编更新的文章只要能对粉丝们有用,就是我们最大的鼓励和动力,不要忘记讲本站分享给您身边的朋友哦!!