python-アクセサリーの書き方と定義


python装飾器
コードの実行中に動的に機能を追加する方式を「デコレータ」(Decorator)と呼ぶ.私の理解は、定義された関数にいくつかの機能を追加するが、関数の元の定義を変更しないことです.オブジェクト向けインタフェースの実装と少し似ているが、装飾器はインタフェースに相当し、以下の具体的な関数はそのインタフェースの実装である.装飾器の本質は高次関数であり、装飾を必要とする関数が伝わる.
使用法
# demo.py
def printFuncName(func):
    def wrapper(*args, **kw):
        print(func.__name__)
        return func(*args, **kw)
    return wrapper

@printFunName
def person(name, age, **kw):
    print('name:', name, 'age:', age, 'other:', kw)
    
#  
>>> from demo import person
>>> person(1,2)
person
name: 1 age: 2 other: {}

上のprintFuncNameは装飾器であり、personが呼び出される前に関数を改造し、funcは関数体であり、(*args,**kw)は伝達関数のパラメータであるため、func.__name__は関数得名personであり、装飾器の役割は以下の通りである.
person = printFuncName(person)

しかし問題が発生しました
>>> person.__name__
'wrapper'
personの内部の本当の関数名とwrapperになったので、Python内蔵の装飾器functools.wrapswrapperの属性と元の関数の属性を統一することができます.
#demo.py

import functools

def printName(func):
    @functools.wraps(func)
    def wrapper(*args, **kw):
        print(func.__name__)
        return func(*args, **kw)
    return wrapper

@printName
def person(name, age, **kw):
    print('name:', name, 'age:', age, 'other:', kw)
    
#  
>>> from demo import person
>>> person.__name__
'person'


ダイナミックな装飾器が必要な場合は、装飾器にパラメータを入力する必要があります.そのため、元の装飾器の外側にパラメータを入力するための関数をネストする必要があります.これが最も完全な装飾器です.
#demo.py

import functools
def printName(text):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kw):
            print('%s:%s' % (text, func.__name__)) #     
            return func(*args, **kw)
        return wrapper
    return decorator

@printName('     ')
def person(name, age, **kw):
    print('name:', name, 'age:', age, 'other:', kw)
    
#  
>>> from demo import person
>>> person(1,2)
     :person
name: 1 age: 2 other: {}