当前位置: 首页 > news >正文

用jsp做的购物网站互联网推广销售是做什么的

用jsp做的购物网站,互联网推广销售是做什么的,wordpress 调用文章作者,东营政府采购网官网1.介绍 Python装饰器在开发过程中,有着较为重要的地位,但是对于初学者来说,并不便于理解,本文将带着大家分析python装饰器的使用。 2.定义 装饰器本质上就是一个函数,这个函数接受其他函数作为参数,并将其以…

1.介绍

Python装饰器在开发过程中,有着较为重要的地位,但是对于初学者来说,并不便于理解,本文将带着大家分析python装饰器的使用。

2.定义

装饰器本质上就是一个函数,这个函数接受其他函数作为参数,并将其以一个新的修改后的函数作为替换。
概念较为抽象,我们来考虑如下一个场景,现在我们需要对用户年龄进行认证,如果年龄小于18,则给出提示,年龄不符合要求(嘿嘿嘿,大家都懂)。代码如下:

class Movie(object):def get_movie(self,age):if age<18:raise Exception('用户年龄不符合要求')return self.moviedef set_movie(self,age,movie):if age <18:raise Exception('用户年龄不符合要求')self.movie = movie复制代码

考虑到复用性的问题,我们对其修改:

def check_age(age):
if age < 18:raise Exception('用户年龄不符合要求')class User(object):def get_movie(self, age):check_age(age)return self.moviedef set_movie(self, age, movie):check_age(age)self.movie = movie复制代码

现在,代码看起来整洁了一点,但是用装饰器的话可以做的更好:

def check_age(f):def wrapper(*args,**kwargs):if args[1]<18:raise Exception('用户年龄不符合要求')return f(*args,**kwargs)return wrapperclass User(object):@check_agedef get_movie(self, age):return self.movie@check_agedef set_movie(self, age, movie):self.movie = movie复制代码

上面这段代码就是使用装饰的一个典型例子,函数check_age中定义了另一个函数wrapper,并将wrapper做为返回值。这个例子很好的展示了装饰器的语法。

2.2 装饰器的本质

上面说到装饰器的本质就是一个函数,这个函数接受另一个函数作为参数,并将其其以一个新的修改后的函数进行替换。再来看下面一个例子,可以帮我们更好的理解:

def bread(func):def wrapper():print ("</''''''\>")func()print ("</______\>")return wrapperdef sandwich():print('- sandwich -')sandwich_copy = bread(sandwich)
sandwich_copy()复制代码

输出结果如下:

</''''''\>
- sandwich -
</______\>复制代码

bread是一个函数,它接受一个函数作为参数,然后返回一个新的函数,新的函数对原来的函数进行了一些修改和扩展(打印一些东西),且这个新函数可以当做普通函数进行调用。
使用python提供的装饰器语法,简化上面的代码:

def bread(func):def wrapper():print ("</''''''\>")func()print ("</______\>")return wrapper@bread
def sandwich():print('- sandwich -')sandwich =  sandwich()复制代码

到这里,我们应该理解了装饰器的用法和作用了,再次强调一遍,装饰器本质上就是一个函数,这个函数接受其他的函数作为参数,并将其以一个新的修改后的函数进行替换

3.使用装饰器需要注意的地方

前面我们介绍了装饰器的用法,可以看出装饰器其实很好理解,也非常简单。但是装饰器还有一些需要我们注意的地方

3.1 函数的属性变化

装饰器动态替换的新函数替换了原来的函数,但是,新函数缺少很多原函数的属性,如docstring和函数名。

def bread(func):def wrapper():print ("</''''''\>")func()print ("</______\>")return wrapper@bread
def sandwich():'''there are something'''print('- sandwich -')def hamberger():'''there are something'''print('- hamberger -')def main():print(sandwich.__doc__)print(sandwich.__name__)print(hamberger.__doc__)print(hamberger.__name__)main()复制代码

执行上面的程序,得到如下结果:

None
wrapper
there are something
hamberger复制代码

在上述代码中,定义了两个函数sandwich和hanberger,其中sandwich使用装饰器@bread进行了封装,我们获取sandwich和hanberger的docstring和函数名字,可以看到,使用了装饰器的函数,无法正确获取函数原有的docstring和名字,为了解决这个问题,可以使用python内置的functools模块。

def bread(func):@functools.wrap(func)def wrapper():print ("</''''''\>")func()print ("</______\>")return wrapper复制代码

我们只需要增加一行代码,就能正确的获取函数的属性。
此外,也可以像下面这样:

import functools
def bread(func):def wrapper():print ("</''''''\>")func()print ("</______\>")return functools.wraps(func)(wrapper)复制代码

不过,还是第一种方法的可读性要更强一点。

3.2使用inspect函数来获取函数参数

我们再来看如下一段代码:

def check_age(f):@functools.wraps(f)def wrapper(*args,**kwargs):if kwargs.get('age')<18:raise Exception('用户年龄不符合要求')return f(*args,**kwargs)return wrapperclass User(object):@check_agedef get_movie(self, age):return self.movie@check_agedef set_movie(self, age, movie):self.movie = movieuser = User()
user.set_movie(19,'Avatar')复制代码

这段代码运行后会直接抛出,因为我们传入的'age'是一个位置参数,而我们却用关键字参数(kwargs)获取用户名,因此。‘kwargs.get('age')’返回None,None和int类型是无法比较的,所以会抛出异常。
为了设计一个更加智能的装饰器,我们需要使用python的inspect模块。如下所示:

def check_age(f):@functools.wraps(f)def wrapper(*args,**kwargs):getcallargs = inspect.getcallargs(f, *args, **kwargs)print(getcallargs)if getcallargs.get('age')<18:raise Exception('用户年龄不符合要求')return f(*args,**kwargs)return wrapper复制代码

通过inspect.getcallargs,返回一个将参数名和值作为键值对的字典,在上述代码中,返回{'self': <__main__.user object="" at="">, 'age': 19, 'movie': 'Avatar'},通过这种方式,我们的装饰器不必检查参数username是基于位置参数还是基于关键字参数,而只需在字典中查找即可。

3.3多个装饰器的调用顺序

在开发中,会出现对于一个函数使用两个装饰器进行包装的情况,代码如下:

def bold(f):def wrapper():return "<b>"+f()+"</b>"return wrapper
def italic(f):def wrapper():return "<i>"+f()+"</i>"return wrapper
@bold
@italic
def hello():return "hello world"print(hello()) # <b><i>hello world</i></b>复制代码
  • 分析
    在前面我们提到,装饰器就是在外层进行了封装:

      @italichello()hello = italic(hello)复制代码

    对于两层封装便是:

      @bold@italichello()hello = bold(italic(hello))复制代码

    这样理解多个装饰器的调用顺序,之后就不会再有疑问了

    3.4 给装饰器传递参数

    现在,我们的需求修改了,并不是限定为18岁了,对于不同的地区可能是20岁,也可能是16岁。那么我们如何设计一个通用的装饰器呢?

def check_age(age='18'):def decorator(f):@functools.wraps(f)def wrapper(*args, **kwargs):getcallargs = inspect.getcallargs(f, *args, **kwargs)if getcallargs.get('age') < age:raise Exception('用户年龄不符合要求')return f(*args, **kwargs)return wrapperreturn decoratorclass User(object):@check_age(18)def get_movie(self, age):return self.movie@check_age(18)def set_movie(self, age, movie):check_age(age)self.movie = movie
user = User()
user.set_movie(16,'Avatar')复制代码

通过上述方式,我们可以在使用装饰器时设置age的值,而不需要修改装饰器内的代码,使程序的健壮性更强,符合开闭原则。

4.总结

到这里,关于装饰器的理解,我们就介绍完了,配合在实际开发中的使用,你很快就能掌握它。

http://www.lbrq.cn/news/2446183.html

相关文章:

  • 电商网站开发报价单青岛网站推广关键词
  • 做设计接私活的网站电子商务seo是什么意思
  • 电话开发网站建设话术cps推广平台有哪些
  • 罗村网站建设快速排名优化seo
  • 电子商务网站建设的步骤一般为(国外免费建站网站搭建
  • 网站目标人群企业网站推广技巧
  • 免费b2b网站大全黄页88恶意点击软件有哪些
  • SFDA的网站建设网站优化排名方法
  • 南充市房产信息网官网seo怎么做推广
  • 有哪些网站可以免费看电影河南自助建站seo公司
  • 天元建设集团有限公司青岛迈步者seo
  • 网站建设招标公告网页制作代码html制作一个网页
  • 搜索不到我的网站搜索引擎的设计与实现
  • 深圳市住房和建设局领导班子广州seo公司如何
  • 做网站被骗首付款怎么报案全网营销国际系统
  • 网站建设书籍目录百度app客服人工电话
  • 日本做鸡做爱成人网站播放微信crm客户管理系统
  • 深圳css3网站开发多少钱小红书怎么推广引流
  • 一个可以做网站百度seo排名优化公司哪家好
  • 福州seo计费seo是什么东西
  • 金融网站源码最新军事消息
  • 网站建设教程开源代码下载七台河网站seo
  • photoshop 做网站怎么上百度搜索
  • 向公司申请请做网站网络营销推广策划
  • 网站建设销售招聘搜索引擎优化结果
  • 那些做app网站的怎么寻找客户的网站客服系统
  • 成都装修网站建设多少钱中国网站建设公司
  • 做暧暧网站在线观看网络营销模式有哪些类型
  • 有学给宝宝做衣服的网站吗互联网论坛
  • t型布局网站的优缺点永久免费域名申请
  • 根本是什么
  • 【C++基础】指针常量 | 常量指针 | int* p | const int* p | int* const p| const int* const p
  • LE AUDIO CIS/BIS音频传输时延计算方法
  • 时间和空间复杂度
  • JavaWeb学习打卡13(JSP原理解析)
  • 开发避坑短篇(5):vue el-date-picker 设置默认开始结束时间