2013-06-15 7 views
5
from functools import wraps 
def logged(func): 
    @wraps(func) 
    def with_logging(*args, **kwargs): 
     print func.__name__ + " was called" 
     return func(*args, **kwargs) 
    return with_logging 

@logged 
def f(x): 
    """does some math""" 
    return x + x * x 

print f.__name__ # prints 'f' 
print f.__doc__ # prints 'does some math' 

इस नमूना कोड को देखते हुए, मैं @logged(variable) कैसे कर पाऊंगा?पायथन सजावट वैकल्पिक तर्क

मैं इस

from functools import wraps 
def logged(func): 
    def outer(var): 
     @wraps(func) 
     def with_logging(*args, **kwargs): 
      print func.__name__ + " was called" 
      return func(*args, **kwargs) 
     return with_logging 
    return outer 

की कोशिश की मैं इस तरह अमल करने के लिए उम्मीद कर रहा था: लॉग इन (समारोह) (session_variable)

लेकिन काम नहीं करता। कोई विचार? मैं @logged और @logged (var) (या यहां तक ​​कि @logged (var1, var2) करने में सक्षम होना चाहता हूं) धन्यवाद।

उत्तर

11

चाल यहाँ है, तो आप आत्मनिरीक्षण करने के लिए आप क्या दिया जाता है:

# No arguments 
@logged 
def some_function(x): 
    pass 

# One or more arguments 
@logged(1, 2, 3) 
def some_function(x): 
    pass 

# One or more keyword arguments 
@logged(key=1, another_key=2) 
def some_function(x): 
    pass 

# A mix of the two 
@logged(1, 2, key=3) 
def some_function(x): 
    pass 

यह यह है अगर काम नहीं करेगा:

def logged(*setting_args, **setting_kwargs): 
    no_args = False 
    if len(setting_args) == 1 \ 
     and not setting_kwargs \ 
     and callable(setting_args[0]): 
     # We were called without args 
     func = setting_args[0] 
     no_args = True 

    def outer(func): 
     @wraps(func) 
     def with_logging(*args, **kwargs): 
      print "{} was called".format(func.__name__) 
      print "Setting args are: {}".format(setting_args) 
      print "Setting keyword args are: {}".format(setting_kwargs) 
      return func(*args, **kwargs) 
     return with_logging 

    if no_args: 
     return outer(func) 
    else: 
     return outer 

यह निम्न में से किसी के साथ काम करेंगे केवल एक कॉल करने योग्य तर्क के साथ बुलाया जाता है:

# This will break. 
@logged(lambda: "Just for fun") 
def some_function(x): 
    pass 

एन है एक कॉल करने योग्य सेटिंग और सजावटी के नो-एर्ग आमंत्रण के बीच अंतर बताने का तरीका। हालांकि, अगर आप के आसपास पाने के लिए भी है कि अगर आप की जरूरत है एक कचरा कीवर्ड आर्ग पारित कर सकते हैं:

# This gets around the above limitation 
@logged(lambda: "Just for fun", ignored=True) 
def some_function(x): 
    pass 
+0

धन्यवाद। मैंने बहुत कुछ सीखा। – user423455

+0

उत्कृष्ट, धन्यवाद। इससे मुझे 'आवश्यक_परैम्स()' सजावट को लागू करने में मदद मिली। – Jason

0

जावक def outer(var) शब्दों में कहें, कि

def outer(var): 
    def logged(func): 
     ... 

, तो अपने समारोह के लिए @outer(somevar) उपयोग करते हैं, यह काम होता है।

0

वहाँ कोड आप की कोशिश की में मामूली त्रुटि है। func>var>*args, **kwargs के रूप में तर्कों के साथ नेस्टेड फ़ंक्शंस बनाने के बजाय, ऑर्डर var>func>*args, **kwargs होना चाहिए।

नीचे कोड स्निपेट है जो आपकी आवश्यकता के अनुरूप होगा। , और अधिक कैसे सज्जाकार काम पर

@logged 
def func1(): 
    ... 

या,

@logged(xyz) 
def func2(): 
    ... 

पता करने के लिए लेख Decorators with optional arguments देखें:

from functools import wraps 

def logged(var=None): 
    def outer(func): 
     @wraps(func) 
     def with_logging(*args, **kwargs): 
      print func.__name__ + " was called" 
      return func(*args, **kwargs) 
     return with_logging 
    return outer 

आप के रूप में इस डेकोरेटर कह सकते हैं।

0

शॉन विएरा के लिए एक संभावित विकल्प के समाधान हो सकता है:

from functools import wraps 
import inspect 


def decorator_defaults(**defined_defaults): 
    def decorator(f): 
     args_names = inspect.getargspec(f)[0] 

     def wrapper(*new_args, **new_kwargs): 
      defaults = dict(defined_defaults, **new_kwargs) 
      if len(new_args) == 0: 
       return f(**defaults) 
      elif len(new_args) == 1 and callable(new_args[0]): 
       return f(**defaults)(new_args[0]) 
      else: 
       too_many_args = False 
       if len(new_args) > len(args_names): 
        too_many_args = True 
       else: 
        for i in range(len(new_args)): 
         arg = new_args[i] 
         arg_name = args_names[i] 
         defaults[arg_name] = arg 
       if len(defaults) > len(args_names): 
        too_many_args = True 
       if not too_many_args: 
        final_defaults = [] 
        for name in args_names: 
         final_defaults.append(defaults[name]) 
        return f(*final_defaults) 
       if too_many_args: 
        raise TypeError("{0}() takes {1} argument(s) " 
            "but {2} were given". 
            format(f.__name__, 
              len(args_names), 
              len(defaults))) 
     return wrapper 
    return decorator 


@decorator_defaults(start_val="-=[", end_val="]=-") 
def my_text_decorator(start_val, end_val): 
    def decorator(f): 
     @wraps(f) 
     def wrapper(*args, **kwargs): 
      return "".join([f.__name__, ' ', start_val, 
          f(*args, **kwargs), end_val]) 
     return wrapper 
    return decorator 


@decorator_defaults(end_val="]=-") 
def my_text_decorator2(start_val, end_val): 
    def decorator(f): 
     @wraps(f) 
     def wrapper(*args, **kwargs): 
      return "".join([f.__name__, ' ', start_val, 
          f(*args, **kwargs), end_val]) 
     return wrapper 
    return decorator 


@my_text_decorator 
def func1a(value): 
    return value 


@my_text_decorator() 
def func2a(value): 
    return value 


@my_text_decorator2("-=[") 
def func2b(value): 
    return value 


@my_text_decorator(end_val=" ...") 
def func3a(value): 
    return value 


@my_text_decorator2("-=[", end_val=" ...") 
def func3b(value): 
    return value 


@my_text_decorator("|> ", " <|") 
def func4a(value): 
    return value 


@my_text_decorator2("|> ", " <|") 
def func4b(value): 
    return value 


@my_text_decorator(end_val=" ...", start_val="|> ") 
def func5a(value): 
    return value 


@my_text_decorator2("|> ", end_val=" ...") 
def func5b(value): 
    return value 


print(func1a('My sample text')) # func1a -=[My sample text]=- 
print(func2a('My sample text')) # func2a -=[My sample text]=- 
print(func2b('My sample text')) # func2b -=[My sample text]=- 
print(func3a('My sample text')) # func3a -=[My sample text ... 
print(func3b('My sample text')) # func3b -=[My sample text ... 
print(func4a('My sample text')) # func4a |> My sample text <| 
print(func4b('My sample text')) # func4b |> My sample text <| 
print(func5a('My sample text')) # func5a |> My sample text ... 
print(func5b('My sample text')) # func5b |> My sample text ... 

नोट: यह एक ही दोष यह है जहाँ आप डेकोरेटर करने के लिए समारोह के रूप में 1 तर्क पारित नहीं हो सकता है, लेकिन आप एक से अधिक सज्जाकार पर इस कार्यक्षमता चाहते हैं आप कोड बॉयलरप्लेट से बच सकते हैं।

संबंधित मुद्दे