• [^] # Re: wrapper et decorateur

    Posté par (site web personnel) . En réponse au message Argument de fonction récurrent. Évalué à 2.

    Bon je revient à la charge avec une solution plus propre qui devrait plaire à pas mal de monde (enfin j'espère) :

    wrapper.py:

    class Wrapper(object):
     def __init__(self, **kwords):
     self.kwords = kwords
     self.functions = {}
     def add_function(self, function):
     self.functions[function.func_name] = function
     def __getattr__(self, functionName):
     try:
     func = self.functions[functionName]
     except KeyError:
     raise AttributeError
     def wrapFunction(*args, **kwords):
     argsNeeded = list(func.func_code.co_varnames)
     argsDict = {}
     for i, arg in enumerate(args):
     argsDict[argsNeeded[i]] = arg
     for key, val in kwords.items():
     if key in argsDict:
     raise TypeError("%s() got multiple values for keyword argument '%s'"%(functionName, key))
     argsDict[key] = val
     for key,val in self.kwords.items():
     if key not in argsDict and key in argsNeeded:
     argsDict[key] = val
     for arg in argsNeeded[:-len(func.func_defaults or [])]:
     if arg not in argsDict:
     raise TypeError("%s() need argument '%s'"%(functionName,arg))
     return func(**argsDict)
     return wrapFunction
    
    

    test.py:

    #!/usr/bin/env python
    from wrapper import Wrapper
    def function1(arg1, arg2, recurrent_arg, default_arg="default"):
     print arg1, arg2, recurrent_arg, default_arg
    def function2(recurrent_arg, another_recurrent_arg):
     print recurrent_arg, another_recurrent_arg
    def function3(arg1, arg2, recurrent_arg):
     wrapper = Wrapper(recurrent_arg=recurrent_arg)
     wrapper.add_function(function1)
     wrapper.add_function(function2)
     print "1 =>",
     function1(arg1,arg2,recurrent_arg)
     print "2 =>",
     wrapper.function1(arg1,arg2,recurrent_arg)
     print "3 =>",
     wrapper.function1(arg1,arg2)
     print "4 =>",
     wrapper.kwords["recurrent_arg"] = 42
     wrapper.function1(arg1,arg2)
     print "5 =>",
     wrapper.kwords["default_arg"] = 3.14
     wrapper.function1(arg1,arg2)
     print "6 =>",
     wrapper.function1(arg1,arg2,3)
     print "7 =>",
     wrapper.function1(arg1, default_arg="cool", arg2=42)
     print "8 =>",
     wrapper.kwords["arg1"]=100
     wrapper.function1(default_arg="cool", arg2=42)
     print "9 =>",
     wrapper.function2(another_recurrent_arg="another")
     print "10 =>",
     wrapper.kwords["another_recurrent_arg"] = "again"
     wrapper.function2()
    function3(1, 2, 3)
    
    

    Ça donne :

    1 => 1 2 3 default
    2 => 1 2 3 default
    3 => 1 2 3 default
    4 => 1 2 42 default
    5 => 1 2 42 3.14
    6 => 1 2 3 3.14
    7 => 1 42 42 cool
    8 => 100 42 42 cool
    9 => 42 another
    10 => 42 again
    
    

    Matthieu Gautier|irc:starmad