2010-04-24 18 views
8

यहाँ मैं क्या चारों ओर पाने के लिए कोशिश कर रहा हूँ की एक बहुत ही सरल उदाहरण है:वर्ग __init__ (नहीं उदाहरण __init__)

class Test(object): 
    some_dict = {Test: True} 

समस्या जबकि यह अभी भी परिभाषित किया जा रहा है कि मैं टेस्ट का उल्लेख नहीं कर सकता है

आम तौर पर, मैं बस यह करता हूं:

class Test(object): 
    some_dict = {} 
    def __init__(self): 
     if self.__class__.some_dict == {}: 
      self.__class__.some_dict = {Test: True} 

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

तो मेरी प्रश्न यह है कि, इसे परिभाषित किए जाने पर टेस्ट को कैसे संदर्भित किया जा सकता है, या क्या __init__ जैसा कुछ है जिसे कक्षा के रूप में जल्द ही कहा जाता है? यदि संभव हो, तो मुझे कक्षा परिभाषा के अंदर रहने के लिए self.some_dict = {Test: True} चाहिए।

class Test(object): 
    @classmethod 
    def class_init(cls): 
     cls.some_dict = {Test: True} 
Test.class_init() 
+0

"समस्या यह है कि मैं टेस्ट को संदर्भित नहीं कर सकता, जबकि इसे अभी भी परिभाषित किया जा रहा है"। इसलिए? परिभाषा के दौरान ** आपको किस तरह के संदर्भ की आवश्यकता है **? मानक उत्तर कोई नहीं है: कक्षा परिभाषा स्थिर, सुसंगत और परिवर्तनीय है। ** व्यवहार ** बदल सकते हैं। परिभाषा नहीं बदलनी चाहिए। आप इस "अलग-अलग परिभाषा" व्यवसाय के साथ क्या करने की कोशिश कर रहे हैं? –

+0

परिभाषा नहीं बदल रही है। मुझे बस कक्षा के संदर्भ की आवश्यकता है, और संगठन के प्रयोजनों के लिए, मैं यह पसंद करूंगा कि कक्षा को परिभाषित किए जाने पर मैंने उस संदर्भ को सेट किया है। – Ponkadoodle

+0

मैं समझता हूं कि आप क्या करने की कोशिश कर रहे हैं, लेकिन मुझे नहीं मिल रहा है कि आप इसे इस तरह से करने की कोशिश क्यों कर रहे हैं और आप क्या हासिल करना चाहते हैं। क्या आप थोड़ा सा विस्तार कर सकते हैं? ऐसा लगता है कि एक वास्तुशिल्प के बाद एक "मैं कैसे पाइथन को जोड़ता हूं ...?" मुझे मुद्दा – Aea

उत्तर

12

कक्षा वास्तव में परिभाषित होने पर अस्तित्व में नहीं है। class कथन का तरीका यह है कि कथन का निकाय कोड के ब्लॉक के रूप में, एक अलग नामस्थान में निष्पादित किया जाता है। निष्पादन के अंत में, नामस्थान मेटाक्लास (जैसे type) को पास किया गया है और मेटाक्लास नामस्थान स्थान के रूप में नामस्थान का उपयोग कर वर्ग बनाता है।

आपके विवरण से, यह एक कक्षा होने के लिए आवश्यक ध्वनि के लिए आवश्यक ध्वनि है। ऐसा लगता है कि यह मॉड्यूल होना चाहिए। some_dict एक वैश्विक है - भले ही यह एक वर्ग विशेषता है, आपके प्रोग्राम में केवल एक ही विशेषता है, इसलिए यह वैश्विक होने से बेहतर नहीं है - और कक्षा में आपके पास कोई भी वर्ग विधि केवल कार्य हो सकती है।

तुम सच में एक वर्ग के होने के लिए चाहते हैं, तो आप तीन विकल्प हैं: (अजगर 2.6 में या बाद में)

class Test: 
    some_dict = {} 
Test.some_dict[Test] = True 

एक वर्ग डेकोरेटर का प्रयोग करें:

def set_some_dict(cls): 
    cls.some_dict[cls] = True 

@set_some_dict 
class Test: 
    some_dict = {} 
वर्ग को परिभाषित करने के बाद dict सेट

या एक metaclass का उपयोग करें:

class SomeDictSetterType(type): 
    def __init__(self, name, bases, attrs): 
     self.some_dict[self] = True 
     super(SomeDictSetterType, self).__init__(name, bases, attrs) 

class Test(object): 
    __metaclass__ = SomeDictSetterType 
    some_dict = {} 
+0

+1 यह * एक मॉड्यूल हो सकता है, लेकिन मैं इसे एक वर्ग बनना पसंद करूंगा। यदि यह एक अलग मॉड्यूल में था, तो मुझे परिपत्र आयात को रोकने के लिए थोड़ा पुनर्व्यवस्थित करना होगा। साथ ही, मेरे प्रोजेक्ट को संपादित करते समय मुझे 20 टैब खोलने की आवश्यकता होगी यदि वे सभी वर्ग अलग-अलग फाइलों में थे। वैसे भी, मेटाक्लास के बारे में मुझे बताने के लिए धन्यवाद। –

+0

के लिए – Ponkadoodle

+0

सजावट एक अच्छा दृष्टिकोण है –

4

आप मुख्य वर्ग परिभाषा के बाद some_dict विशेषता जोड़ सकते हैं: यही एक रास्ता है मैं कैसे अब तक यह करने के लिए पता है।

class Test(object): 
    pass 
Test.some_dict = {Test: True} 
+0

यह करने का यह तरीका है। – PaulMcG

+0

सहमत - यह सही जवाब है। विस्तृत उत्तर –

0

तुम भी एक metaclass उपयोग कर सकते हैं (एक समारोह यहाँ लेकिन वहाँ अन्य तरीके हैं) :

def Meta(name, bases, ns): 
    klass = type(name, bases, ns) 
    setattr(klass, 'some_dict', { klass: True }) 
    return klass 

class Test(object): 
    __metaclass__ = Meta 

print Test.some_dict 
0

थॉमस का पहला उदाहरण बहुत अच्छा है, लेकिन यह वही काम करने का एक और पाइथोनिक तरीका है।

class Test: 
    x = {} 
    @classmethod 
    def init(cls): 
     # do whatever setup you need here 
     cls.x[cls] = True 
Test.init() 
1

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

ए (अजीब दिखने) दूसरे जो सुझाव दिया है करने के लिए वैकल्पिक:

class Test(object): 
    def __new__(cls): 
     cls.some_dict = {cls: True} 

Test() 

तुम भी है __new__ एक संदर्भ वर्ग पर लौट सकता है और एक डेकोरेटर का उपयोग इसे कहते हैं: आप __new__ इस्तेमाल कर सकते हैं

def instantiate(cls): 
    return cls() 

@instantiate 
class Test(object): 
    def __new__(cls): 
     cls.some_dict = {cls: True} 
     return cls 
संबंधित मुद्दे