📕
innohub
  • KEEP LEARNING
  • WebInfo
    • JS 部分运算符操作
    • javascript 中的object array
    • 错误处理以及异常捕获
    • JavaScript Bases
    • LaoZi & Confucius
  • PyInfo
    • Python3 输入与输出
    • Python3OS
    • python 修饰器的使用
    • python3 与mysql数据库连接使用实例
    • Format-specifier
    • CGI初学踩坑
    • Django 项目测试
    • Assert-info
    • 使用ngnix和uWSGI配置Django
    • write|SVN​
    • Matplotlib 基本使用
    • 重读 Python 官方文档
    • Python3 Base
    • python3 多线程
    • Python3 函数解析
    • python3 str 对象的基本操作
    • protocl buffers
    • Iterator-Generator
    • Django base
    • Decorator 2
    • Export to wheel or egg-info
    • 三. 运算、数据及逻辑
  • GoInfo
    • Info
      • Select 语句使用
      • First class function
      • Work Pools
      • StructTag
      • Go struct
      • 常用函数
      • Strings操作
      • Golang Bases
      • 数组以及切片
      • 文件操作
      • Golang 中的指针类型
      • Golang Map 类型
      • Reflection
      • 函数闭包
      • 接口
      • Panic and Recover
      • Go中的错误处理
      • 并发
      • defer usage
      • Method in golang
      • Object-oriented Programming
      • Goalng 包管理机制
  • RustInfo
    • Info
      • 包、crate、模块
      • Rust 中的错误处理
      • 智能指针
      • 泛型 generics
      • 数据布局与内存对齐
      • Functions and methods
      • 无畏并发
      • Actix-web 基本使用
      • Got from guessing game
      • 结构体的使用
      • Rust 中的函数式语言功能
      • 集合类型
      • 枚举以及模式匹配
      • Slice 类型
      • 生命周期
      • 测试
      • Rust 中的所有权
      • trait
      • 不安全 Rust
      • Format_print
      • Rust 通用编程概念
      • Macro
  • OS
    • info
      • 内存屏障 -- Part 1
      • 内存屏障 -- Part 2
      • CPU 上下文切换
      • 文件读写与零拷贝
      • ELF 文件
  • MySql
    • info
      • MySql 架构与历史
      • 02-key
  • kubernetes
    • 第二章 k8s 基本概念
    • 第一章 Kubernetes -- 伟大舵手
  • Redis
    • info
      • Redis 总览
      • 02-underline-ds
  • Shell&CInfo
    • GCC 与make的使用
    • C++ 中 malloc 与 new
    • 位运算符操作
    • Base of C macro
    • C 语言中 extern 关键字的用法
  • Distributed
    • info
      • 分布式理论概述
  • Java
    • info
      • Java 内存模型
  • Prometheus
    • Prometheus -- 不灭之火
Powered by GitBook
On this page
  • 一.万物皆对象
  • 二.函数修饰器的使用 (Function Decorator)
  • 三.类中方法修饰器(Method Decorator)
  • 四. 类装饰器(Class Decorator)
  • 五.多装饰器同时操作 (Chain Decorators)
  • 六.装饰时防止信息丢失
  • 七.向装饰器传递参数

Was this helpful?

  1. PyInfo

python 修饰器的使用

PreviousPython3OSNextpython3 与mysql数据库连接使用实例

Last updated 5 years ago

Was this helpful?

一.万物皆对象

我相信真理,我更相信万物皆对象!

​ -------python

在python中一切都是对象,一个函数可以赋值给一个变量,一个类可以赋值给一个变量.因为函数是普通对象,所以可以作为参数传递,作为另一个函数的返回值

class

以函数作为返回值:

def outer_function():
         print "1. This is outer function!"
         def inner_function():
            print "2. This is inner function, inside outer function!"
         print "3. This is outside inner function, inside outer function!"
         return inner_function()


func_assign = outer_function()

#######################Output######################################
1. This is outer function!
3. This is outside inner function, inside outer function!
2. This is inner function, inside outer function!

二.函数修饰器的使用 (Function Decorator)

python函数修饰符通过连接一个函数对象@decor,在调用一个callable 的函数对象A时将A传入decor中并执行函数,可以嵌套执行

def test(f):  
    print "before ..."  
    f()  
    print "after ..."  

@test  
def func():  
    print "func was called"  

#############################output##################################
#before ...  
#func was called  
#after ...

使用修饰符展现函数运行时间:

#!/usr/bin/python3

import time

def time_count(input_func):

    def timed(*args, **kwargs):
        print('进入修饰器!')
        start = time.time()
        result = input_func(*args, *kwargs)
        end = time.time()

        print('Method name:{0}, Arg:{1}, Kwargs{2}, time:{3:.3f}ms'.format(
            input_func.__name__,
            args,
            kwargs,
            (end-start)*1000))
        return result
    return timed


@time_count
def test(*args, **kwargs):
    #time.sleep(1)
    print('被修饰函数内部')
    print(args, kwargs)


test([56252, 'test'], name='ano', bar=9)

将函数test作为参数传递给time_count() 在修饰器内部,test是参数input,test的参数被传递给timed

三.类中方法修饰器(Method Decorator)

根据一切皆对象的概念,可以将类中的方法作为类的属性进行操作,方法装饰器允许通过装饰来覆盖类属性,而不必查找调用函数。

#!/usr/bin/python3

# 类中方法的修饰符,在不需要找到调用函数时改写类的属性
# python中一切皆对象,可以通过修饰符以函数为参数调用修饰器函数,
# 传入的函数一定是可调用的   callabled  

def method_decor(method):

    def inner(city):
        if city.name == 'LosA':
            print('It\'s a great city!')
        else:
            method(city)

    return inner


class City(object):

    def __init__(self, name):
        self.name = name

    @method_decor
    def print_test(self):
        print(self.name)


c1 = City('LosA')
c1.print_test()
c2 = City('Beijing')
c2.print_test()

####################output#####################################

It's a great city!
Beijing

依旧方法的参数被传入了装饰器的内部函数,而方法本身被作为参数传给装饰器函数,在这种情形下,不需要在类内修改方法即可达到目的

四. 类装饰器(Class Decorator)

如果需要装饰器返回一个对象,并且可以对被装饰的可调用对象添加属性或者进行操作,可以定义一个装饰器类

class decoclass(object):

    def __init__(self, f):
        self.f = f

    def __call__(self, *args, **kwargs):
        # before f actions
        print('decorator initialised')
        self.f(*args, **kwargs)
        print('decorator terminated')
        # after f actions

@decoclass
def klass():
    print('class')

klass()

###############################output#########################
decorator initialised
class
decorator terminated

五.多装饰器同时操作 (Chain Decorators)

@f1(arg)
@f2
def func(): 
    pass
等价于:
def func(): pass
func = f1(arg)(f2(func))

即f1返回值作为函数,参数是f2执行完毕后的返回值,注意最先执行的函数是f2即从下往上执行s

#!/usr/bin/python3
class decoclass(object):

    def __init__(self, f):
        self.f = f

    def __call__(self, *args, **kwargs):
        # before f actions
        print('decorator initialised')
        print('进入装饰器类')
        self.f(*args, **kwargs)
        print('decorator terminated')
        # after f actions


def show(func):
    print('进入装饰器函数')
    def inner(*args, **kwargs):
        print('进入内部函数')
        print('参数为:', args, kwargs)
    return inner  # 必须返回一个函数对象,因为其上层调用是一个装饰器

@decoclass
@show
def klass(*args, *))*kwargs):
    print('class')

klass(1, 2, 'class',[1, 3], name='test', id=1)

输出:

进入装饰器函数

decorator initialised

进入装饰器类

进入内部函数

参数为: (1, 2, 'class', [1, 3]) {'name': 'test', 'id': 1}

decorator terminated

六.装饰时防止信息丢失

如果直接使用装饰器可能导致原方法或者类的属性丢失,如下实例:

#!/usr/bin/python3

def decorator(func):
    """decorator docstring is here!"""
    def inner(*args):
        """inner docstring is here!"""
        print(func.__name__+' was called')
        return func(*args)
    return inner


@decorator
def func(x):
    """Trible times"""
    return x**3

print(func(3))
print(func.__name__)
print(func.__doc__)

输出:

由于func函数在inner中调用,其信息被inner函数的属性覆盖,可以通过functools.wraps 来避免丢失

#!/usr/bin/python3
from functools import wraps

def decorator(func):
    """decorator docstring is here!"""
    @wraps(func)
    def inner(*args):
        """inner docstring is here!"""
        print(func.__name__+' was called')
        return func(*args)
    return inner


@decorator
def func(x):
    """Trible times"""
    return x**3


print(func(3))
print(func.__name__)
print(func.__doc__)
#####################################output###############################
func was called
27
func
Trible times

七.向装饰器传递参数

#!/usr/bin/python3

class Decorator(object):

    def __init__(self, arg1, arg2):
        print('参数传递给装饰器类,分别为:{0} and {1}'.format(arg1, arg2))
        self.arg1 = arg1
        self.arg2 = arg2

    def __call__(self, func,  *args, **kwargs):

        def inner(*args, **kwargs):
            print('参数传递给内部方法:%s and %s' % (self.arg1, self.arg2))
            return func(*args, **kwargs)
        return inner


@Decorator('kobe', 'Brany')
def print_(*args):
    for arg in args:
        print(arg, end='')


print_(1,2,3)


参数传递给装饰器类,分别为:kobe and Brany
参数传递给内部方法:kobe and Brany
123
decor

A function definition may be wrapped by one or more expressions. Decorator expressions are evaluated when the function is defined, in the scope that contains the function definition. The result must be a callable, which is invoked with the function object as the only argument. The returned value is bound to the function name instead of the function object. Multiple decorators are applied in nested fashion. For example, the following code:

wrap
decorator