2015-09-14 11 views
5

मैंने यहां एक उत्तर खोजने की कोशिश की, लेकिन नहीं कर सका।पायथन सजावट @func()। विशेषता वाक्यविन्यास त्रुटि

@obj.funC# works 
@obj.func(**kwargs) #works 
@obj.func1(**kwargs).func2 #-> syntax error 

मुझे समझ नहीं आता क्यों तीसरा रूप एक सिंटैक्स त्रुटि है, यह मेरे लिए है कि किसी भी अजगर वाक्य रचना का उल्लंघन नहीं कर रहा है और यह मेरे लिए स्पष्ट उपयोगकर्ता क्या करना चाहते हैं क्या है लगता है (नीचे उदाहरण देखें)।

मैंने सजावटी कार्यान्वयन के pep 0318 पर देखा लेकिन मुझे कोई जवाब नहीं मिला।

यहाँ bellow, उपयोग का एक उदाहरण होगा:

class ItemFunc(object): 
    def __init__(self, fcall=None, **kwargs): 
     self.defaults = kwargs 
     self.fcall = None 

    def __call__(self, *args, **kwargs): 
     kwargs = dict(self.defaults, **kwargs) 
     # do something more complex with kwargs 
     output = self.fcall(*args, **kwargs) 
     # do something more with output 
     return output 

    def caller(self, fcall): 
     """ set call and return self """ 
     self.call = fcall # after some check obviously 
     return self 

    def copy(self,**kwargs): 
     kwargs = dict(self.defaults, **kwargs) 
     return self.__class__(self.fcall, **kwargs) 

    def copy_and_decorate(self, **kwargs): 
     return self.copy(**kwargs).caller 

से आप एक डेकोरेटर के रूप में ItemFunc उपयोग कर सकते हैं:

@ItemFunc 
def plot(**kwargs): 
    pass 

redcross = plot.copy(color="red", marker="+") 
@redcross.caller 
def plot_data1(**kwargs): 
    pass 

bluecross = redcross.copy(color="blue") 
@bluecross.caller 
def plot_data2(**kwargs): 
    pass 

लेकिन क्यों यह निम्नलिखित 'शॉर्टकट वाक्य रचना' मना किया है:

@redcross.copy(color="blue").caller 
def plot_data2(**kwargs): 
    pass 

लेकिन मैं कर सकता हूं:

@redcross.copy_and_decorate(color="blue") 
def plot_data2(**kwargs): 
    pass   

पहला फॉर्म अच्छा लगता है, कम से कम मैं पीछे के इरादे को बेहतर समझता हूं।

उत्तर

6

Function definitions grammar आगे बिंदीदार नामों के साथ कॉल की अनुमति नहीं देता है; वाक्य रचना अंत पर डॉटेड नाम और एक वैकल्पिक कॉल तक ही सीमित है:

decorated  ::= decorators (classdef | funcdef) 
decorators  ::= decorator+ 
decorator  ::= "@" dotted_name ["(" [argument_list [","]] ")"] NEWLINE 
funcdef  ::= "def" funcname "(" [parameter_list] ")" ":" suite 
dotted_name ::= identifier ("." identifier)* 

ध्यान दें कि कि नहीं एक पूर्ण अभिव्यक्ति है, लेकिन एक बहुत ही सीमित सबसेट है। - मनमाना भाव से काम नहीं चलेगा

डेकोरेटर बयान क्या इसे स्वीकार कर सकते में सीमित है:

यह पीईपी, जिसमें कहा गया है की प्रतिध्वनि है। गिटो ने इसे आंत महसूस करने के कारण पसंद किया [17]।

और

एक समारोह है कि रिटर्न एक डेकोरेटर जो @ चिह्न के बाद वाले हिस्से एक अभिव्यक्ति होने के लिए विचार किया जा सकता है कर रहा है (हालांकि वाक्य रचना प्रतिबंधित करने के लिए सिर्फ एक समारोह) के लिए तर्क, और जो अभिव्यक्ति रिटर्न देता है उसे बुलाया जाता है। घोषणा तर्क देखें [16]।

जोर मेरा।

इसलिए जब यह काफी आसान होगा वाक्य रचना भविष्य में @test को बदलने के लिए, मैं जब तक कोई वास्तविक अधिक सीमित फार्म के साथ रहना चाहते हैं:

तर्क यह है कि Guido feels there isn't a real use case for allowing more है केस का इस्तेमाल प्रस्तुत किया जाता है जहां @test को पठनीयता में वृद्धि होगी। (@foo()। बार() गिनती नहीं है क्योंकि मुझे उम्मीद नहीं है कि आपको कभी भी की आवश्यकता होगी)।

आपको गिडो और अन्य मूल डेवलपर्स को मनाने की आवश्यकता होगी कि आपका मामला इन प्रतिबंधों को उठाने के योग्य उचित उपयोगकाज है!

+0

हाँ, यह एक दार्शनिक समस्या है। मेरे लिए .getter या .caller (जैसे कि मेरे उदाहरण में) के साथ सजावटी को खत्म करना मेरे लिए यह स्पष्ट करता है कि हम क्या करना चाहते हैं, अंत में एक फ़ंक्शन को कॉल करते समय एक कॉलर विधि (मेरा उदाहरण दोबारा) भेज दिया जाता है लेकिन कम पठनीय। क्या आपको नहीं लगता? – user3240484

+0

@ user3240484: मैं देख सकता हूं कि आप अपने सेटअप के साथ कहां जा रहे हैं; लेकिन शायद एक विशेषता का उपयोग करने के बजाय, '__call__' वास्तविक सजावट वापस लौटाता है, जो कुछ '__call__' का समर्थन करता है? –

+0

आप सही हैं, लेकिन यदि आप मेरे उदाहरण को देखते हैं तो __call__ विधि ऑब्जेक्ट फ़ंक्शन-जैसी उपयोगकर्ताओं को रखने के लिए पहले से ही 'fcall' funtion के सजावट की तरह कार्य करती है। मैं एक कॉल फ़ंक्शन द्वारा __call__ को प्रतिस्थापित कर सकता हूं और सजावटी को वापस करने के लिए __call__ का उपयोग कर सकता हूं, लेकिन मैं वहां क्या हासिल करता हूं, मैंने इसे वहां खोला। धन्यवाद – user3240484

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