2013-04-01 5 views
18

मैं स्थिर कारखाने विधि के वापसी मूल्य के प्रकार को निर्दिष्ट करने के लिए Python function annotations का उपयोग करने जा रहा था। मैं समझता हूं कि एनोटेशन के लिए यह one of the desired use cases है।युक्त श्रेणी का नाम रिटर्न वैल्यू फ़ंक्शन एनोटेशन के रूप में क्यों नहीं पहचाना जाता है?

class Trie: 
    @staticmethod 
    def from_mapping(mapping) -> Trie: 
     # docstrings and initialization ommitted 
     trie = Trie() 
     return trie 

PEP 3107 कहा गया है कि:

समारोह एनोटेशन संकलन समय में आयोजित एक समारोह के विभिन्न भागों के साथ मनमाना अजगर भाव जोड़ का एक तरीका से ज्यादा कुछ नहीं कर रहे हैं।

Trie पायथन में मान्य अभिव्यक्ति है, है ना? अजगर सहमत नहीं है या बल्कि, नाम नहीं मिल सकता है:

def from_mapping(mapping) -> Trie:
NameError: name 'Trie' is not defined

यह ध्यान देने योग्य है कि इस त्रुटि नहीं होता है लायक है अगर एक मौलिक प्रकार (जैसे object या int के रूप में) या एक मानक पुस्तकालय प्रकार (जैसे collections.deque) निर्दिष्ट है।

इस त्रुटि का कारण क्या है और मैं इसे कैसे ठीक कर सकता हूं?

+1

संभावित डुप्लिकेट [मैं कैसे निर्दिष्ट कर सकता है कि एक विधि की वापसी प्रकार वर्ग के रूप में एक ही है खुद पाइथन में?] (https://stackoverflow.com/questions/33533148/how-do-i-specify-that-the-return-type-of-a-method-is-the-same-as-the- कक्षा-उपन्यास) –

उत्तर

10

पीईपी 484 forward references के रूप में इसका आधिकारिक समाधान प्रदान करता है।

एक प्रकार संकेत ऐसे नाम हैं जो अभी तक परिभाषित नहीं किया गया है, तो उस परिभाषा एक स्ट्रिंग शाब्दिक रूप में व्यक्त किया जा सकता है, बाद में हल किया जाना।

प्रश्न कोड के मामले में:

class Trie: 
    @staticmethod 
    def from_mapping(mapping) -> Trie: 
     # docstrings and initialization ommitted 
     trie = Trie() 
     return trie 

बन जाता है:

class Trie: 
    @staticmethod 
    def from_mapping(mapping) -> 'Trie': 
     # docstrings and initialization ommitted 
     trie = Trie() 
     return trie 
की
+0

वाह, मुझे आश्चर्य है कि मुझे याद आया - इस उत्तर में योगदान के लिए धन्यवाद। – Adam

12

Trie एक वैध अभिव्यक्ति है, और नाम नाम Trie से जुड़े वर्तमान मूल्य का मूल्यांकन करता है। लेकिन उस नाम को अभी तक परिभाषित नहीं किया गया है - क्लास ऑब्जेक्ट केवल के बाद इसके नाम से जुड़ा हुआ है, कक्षा का शरीर पूर्ण होने के लिए चला गया है। आप इस बहुत सरल उदाहरण में समान व्यवहार ध्यान दें होगी:

class C: 
    myself = C 
    # or even just 
    C 

आम तौर पर, वैकल्पिक हल वर्ग विशेषता की स्थापना की जाएगी के बाद कक्षा वर्ग शरीर के बाहर, परिभाषित किया गया है। यह वास्तव में एक अच्छा विकल्प नहीं है, हालांकि यह काम करता है। वैकल्पिक रूप से, आप प्रारंभिक परिभाषा में किसी भी प्लेसहोल्डर मूल्य इस्तेमाल कर सकते हैं, तो (जो कानूनी है, क्योंकि यह एक नियमित शब्दकोश है) __annotations__ में इसे बदलना:

class C: 
    def f() -> ...: pass 
print(C.f.__annotations__) 
C.f.__annotations__['return'] = C 
print(C.f.__annotations__) 

यह बल्कि hacky हालांकि महसूस करता है। आपके उपयोग के मामले के आधार पर, इसके बजाय एक सेंटीनल ऑब्जेक्ट (उदा। CONTAINING_CLASS = object()) का उपयोग करना संभव हो सकता है और जो भी वास्तव में एनोटेशन को संसाधित करता है उसे व्याख्या करना छोड़ दें।

+0

दिलचस्प ... हालांकि, मैं कक्षा के नाम * अंदर * मेरी स्थिर विधि का उपयोग कर सकता हूं। ऐसा इसलिए है क्योंकि किसी फ़ंक्शन की सामग्री को निष्पादित होने पर ही पार्स किया जाता है, लेकिन कक्षा परिभाषा के तुरंत बाद हस्ताक्षर को पार्स किया जाता है? रुचि रखने वाले किसी और के लिए पाइथन भाषा संदर्भ के यहां [प्रासंगिक भाग] (http://docs.python.org/3.3/reference/compound_stmts.html#class-definitions) है। – Adam

+2

@codesparkle: पार्सिंग निष्पादन से अलग है। त्रुटि निष्पादन पर होती है। एनोटेशन समेत आपकी कक्षा परिभाषा कोड का निष्पादन है। हालांकि, जब वर्ग परिभाषित किया जाता है तो कार्यों के अंदरूनी भाग निष्पादित नहीं होते हैं (स्पष्ट रूप से)। –

+0

सिर्फ '->' लिखने के बारे में कैसे Trie'' – jamylak

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

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