2011-02-14 13 views
11

के भीतर से एक नई वस्तु उत्पन्न करने के लिए Idiomatic Python मेरे पास मेरी एक ऑब्जेक्ट पर एक विधि है जो उसी कक्षा का एक नया उदाहरण देता है। मैं इस विधि को लिखने के लिए सबसे बेवकूफ तरीका जानने की कोशिश कर रहा हूं जैसे कि यह कोड को डुप्लिकेट किए बिना उसी प्रकार की एक नई वस्तु उत्पन्न करता है।कक्षा

के बाद से इस पद्धति का उदाहरण डेटा का उपयोग करता, मेरी पहली पास होना जरूरी है:

class Foo(object): 
    def get_new(self): 
     data = # Do interesting things 
     return Foo(data) 

हालांकि, अगर मैं फू उपवर्ग और get_new ओवरराइड नहीं करते, SubFoo पर get_new बुला एक फू वापसी होगी! तो, मैं एक classmethod लिख सकते हैं:

class Foo(object): 

    @classmethod 
    def get_new(cls, obj): 
     data = # Munge about in objects internals 
     return cls(data) 

हालांकि, डेटा मैं तक पहुँचने हूँ वस्तु के लिए विशिष्ट है, तो यह इस बात के लिए कैप्सूलीकरण को तोड़ने के लिए एक "सामान्य" (असज्जित) विधि होने के लिए नहीं लगता है। इसके अतिरिक्त, आपको इसे SubFoo.get_new(sub_foo_inst) जैसा कॉल करना होगा, जो अनावश्यक लगता है। मैं ऑब्जेक्ट को बस "जानना" चाहता हूं कि किस प्रकार का रिटर्न - एक ही प्रकार जैसा ही है!

मुझे लगता है कि कक्षा में फैक्ट्री विधि जोड़ना भी संभव है, और तर्क को डुप्लिकेट किए बिना, हर जगह वापसी प्रकार को ओवरराइड करना संभव है, लेकिन ऐसा लगता है कि उप-वर्गों पर बहुत अधिक काम किया जाता है।

तो, मेरा सवाल यह है कि, एक विधि लिखने का सबसे अच्छा तरीका क्या है जो कक्षा के प्रकार में लचीलापन देता है बिना किसी जगह के प्रकार को एनोटेट किए बिना?

+0

क्लासमेड स्वयं पाइथन पर बहुत मूर्ख नहीं हैं; कारखानों केवल सादे कार्य हो सकते हैं जो कक्षा के समान मॉड्यूल में रहते हैं। –

+1

@Adam: कक्षा विधियों का उपयोग होता है (उदाहरण के लिए जब आप कक्षा चर का उपयोग कर रहे हैं और विरासत तोड़ना नहीं चाहते हैं)। स्थिर तरीके बहुत खराब हैं। – delnan

उत्तर

16

आप इसे और अधिक उपवर्गीकरण के लिए लचीला बनाना चाहते हैं, तो आप बस self.__class__ विशेष विशेषता का उपयोग कर सकते हैं:

class Foo(object): 
    def __init__(self, data): 
     self.data = data 

    def get_new(self): 
     data = # Do interesting things 
     return self.__class__(data) 

ध्यान दें कि @classmethod दृष्टिकोण का उपयोग कर किसी भी एक उदाहरण के भीतर डेटा तक पहुँचने से रोकने जाएगा, इसे हटाने उदाहरणों में एक व्यवहार्य समाधान के रूप में जहां #Do interesting things किसी उदाहरण के भीतर संग्रहीत डेटा पर निर्भर करता है।

अजगर 2 के लिए, मैं, type(self) उपयोग करने की अनुशंसा नहीं है के रूप में इस classic classes के लिए एक अनुचित मान प्रदान करेंगे (यानी, आधार object से subclassed नहीं उन):

>>> class Foo: 
...  pass 
... 
>>> f = Foo() 
>>> type(f) 
<type 'instance'> 
>>> f.__class__ # Note that the __class__ attribute still works 
<class '__main__.Foo'> 

अजगर 3 के लिए, यह नहीं है एक मुद्दा के रूप में, क्योंकि सभी वर्ग object से प्राप्त किए गए हैं, हालांकि, मेरा मानना ​​है कि self.__class__ को अधिक पायथनिक मुहावर माना जाता है।

+0

बिल्कुल सही! यही वही है जो मैं ढूंढ रहा था। यह पाइथन का उपयोग करके गंभीरता से केवल सप्ताह 2 या इससे भी अधिक है, इसलिए मैं अभी भी सभी टुकड़ों और पूरी तरह से उपयोग किए जाने के बारे में पूरी तरह से अवगत नहीं हूं। –

+1

'प्रकार (स्वयं)' का उपयोग करके, जैसा कि मॉटर सुझाव देता है, अनिवार्य रूप से वही बात करता है लेकिन थोड़ा साफ करने वाला IMHO है। लेकिन शायद यह चार अंडरस्कोर के साथ कुछ भी मेरे लिए उलझन है। – Thomas

+2

@ थॉमस: मैं वास्तव में 'प्रकार()' का उपयोग करने की अनुशंसा नहीं करता हूं, और मैंने अपने उत्तर के बारे में एक स्पष्टीकरण जोड़ा है। – gotgenes

2

आप बिल्टिन 'प्रकार' का उपयोग कर सकते हैं।

type(instance) 

उस उदाहरण की कक्षा है।