2016-09-28 9 views
14

मैं अपनी विशाल कक्षा को दो में विभाजित करने की कोशिश कर रहा हूं; अच्छी तरह से, मूल रूप से "मुख्य" वर्ग और इतने की तरह अतिरिक्त कार्य, के साथ एक mixin में:पाइथन प्रकार बिना चक्रीय आयात के संकेत

# main.py 
import mymixin.py 

class Main(object, MyMixin): 
    def func1(self, xxx): 
     ... 


# mymixin.py 
class MyMixin(object): 
    def func2(self: Main, xxx): # <--- note the type hint 
     ... 

अब, जबकि यह सिर्फ ठीक काम करता है, निश्चित रूप से MyMixin.func2 में टाइप संकेत काम नहीं कर सकता। मैं main.py आयात नहीं कर सकता, क्योंकि मुझे एक चक्रीय आयात मिलेगा और संकेत के बिना, मेरा संपादक (PyCharm) यह नहीं बता सकता कि self क्या है।

पायथन 3.4 का उपयोग करके, यदि समाधान उपलब्ध हो तो 3.5 तक जाने के इच्छुक हैं।

क्या कोई तरीका है कि मैं अपनी कक्षा को दो फाइलों में विभाजित कर सकता हूं और सभी "कनेक्शन" रख सकता हूं ताकि मेरा आईडीई अभी भी मुझे स्वत: पूर्णता प्रदान कर सके & अन्य सभी उपहार जो इस प्रकार से जानते हैं?

+0

मुझे नहीं लगता कि आपको आमतौर पर 'स्वयं' के प्रकार को एनोटेट करने की आवश्यकता होनी चाहिए, क्योंकि यह हमेशा मौजूदा वर्ग का उप-वर्ग बनने वाला होता है (और किसी भी प्रकार की जांच प्रणाली इसे समझने में सक्षम होना चाहिए खुद)। क्या 'func2'' func1' को कॉल करने का प्रयास कर रहा है, जिसे 'MyMixin' में परिभाषित नहीं किया गया है? शायद यह होना चाहिए (शायद 'सार तत्व' के रूप में, शायद? – Blckknght

उत्तर

24

वहाँ सामान्य रूप में आयात चक्र को संभालने के लिए एक बेहद खूबसूरत तरीका नहीं है , मुझे डर लग रहा है। आपके विकल्प या तो चक्रीय निर्भरता को निकालना अपने कोड नया स्वरूप हैं, या अगर यह संभव नहीं है, कुछ इस तरह करते हैं:

# some_file.py 

from typing import TYPE_CHECKING 
if TYPE_CHECKING: 
    from main import Main 

class MyObject(object): 
    def func2(self, some_param: 'Main'): 
     ... 

TYPE_CHECKING लगातार क्रम में हमेशा False है, इसलिए आयात नहीं किया जाएगा मूल्यांकन किया गया, लेकिन mypy (और अन्य प्रकार-जांच उपकरण) उस ब्लॉक की सामग्री का मूल्यांकन करेंगे।

हमें Main एक स्ट्रिंग में एनोटेशन टाइप करने की भी आवश्यकता है, Main प्रतीक रनटाइम पर उपलब्ध नहीं है क्योंकि इसे प्रभावी रूप से घोषित करना है।

जो कुछ भी कहा गया है, मैपी के साथ मिश्रित मिश्रणों के लिए आपको वर्तमान में कुछ और संरचना की आवश्यकता होगी। Mypy recommends an approach मूल रूप से deceze वर्णन कर रहा है - एक एबीसी बनाने के लिए कि आपके Main और MyMixin कक्षाएं उत्तराधिकारी हैं। अगर आपको पिचर्म के चेकर को खुश करने के लिए कुछ ऐसा करने की ज़रूरत है तो मुझे आश्चर्य नहीं होगा।

+1

इसके लिए धन्यवाद। मेरे वर्तमान पायथन 3.4 में 'टाइपिंग' नहीं है, लेकिन PyCharm 'झूठी:' के साथ भी बहुत खुश था। – velis

+0

एकमात्र समस्या यह है कि यह मायऑब्जेक्ट को Django मॉडल के रूप में नहीं पहचानता है। मॉडल और इस प्रकार उदाहरण के गुणों को '__init__' के बाहर परिभाषित किया जा रहा है – velis

6

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

ठीक से समझदार टाइपिंग के साथ ऐसा करने के लिए, MyMixin एक इंटरफ़ेस, या अमूर्त वर्ग अजगर की भाषा में के खिलाफ कोडित किया जाना चाहिए:

import abc 


class MixinDependencyInterface(abc.ABC): 
    @abc.abstractmethod 
    def foo(self): 
     pass 


class MyMixin: 
    def func2(self: MixinDependencyInterface, xxx): 
     self.foo() # ← mixin only depends on the interface 


class Main(MixinDependencyInterface, MyMixin): 
    def foo(self): 
     print('bar') 
+0

ठीक है, मैं नहीं कह रहा हूं कि मेरा समाधान बहुत अच्छा है। कोड को और अधिक प्रबंधनीय बनाने के लिए मैं बस यही करने का प्रयास कर रहा हूं। आपका सुझाव पास हो सकता है, लेकिन इसका मतलब यह होगा कि पूरे मुख्य वर्ग को मेरे __specific__ मामले में इंटरफेस में ले जाया जा रहा है। – velis

1

तुम हमेशा के नाम के बजाय संकुल आयात कर सकते हैं:

# main.py 
import mymixin 

class Main(object, mymixin.MyMixin): 
    def func1(self, xxx): 
     ... 

 

# mymixin.py 
import main 

class MyMixin(object): 
    def func2(self: main.Main, xxx): 
     ... 

यह मदद से आप चक्रीय निर्भरता समस्या से बचने के।

0

मेरा मूल प्रयास समाधान के काफी करीब था।

# main.py 
import mymixin.py 

class Main(object, MyMixin): 
    def func1(self, xxx): 
     ... 


# mymixin.py 
if False: 
    from main import Main 

class MyMixin(object): 
    def func2(self: 'Main', xxx): # <--- note the type hint 
     ... 

नोट if False बयान है कि आयात होता है कभी नहीं (लेकिन आईडीई इसके बारे में वैसे भी जानता है) के भीतर आयात और क्योंकि यह क्रम में ज्ञात नहीं है स्ट्रिंग के रूप में Main वर्ग का उपयोग कर: यह मैं वर्तमान में क्या उपयोग कर रहा हूँ है।

0

मुझे लगता है कि फ़ाइल में सभी वर्गों और निर्भरताओं को आयात करने का सही तरीका होना चाहिए (जैसे __init__.py) और फिर from __init__ import * अन्य सभी फ़ाइलों में।

इस मामले में आप

  1. उन फ़ाइलों और वर्गों और करने के लिए कई संदर्भ से परहेज कर रहे हैं
  2. भी केवल
  3. तीसरे pycharm होगा अन्य फ़ाइलों में से प्रत्येक और में एक लाइन जोड़ने के लिए उन सभी वर्गों के बारे में जानना जिन्हें आप उपयोग कर सकते हैं।
संबंधित मुद्दे