2016-08-15 13 views
5

मुझे एक कन्डर्रम का सामना करना पड़ा है। मुझे लगता है कि मुझे यह पता होना चाहिए कि इसे कैसे हल किया जाए - मैं बेहद जानकार और पाइथन में अनुभवी हूं - लेकिन मैं इसे समझ नहीं सकता। ऐसा लगता है कि मैं जिस तरह से संघर्ष कर रहा हूं उसे एक डिजाइन पैटर्न द्वारा संबोधित किया जाना चाहिए जो फैक्ट्री थीम पर भिन्नता है, लेकिन मुझे एक याद नहीं है। (इस लेखन के अंत में मैं एक तकनीकी समाधान का सुझाव देता हूं, लेकिन यह एक असंभव प्रतीत होता है।) मुझे आशा है कि आपको यह चर्चा अपने आप में दिलचस्प लगेगी, लेकिन मैं अपनी समस्या के समाधान के लिए कुछ सुझाव सुनने की आशा करता हूं।पायथन में किसी अन्य के उदाहरण के लिए एक वर्ग की वस्तुओं के निर्माण को प्रतिबंधित कैसे करें?

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

ये मॉडल-लेयर कक्षाएं हैं जो एक अनुप्रयोग का उपयोग करता है। बी, सी, या डी के अनुप्रयोगों में हेरफेर करने के उदाहरण में कोई समस्या नहीं है, इसे सिर्फ उन्हें सीधे नहीं बनाना चाहिए - यह सब सीधे बनाने में सक्षम होना चाहिए ए (और ए भी एक सिंगलटन हो सकता है)। विभिन्न प्रकार के सत्यापन, प्रबंधन, ट्रैकिंग, लेखा परीक्षा इत्यादि हैं जिन्हें एक वर्ग के तरीकों में लागू किया जा सकता है जो अगले के उदाहरण बनाते हैं।

एक उदाहरण एक ऑपरेटिंग सिस्टम हो सकता है जो फाइल सिस्टम बना सकता है जो फाइलें बना सकते हैं जो निर्देशिका बना सकते हैं, लेकिन एप्लिकेशन कोड को उस श्रृंखला का पालन करना होगा। उदाहरण के लिए, भले ही उसके पास निर्देशिका पर हाथ हो, फिर भी फ़ाइल बनाने के लिए कहा जाने पर निर्देशिका के उदाहरण File.__init__ निर्देशिका उदाहरण देने में सक्षम नहीं होना चाहिए, भले ही निर्देशिका बनाने के लिए निर्देशिका के उदाहरण क्या हों।

मैं कुछ कार्यान्वयन का समर्थन करने के लिए एक डिज़ाइन समाधान की तलाश में हूं, कुछ उपयोगकर्ता-सबूत नहीं - मैं बाद की व्यर्थता को समझता हूं।

केवल एक चीज मैं अब तक के बारे में सोचा है:

  1. सभी वर्ग के नाम एक को छोड़कर एक अंडरस्कोर से
  2. पहुँच _B() को केवल उदाहरणों से, _C() केवल बी उदाहरणों से शुरू करते हैं, और _D() केवल _C उदाहरणों से
  3. द्वारा इस व्यवस्था का सम्मान करना और सीधे ही (संभवतः सिंगलटन) वर्ग एक

मॉड्यूल स्तरीय "छिपा" का उदाहरण बना आवेदन-परत प्रोग्रामर पर भरोसा करते हैं मॉड्यूल की __all__ सूची से कक्षा को छोड़कर अपर्याप्त है, क्योंकि केवल import * निर्माण को प्रभावित करता है - एक और मॉड्यूल अभी भी import module द्वारा कक्षा तक पहुंच सकता है और फिर module.class का संदर्भ दे सकता है।

(यह सी ++ समस्याओं की सभी अनजान याद दिलाता है जिसके लिए दो वर्गों के मित्र होने की आवश्यकता होती है क्योंकि वे दो-तरफा संबंधों में भाग लेते हैं: प्रत्येक वर्ग के उदाहरण अन्य वर्ग के तरीकों का संदर्भ करने में सक्षम होना चाहिए जो प्रबंधन करते हैं रिश्ते के दूसरी तरफ।)

जो समाधान पाइथन के अर्थशास्त्र और व्यावहारिक रूप से सर्वोत्तम हो सकता है वह बी के अंदर परिभाषित सी, सी और बी के अंदर परिभाषित बी को परिभाषित करना है। यह एक बेहद बदसूरत तरीका है एक बहुत बड़ी कक्षा में कोड के लायक कई मॉड्यूल। (और कल्पना करें कि श्रृंखला कुछ और स्तर नीचे चला गया है।) यह नेस्टेड कक्षाओं के अधिक सामान्य उपयोगों का विस्तार है और शायद ऐसा करने का एकमात्र तकनीकी रूप से अच्छा तरीका है, लेकिन मैंने इस तरह के रूसी-गुड़िया वर्ग संरचना को कभी नहीं देखा है।

विचार?

+0

यदि आप समस्या संक्षेप में तैयार कर सकता है एक एक वाक्य है कि आप विचार और उदाहरण के अपने खुद के लाइन से अलग में यह उपयोगी होगा। – noumenal

+0

यह कट्टरपंथी है कि क्लास कन्स्ट्रक्टर को पहुंचने योग्य बनाने की कोशिश करने के बजाय आप [तकनीक] [http://stackoverflow.com/a/9812105/3895264) के समान तकनीक का उपयोग करके निर्माण के दौरान कॉलिंग विधि की कक्षा की जांच कर सकते हैं। ध्यान दें कि मैं हालांकि इसकी सिफारिश करता हूं! – FujiApple

+0

अलग करना एक अच्छा विचार है - माफ करना मैंने इसके बारे में नहीं सोचा था। –

उत्तर

6

अजगर पूरी तरह से छुपा यह वस्तुओं है पर बहुत अच्छा नहीं है ... भी यदि आप एक वर्ग परिभाषा को छिपाने के लिए प्रयास करने के लिए "रूसी गुड़िया" बंद करने का फैसला, एक उपयोगकर्ता अभी भी इसे प्राप्त कर सकते हैं ...

class A(object): 
    def create_b(self): 
     class B(object): 
      pass 
     return B() 

a = A() 
b = a.create_b() 
b_cls = type(b) 
another_b = b_cls() 

सीधे शब्दों में कहें - एक उपयोगकर्ता स्रोत कोड का एक्सेस है (और वे inspect के माध्यम से इसे प्राप्त कर सकते हैं या कम से कम, वे dis जो एक प्रशिक्षित आँख को काफी अच्छा है के माध्यम से बाईटकोड प्राप्त कर सकते हैं), तो उनके पास पर्याप्त रूप से प्रेरित होने पर आपके वर्ग के उदाहरण बनाने की शक्ति है।

आम तौर पर, कक्षा को केवल कुछ ऐसा करने के लिए पर्याप्त है जो उपयोगकर्ता को खुद को तत्काल नहीं करना चाहिए - अगर वे उस विश्वास को तोड़ते हैं, तो यह उनकी गलती है जब उनका प्रोग्राम दुर्घटनाग्रस्त हो जाता है और जलता है (और कुछ बुरा साइड- प्रभाव जो उनके हार्ड ड्राइव को साफ़ करने के बाद अपने कंप्यूटर को आग पकड़ने का कारण बनता है)। यह एक सुंदर केंद्रीय पायथन दर्शन है, जो python mail archives में अच्छी तरह से कहा गया है:

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

आखिरकार, हम सभी यहां वयस्कों की सहमति दे रहे हैं।

सी ++ और जावा में यह दर्शन नहीं है (उसी हद तक नहीं)। वे आपको निजी विधियों और स्थिर सदस्यों को बनाने की अनुमति देते हैं।

पर्ल संस्कृति इस संबंध में अजगर की तरह है, लेकिन पर्ल भावना को थोड़ा अलग तरीके से व्यक्त करता है। जैसा कि ऊंट पुस्तक ने रखा है,

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

लेकिन भावना समान है।

1

बस मेरे सिर के ऊपर से:

def B(object): 
    pass 

def D(object): 
    pass 

def bound(object): 
    if type(object) is C: 
     assert isinstance(D) 
    if type(object) is A: 
     assert isinstance(B) 
    else: 
     assert false 

@bound 
def C(D): 
    pass 

@bound 
def A(B): 
    pass 
+0

इस कोड को जांचने की आवश्यकता होगी: वर्तमान में यह नहीं चल रहा है। इसके पीछे विचार की व्याख्या करना भी बहुत उपयोगी होगा। – EOL

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

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