Python3.5装饰器原理及应用实例详解

本文实例讲述了Python3.5装饰器原理及应用。分享给大家供大家参考,具体如下:

1、装饰器:

(1)本质:装饰器的本质是函数,其基本语法都是用关键字def去定义的。

(2)功能:装饰其他函数,即:为其他函数添加附加功能。

(3)原则:不能修改被装饰的函数的源代码,不能修改被装饰的函数的调用方式。即:装饰器对待被修饰的函数是完全透明的。

(4)简单应用:统计函数运行时间的装饰器

import time
#统计函数运行时间的砖装饰器
def timmer(func):
  def warpper(*args,**kwargs):
    strat_time = time.time()
    func()
    stop_time = time.time()
    print("the func run time is %s" %(stop_time-strat_time))
  return warpper
@timmer
def test1():
  time.sleep(3)
  print("in the test1")
test1()
 

运行结果:

in the test1
the func run time is 3.000171661376953

(5)实现装饰器知识储备:

a、函数即“变量”

b、高阶函数

c、函数嵌套

d、高阶函数+嵌套函数==》装饰器

2、装饰器知识储备——函数即“变量”

定义一个函数,相当于把函数体赋值给这个函数名。

Python解释器如何回收变量:采用引用计数。当引用有没有了时(门牌号不存在),变量就被回收了。

函数的定义也有内存回收机制,与变量回收机制一样。匿名函数没有函数名,就会被回收。

变量的使用:先定义再调用,只要在调用之前已经存在(定义)即可;函数即“变量”,函数的使用是一样的。

函数调用顺序:其他的高级语言类似,Python 不允许在函数未声明之前,对其进行引用或者调用

下面的两段代码运行效果一样:

def bar():
  print("in the bar")
def foo():
  print("in the foo")
  bar()
foo()
#python为解释执行,函数foo在调用前已经声明了bar和foo,所以bar和foo无顺序之分
def foo():
  print("in the foo")
  bar()
def bar():
  print("in the bar")
foo()

运行结果:

in the foo
in the bar
in the foo
in the bar

注意:python为解释执行,函数foo在调用前已经声明了bar和foo,所以bar和foo无顺序之分

原理图为:

3、装饰器知识储备——高阶函数

满足下列其中一种即可称之为高阶函数:

a、把一个函数名当做实参传递给另一个函数(在不修改被装饰函数的情况下为其添加附加功能)

b、返回值中包含函数名(不修改函数的调用方式)

(1)高阶函数示例:

def bar():
  print("in the bar")
def test1(func):
  print(func)  #打印门牌号,即内存地址
  func()
test1(bar)   #门牌号func=bar

运行结果:

<function bar at 0x00BCDFA8>
in the bar

(2)高阶函数的妙处——把一个函数名当做实参传递给另一个函数(在不修改被装饰函数的情况下为其添加附加功能)

import time
def bar():
  time.sleep(3)
  print("in the bar")
#test2在不修改被修饰函数bar的代码时添加了附加的及时功能
def test2(func):
  start_time = time.time()
  func()   #run bar
  stop_time = time.time()
  print("the func run time is %s " %(stop_time-start_time))
#调用方式发生改变,不能像原来的方法去调用被修饰的函数(所以不能实现装饰器的功能)
test2(bar)
#bar()

运行结果:

in the bar
the func run time is 3.000171661376953

(3)高阶函数的妙处——返回值中包含函数名(不修改函数的调用方式)

import time
def bar():
   time.sleep(3)
   print("in the bar")
def test3(func):
  print(func)
  return func
bar = test3(bar)
bar()  #run bar

运行结果:

<function bar at 0x00BADFA8>
in the bar

4、装饰器知识储备——嵌套函数

#函数嵌套
def foo():
  print("in the foo")
  def bar():  #bar函数具有局部变量的特性,不能在外部调用,只能在内部调用
    print("in the bar")
  bar()
foo()

运行结果:

in the foo
in the bar

装饰器应用——模拟网站登录页面,访问需要认证登录页面

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:ZhengzhengLiu
#模拟网站,访问页面和部分需要登录的页面
import timer
user,passwd = "liu","liu123"
def auth(func):
  def wrapper(*args,**kwargs):
    username = input("Username:").strip()
    password = input("Password:").strip()
    if username == user and password == passwd:
      print("\033[32;1mUser has passed authentication!\033[0m")
      res = func(*args,**kwargs)
      print("-----after authentication---")
      return res
    else:
      exit("\033[31;1mInvalid username or password!\033[0m")
  return wrapper
def index():
  print("welcome to index page!")
@auth
def home():
  print("welcome to index home!")
  return "from home"
@auth
def bbs():
  print("welcome to index bbs!")
#函数调用
index()
print(home())
bbs()
 

运行结果:

welcome to index page!
Username:liu
Password:liu123
User has passed authentication!
welcome to home page!
-----after authentication---
from home
Username:liu
Password:liu123
User has passed authentication!
welcome to bbs page!
-----after authentication---

装饰器带参数

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:ZhengzhengLiu
#模拟网站,访问页面和部分需要登录的页面,多种认证方式
import timer
user,passwd = "liu","liu123"
def auth(auth_type):
  print("auth func:",auth_type)
  def outer_wrapper(func):
    def wrapper(*args, **kwargs):
      print("wrapper func args:",*args, **kwargs)
      if auth_type == "local":
        username = input("Username:").strip()
        password = input("Password:").strip()
        if username == user and password == passwd:
          print("\033[32;1mUser has passed authentication!\033[0m")
          #被装饰的函数中有返回值,装饰器中传入的参数函数要有返回值
          res = func(*args, **kwargs)  #from home
          print("-----after authentication---")
          return res
        else:
          exit("\033[31;1mInvalid username or password!\033[0m")
      elif auth_type == "ldap":
        print("ldap....")
    return wrapper
  return outer_wrapper
def index():
  print("welcome to index page!")
@auth(auth_type="local")    #利用本地登录 home = wrapper()
def home():
  print("welcome to home page!")
  return "from home"
@auth(auth_type="ldap")    #利用远程的ldap登录
def bbs():
  print("welcome to bbs page!")
#函数调用
index()
print(home())   #wrapper()
bbs()

运行结果:

更多关于Python相关内容可查看本站专题:《Python数据结构与算法教程》、《Python Socket编程技巧总结》、《Python函数使用技巧总结》、《Python字符串操作技巧汇总》及《Python入门与进阶经典教程》

希望本文所述对大家Python程序设计有所帮助。

(0)

相关推荐

  • Python类装饰器实现方法详解

    本文实例讲述了Python类装饰器.分享给大家供大家参考,具体如下: 编写类装饰器 类装饰器类似于函数装饰器的概念,但它应用于类,它们可以用于管理类自身,或者用来拦截实例创建调用以管理实例. 单体类 由于类装饰器可以拦截实例创建调用,所以它们可以用来管理一个类的所有实例,或者扩展这些实例的接口. 下面的类装饰器实现了传统的单体编码模式,即最多只有一个类的一个实例存在. instances = {} # 全局变量,管理实例 def getInstance(aClass, *args): if aC

  • Python3.5装饰器典型案例分析

    本文实例讲述了Python3.5装饰器.分享给大家供大家参考,具体如下: #!/usr/bin/env python # -*- coding:utf-8 -*- # Author:ZhengzhengLiu #高阶函数+嵌套函数==>装饰器 import time def timer(func): #timer(test1)-->func=test1 def decor(): start_time = time.time() func() #run test1 stop_time = tim

  • Python 使用类写装饰器的小技巧

    最近学到了一个有趣的装饰器写法,就记录一下. 装饰器是一个返回函数的函数.写一个装饰器,除了最常见的在函数中定义函数以外,Python还允许使用类来定义一个装饰器. 1.用类写装饰器 下面用常见的写法实现了一个缓存装饰器. def cache(func): data = {} def wrapper(*args, **kwargs): key = f'{func.__name__}-{str(args)}-{str(kwargs)})' if key in data: result = data

  • 浅谈解除装饰器作用(python3新增)

    一个装饰器已经作用在一个函数上,你想撤销它,直接访问原始的未包装的那个函数. 假设装饰器是通过 @wraps 来实现的,那么你可以通过访问 wrapped 属性来访问原始函数: >>> @somedecorator >>> def add(x, y): ... return x + y ... >>> orig_add = add.__wrapped__ >>> orig_add(3, 4) 7 >>> 如果有多个包

  • python3.6中@property装饰器的使用方法示例

    本文实例讲述了python3.6中@property装饰器的使用方法.分享给大家供大家参考,具体如下: 1.@property装饰器的使用场景简单记录如下: 负责把一个方法变成属性调用: 可以把一个getter方法变成属性,@property本身又创建了另一个装饰器@score.setter,负责把一个setter方法变成属性赋值: 只定义getter方法,不定义setter方法就是一个只读属性 2.通过一个例子来加深对@property装饰器的理解:利用@property给一个Screen对象

  • Python黑魔法@property装饰器的使用技巧解析

    @property有什么用呢?表面看来,就是将一个方法用属性的方式来访问. 上代码,代码最清晰了. class Circle(object): def __init__(self, radius): self.radius = radius @property def area(self): return 3.14 * self.radius ** 2 c = Circle(4) print c.radius print c.area 可以看到,area虽然是定义成一个方法的形式,但是加上@pr

  • 实例讲解Python编程中@property装饰器的用法

    取值和赋值 class Actress(): def __init__(self): self.name = 'TianXin' self.age = 5 类Actress中有两个成员变量name和age.在外部对类的成员变量的操作,主要包括取值和赋值.简单的取值操作是x=object.var,简单的赋值操作是object.var=value. >>> actress = Actress() >>> actress.name #取值操作 'TianXin' >&g

  • python类装饰器用法实例

    本文实例讲述了python类装饰器用法.分享给大家供大家参考.具体如下: #!coding=utf-8 registry = {} def register(cls): registry[cls.__clsid__] = cls return cls @register class Foo(object): __clsid__ = '123-456' def bar(self): pass print registry 运行结果如下: {'123-456': <class '__main__.F

  • 介绍Python的@property装饰器的用法

    在绑定属性时,如果我们直接把属性暴露出去,虽然写起来很简单,但是,没办法检查参数,导致可以把成绩随便改: s = Student() s.score = 9999 这显然不合逻辑.为了限制score的范围,可以通过一个set_score()方法来设置成绩,再通过一个get_score()来获取成绩,这样,在set_score()方法里,就可以检查参数: class Student(object): def get_score(self): return self._score def set_s

  • Python3.7 新特性之dataclass装饰器

    Python 3.7中一个令人兴奋的新特性是 data classes . 数据类通常是一个主要包含数据的类,尽管实际上没有任何限制. 它是使用新的 @dataclass 装饰器创建的,如下所示: from dataclasses import dataclass @dataclass class DataClassCard: rank: str suit: str 此代码以及本教程中的所有其他示例仅适用于 Python 3.7 及更高版本. 注意: 当然在 Python 3.6 版本也可以使用

  • python3 property装饰器实现原理与用法示例

    本文实例讲述了python3 property装饰器实现原理与用法.分享给大家供大家参考,具体如下: 学习python的同学,慢慢的都会接触到装饰器,装饰器在python里是功能强大的语法.装饰器配合python的魔法方法,能实现很多意想不到的功能.废话不多说,如果你已经掌握了闭包的原理,代码的逻辑还是可以看明白的,咱们直接进入正题. property的意义 @property把一个类的getter方法变成属性,如果还有setter方法,就在setter方法前面加上@method.setter.

随机推荐