2012-08-14 16 views
7

अपडेट करने के लिए सजावटी का उपयोग करने में त्रुटि आई है, मुझे फ़ंक्शन के रैपर को अपडेट करने के लिए सजावट का उपयोग करने के दौरान त्रुटि संदेश (कम से कम मेरे लिए) त्रुटि संदेश का सामना करना पड़ा है। कोई विचार है कि मैं इसका समाधान कैसे कर सकता हूं?रैपर

मैंने अपना कोड यथासंभव सामान्य बनाने की कोशिश की है, इसलिए यह अन्य स्थितियों पर भी लागू होगी।

def decorator(d): 
    """Make function d a decorator: d wraps a function fn.""" 

    def _d(fn): 
     return functools.update_wrapper(d(fn), fn) 
    functools.update_wrapper(_d, d) 
    return _d 


@decorator 
def f(fn): 
    """Converts the string fn to a function and returns it. 
    Because of the @decorator decorator, _f.__name__ should 
    be identical to f.__name__""" 

    f.__name__ = fn 
    def _f(fn): 
     return eval(fn) 
    return _f 

g = f('x**2') 
print g.__name__ 

वांछित उत्पादन:

>>>x**2 

वास्तविक उत्पादन:

Traceback (most recent call last): 
    File "C:\python\swampy-2.0\testcode.py", line 18, in <module> 
    g = f('x**2') 
    File "C:\python\swampy-2.0\testcode.py", line 6, in _d 
    return functools.update_wrapper(d(fn), fn) 
    File "C:\Python27\lib\functools.py", line 33, in update_wrapper 
    setattr(wrapper, attr, getattr(wrapped, attr)) 
AttributeError: 'str' object has no attribute '__module__' 

उत्तर

5

एक डेकोरेटर एक तर्क के रूप में एक समारोह लेता है और एक और "सजाया" फ़ंक्शन। आप एक स्ट्रिंग पास कर रहे हैं और एक फ़ंक्शन वापस करने का प्रयास कर रहे हैं जो वास्तव में फ़ंक्शन फ़ैक्टरी है। functools.wraps और functools.update_wrapper एक फ़ंक्शन की अपेक्षा करते हैं। एक फ़ंक्शन ऑब्जेक्ट में __module__ विशेषता होगी जबकि str के उदाहरण __module__ विशेषता नहीं है।

क्या आप "x ** 2" स्ट्रिंग से कोई फ़ंक्शन जेनरेट करना चाहते हैं?

decorator का आपका कार्यान्वयन अनावश्यक है। बस functools.wraps का उपयोग करें:

def f(fn): 
    """Converts the string fn to a function and returns it.""" 
    @functools.wraps(fn) 
    def _f(fn): 
     return eval(fn) 
    return _f 

हालांकि, अगर आप नहीं इस मामले में एक डेकोरेटर लेकिन एक समारोह कारखाने चाहते हैं।

def factory(exp): 
    def f(**kwargs): 
     return eval(exp, globals(), kwargs) 
    f.__name__ = exp 
    return f 

अब आप इस तरह इस का उपयोग कर सकते हैं:

>>> x_squared = factory("x**2") 
>>> x_squared(x=7) 
49 

चेतावनी: सर्जन जनरल निर्धारित किया है कि eval आपका स्वास्थ्य के लिए खतरनाक है

+0

प्रतिक्रिया के लिए धन्यवाद! हां, मुझे अच्छी तरह से पता है कि अत्यधिक सावधानी के साथ eval का उपयोग किया जाना चाहिए :) इस मामले में, मुझे लगता है कि मैं इसके साथ रहना चाहता हूं। इस विशेष उदाहरण में, यह महत्वपूर्ण है कि मैं _f .__ name___ में विस्तार भी संग्रहीत करता हूं। ऐसा लगता है कि इनमें से कोई भी समाधान उस आवश्यकता के लिए प्रदान नहीं करता है। –

+1

ओह, आप 'f .__ name__' सेट कर सकते हैं। मुझे अपना जवाब अपडेट करने दें। – stderr

+0

इस उदाहरण में, वास्तव में क्या _f() वास्तव में मेरी मुख्य चिंता नहीं है (मुझे अपने प्रश्न में यह स्पष्ट होना चाहिए था)। मैं मुख्य रूप से एक सजावटी का उपयोग कर फ़ंक्शन रैपर को अपडेट करने के लिए चिंतित हूं। –

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