Maison développement back-end Tutoriel Python Python中的多重装饰器

Python中的多重装饰器

Jun 10, 2016 pm 03:15 PM
python

多重装饰器,即多个装饰器修饰同一个对象【实际上并非完全如此,且看下文详解】

1.装饰器无参数:

复制代码 代码如下:

>>> def first(func):
    print '%s() was post to first()'%func.func_name
    def _first(*args,**kw):
        print 'Call the function %s() in _first().'%func.func_name
        return func(*args,**kw)
    return _first


>>> def second(func):
    print '%s() was post to second()'%func.func_name
    def _second(*args,**kw):
        print 'Call the function %s() in _second().'%func.func_name
        return func(*args,**kw)
    return _second


>>> @first
@second
def test():return 'hello world'

test() was post to second()
_second() was post to first()
>>> test()
Call the function _second() in _first().
Call the function test() in _second().
'hello world'
>>>

实际上它是相当于下面的代码:

复制代码 代码如下:

>>> def test():
    return 'hello world'

>>> test=second(test)
test() was post to second()
>>> test

>>> test=first(test)
_second() was post to first()
>>> test

>>> test()
Call the function _second() in _first().
Call the function test() in _second().
'hello world'
>>>


2.装饰器有参数:
复制代码 代码如下:

>>> def first(printResult=False):
    def _first(func):
        print '%s() was post to _first()'%func.func_name
        def __first(*args,**kw):
            print 'Call the function %s() in __first().'%\
                  func.func_name
            if printResult:
                print func(*args,**kw),'#print in __first().'
            else:
                return func(*args,**kw)
        return __first
    return _first

>>> def second(printResult=False):
    def _second(func):
        print '%s() was post to _second()'%func.func_name
        def __second(*args,**kw):
            print 'Call the function %s() in __second().'%\
                  func.func_name
            if printResult:
                print func(*args,**kw),'#print in __second().'
            else:
                return func(*args,**kw)
        return __second
    return _second

>>> @first(True)
@second(True)
def test():
    return 'hello world'

test() was post to _second()
__second() was post to _first()
>>> test()
Call the function __second() in __first().
Call the function test() in __second().
hello world #print in __second().
None #print in __first().
>>>

如上,第35行输出后调用__second(),而__second()中又调用了test()并print test(),而后返回__first()中继续执行print,而这个print语句print的内容是__second()返回的None

它等同于:

复制代码 代码如下:

>>> def test():
    return 'hello world'

>>> test=second(True)(test)
test() was post to _second()
>>>
>>> test

>>> test=first(True)(test)
__second() was post to _first()
>>> test

>>>


3.多重装饰器的应用:

比如你是项目经理,你要求每一个代码块都必须有参数检查ArgsType和责任检查ResponsibilityRegister,这样就需要两个装饰器对此代码块进行监督。

复制代码 代码如下:

#coding=utf-8
import os,sys,re
from collections import OrderedDict

def ArgsType(*argTypes,**kwTypes):
    u'''ArgsType(*argTypes,**kwTypes)
    options=[('opt_UseTypeOfDefaultValue',False)]

    以下为本函数相关的开关,并非类型检验相关的关键字参数,所有options:
    opt_UseTypeOfDefaultValue=>bool:False,为True时,将对没有指定类型的带默
                               认值的参数使用其默认值的类型
    '''
    def _ArgsType(func):
        #确定所有的parameter name
        argNames=func.func_code.co_varnames[:func.func_code.co_argcount]
        #确定所有的default parameter
        defaults=func.func_defaults
        if defaults:
            defaults=dict(zip(argNames[-len(defaults):],defaults))
        else:defaults=None
        #将“参数类型关键字参数”中的所有“options关键字参数”提出
        options=dict()
        for option,default in [('opt_UseTypeOfDefaultValue',False)]:
            options[option]=kwTypes.pop(option,default)
        #argTypes和kwTypes的总长度应该与argNames一致
        if len(argTypes)+len(kwTypes)>len(argNames):
            raise Exception('Too much types to check %s().'%func.func_name)
        #所有kwTypes中的键不能覆盖在argTypes中已经占用的names
        if not set(argNames[len(argTypes):]).issuperset(
            set(kwTypes.keys())):
            raise Exception('There is some key in kwTypes '+
                'which is not in argNames.')
        #确定所有的参数应该有的types
        types=OrderedDict()
        for name in argNames:types[name]=None
        if len(argTypes):
            for i in range(len(argTypes)):
                name=argNames[i]
                types[name]=argTypes[i]
        else:
            for name,t in kwTypes.items():
                types[name]=t
        if len(kwTypes):
            for name,t in kwTypes.items():
                types[name]=t
        #关于default parameter的type
        if options['opt_UseTypeOfDefaultValue']:
            for k,v in defaults.items():
                #如果default parameter的type没有另外指定,那么就使用
                #default parameter的default value的type
                if types[k]==None:
                    types[k]=type(v)
        def __ArgsType(*args,**kw):
            #order the args
            Args=OrderedDict()
            #init keys
            for name in argNames:Args[name]=None
            #init default values
            if defaults is not None:
                for k,v in defaults.items():
                    Args[k]=v
            #fill in all args
            for i in range(len(args)):
                Args[argNames[i]]=args[i]
            #fill in all keyword args
            for k,v in kw.items():
                Args[k]=v
            #check if there is some None in the values
            if defaults==None:
                for k in Args:
                    if Args[k]==None:
                        if defaults==None:
                            raise Exception(('%s() needs %r parameter, '+
                                'which was not given')%(func.func_name,k))
                        else:
                           if not defaults.has_key(k):
                                raise Exception(('Parameter %r of %s() is'+
                                    ' not a default parameter')%\
                                    (k,func.func_name))
            #check all types
            for k in Args:
                if not isinstance(Args[k],types[k]):
                    raise TypeError(('Parameter %r of %s() must be '+
                        'a %r object, but you post: %r')%\
                        (k,func.func_name,types[k],Args[k]))
            return func(*args,**kw)
        return __ArgsType
    return _ArgsType

def ResponsibilityRegister(author):
    def _ResponsibilityRegister(func):
        def __ResponsibilityRegister(*args,**kw):
            try:
                return func(*args,**kw)
            except Exception as e:
                print ("Something is wrong, It's %s's responsibility."%\
                       author).center(80,'*')
                raise e
        return __ResponsibilityRegister
    return _ResponsibilityRegister

@ResponsibilityRegister('Kate')
@ArgsType(str,int)
def left(Str,Len=1):
    return Str[:Len]

print 'Good calling:'
print left('hello world',8)
print 'Bad calling:'
print left(3,7)

这里没有文档,所以调用者不知道,使用了错误的调用,导致出错,这是Kate的责任。

像上面这种,对代码有两种互不相干的检验时,就可以使用多重装饰器。

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

Video Face Swap

Video Face Swap

Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Article chaud

<🎜>: Dead Rails - Comment apprivoiser les loups
4 Il y a quelques semaines By DDD
<🎜>: Grow A Garden - Guide de mutation complet
2 Il y a quelques semaines By DDD
Niveaux de force pour chaque ennemi et monstre de R.E.P.O.
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Sujets chauds

Tutoriel Java
1659
14
Tutoriel PHP
1258
29
Tutoriel C#
1232
24
PHP et Python: différents paradigmes expliqués PHP et Python: différents paradigmes expliqués Apr 18, 2025 am 12:26 AM

PHP est principalement la programmation procédurale, mais prend également en charge la programmation orientée objet (POO); Python prend en charge une variété de paradigmes, y compris la POO, la programmation fonctionnelle et procédurale. PHP convient au développement Web, et Python convient à une variété d'applications telles que l'analyse des données et l'apprentissage automatique.

Choisir entre PHP et Python: un guide Choisir entre PHP et Python: un guide Apr 18, 2025 am 12:24 AM

PHP convient au développement Web et au prototypage rapide, et Python convient à la science des données et à l'apprentissage automatique. 1.Php est utilisé pour le développement Web dynamique, avec une syntaxe simple et adapté pour un développement rapide. 2. Python a une syntaxe concise, convient à plusieurs champs et a un écosystème de bibliothèque solide.

PHP et Python: une plongée profonde dans leur histoire PHP et Python: une plongée profonde dans leur histoire Apr 18, 2025 am 12:25 AM

PHP est originaire en 1994 et a été développé par Rasmuslerdorf. Il a été utilisé à l'origine pour suivre les visiteurs du site Web et a progressivement évolué en un langage de script côté serveur et a été largement utilisé dans le développement Web. Python a été développé par Guidovan Rossum à la fin des années 1980 et a été publié pour la première fois en 1991. Il met l'accent sur la lisibilité et la simplicité du code, et convient à l'informatique scientifique, à l'analyse des données et à d'autres domaines.

Python vs JavaScript: la courbe d'apprentissage et la facilité d'utilisation Python vs JavaScript: la courbe d'apprentissage et la facilité d'utilisation Apr 16, 2025 am 12:12 AM

Python convient plus aux débutants, avec une courbe d'apprentissage en douceur et une syntaxe concise; JavaScript convient au développement frontal, avec une courbe d'apprentissage abrupte et une syntaxe flexible. 1. La syntaxe Python est intuitive et adaptée à la science des données et au développement back-end. 2. JavaScript est flexible et largement utilisé dans la programmation frontale et côté serveur.

Comment exécuter le code sublime python Comment exécuter le code sublime python Apr 16, 2025 am 08:48 AM

Pour exécuter le code Python dans le texte sublime, vous devez d'abord installer le plug-in Python, puis créer un fichier .py et écrire le code, et enfin appuyez sur Ctrl B pour exécuter le code, et la sortie sera affichée dans la console.

Où écrire du code dans vscode Où écrire du code dans vscode Apr 15, 2025 pm 09:54 PM

L'écriture de code dans Visual Studio Code (VSCODE) est simple et facile à utiliser. Installez simplement VScode, créez un projet, sélectionnez une langue, créez un fichier, écrivez du code, enregistrez-le et exécutez-le. Les avantages de VSCOD incluent la plate-forme multiplateuse, gratuite et open source, des fonctionnalités puissantes, des extensions riches et des poids légers et rapides.

Le code Visual Studio peut-il être utilisé dans Python Le code Visual Studio peut-il être utilisé dans Python Apr 15, 2025 pm 08:18 PM

VS Code peut être utilisé pour écrire Python et fournit de nombreuses fonctionnalités qui en font un outil idéal pour développer des applications Python. Il permet aux utilisateurs de: installer des extensions Python pour obtenir des fonctions telles que la réalisation du code, la mise en évidence de la syntaxe et le débogage. Utilisez le débogueur pour suivre le code étape par étape, trouver et corriger les erreurs. Intégrez Git pour le contrôle de version. Utilisez des outils de mise en forme de code pour maintenir la cohérence du code. Utilisez l'outil de liaison pour repérer les problèmes potentiels à l'avance.

Comment exécuter Python avec le bloc-notes Comment exécuter Python avec le bloc-notes Apr 16, 2025 pm 07:33 PM

L'exécution du code Python dans le bloc-notes nécessite l'installation du plug-in exécutable Python et du plug-in NPEXEC. Après avoir installé Python et ajouté un chemin à lui, configurez la commande "python" et le paramètre "{current_directory} {file_name}" dans le plug-in nppexec pour exécuter le code python via la touche de raccourci "F6" dans le bloc-notes.

See all articles