2010-10-06 10 views
6

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

template<class T> 
    class Foo : T { 
     void fun() {} 
    } 

उत्तर

9

हालांकि यह निश्चित रूप से metaclasses साथ किया जा सकता है, तो आप आप क्या चाहते हैं कर सकते हैं: जब से मैं सी ++/डी खाके से विचार आया, यहाँ क्या कोड मैं सी में कैसा दिखेगा लिखना चाहते हैं की ++ एक उदाहरण है उनके बिना क्योंकि पाइथन कक्षाएं स्वयं वस्तुएं हैं। इसका अर्थ यह है कि आश्चर्यजनक रूप से-अनिवार्य रूप से सी ++ कोड के लगभग एक से एक अनुवाद की आवश्यकता नहीं है। अपेक्षाकृत इस वजह से गैर होने के अलावा, यह भी दोनों अजगर में संशोधन के बिना काम करेंगे 2 & 3.

def template(class_T): 
    """Factory function to create subclasses of class_T.""" 

    class Foo(class_T): 
     def fun(self): 
      print('%s.fun()' % self.__class__.__name__) 

    Foo.__name__ += '_' + class_T.__name__ # rename the subclass to reflect its heritage 
    return Foo 

class Base1: 
    def bar(self): 
     print('Base1.bar()') 

class Base2: 
    def bar(self): 
     print('Base2.bar()') 

Foo_Base1 = template(Base1) 
print('Foo_Base1 base classes: {}'.format(Foo_Base1.__bases__)) 

Foo_Base2 = template(Base2) 
print('Foo_Base2 base classes: {}'.format(Foo_Base2.__bases__)) 

subclass1 = Foo_Base1() 
subclass1.fun() 
subclass1.bar() 
subclass2 = Foo_Base2() 
subclass2.fun() 
subclass2.bar() 

आउटपुट:

Foo_Base1 base classes: (<class __main__.Base1 at 0x00A79C38>,) 
Foo_Base2 base classes: (<class __main__.Base2 at 0x00A79DC0>,) 
Foo_Base1.fun() 
Base1.bar() 
Foo_Base2.fun() 
Base2.bar() 

(कल्पनाशीलता के अभाव में नाम) template() समारोह में कोड है आमतौर पर class factory या फैक्टरी पैटर्न के कार्यान्वयन का एक उदाहरण है। इसलिए, आकस्मिक रूप से, आपको प्रश्न What exactly is a Class Factory? पर जानकारी मिल सकती है।

संपादित करें: जब डिबगिंग अगर वर्ग हमेशा निर्मित एक ही नाम है संभावित भ्रम के बारे में प्रत्येक उपवर्ग लौटे-जो (क अब हटाई गई टिप्पणी में) @aaronasterling की अंतर्दृष्टि से प्रेरित था के लिए अलग अलग वर्ग के नाम बनाने के लिए जोड़ा गया कोड ।

+0

बहुत बढ़िया, मुझे लगता है metaclasses इतना आसान कुछ के लिए overkill है। यह समाधान हिंडसाइट में बहुत अधिक समझ में आता है, क्योंकि पाइथन में प्रकार प्रथम श्रेणी की वस्तुएं हैं, और कक्षाएं रनटाइम पर बनाई जा सकती हैं। मुझे लगता है कि मुझे अपने स्वयं के अभी तक आने के बारे में सोचने की गतिशील भाषा के तरीके के साथ पर्याप्त सहजता नहीं मिली है। – dsimcha

+0

टेम्पलेट्स * सी ++ में मेटाक्लास, दृढ़ता से टाइप की गई भाषा हैं। पाइथन जैसे कमजोर टाइप किए गए एक में, जहां कक्षाएं आपके द्वारा देखी गई वस्तुएं भी होती हैं, वहां अक्सर जाना आवश्यक नहीं होता है - लेकिन जब आप करते हैं, तो आप टेम्पलेट तर्क तक ही सीमित नहीं होते हैं और कुछ अद्भुत चीजें कर सकते हैं। – martineau

+6

** पायथन दृढ़ता से टाइप किया गया ** है, आप पाइथन में एक स्ट्रिंग और एक पूर्णांक नहीं जोड़ सकते हैं जैसे आप कमजोर टाइप की गई भाषा जैसे जावास्क्रिप्ट में करते हैं। संयोग से, ** पायथन भी गतिशील रूप से टाइप किया गया ** है। –

0

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

अजगर में आप एक कारखाने समारोह है कि एक वर्ग लेता है और रनटाइम पर एक नया वर्ग रिटर्न के साथ ऐसा कर सकते हैं:

In [1]: def subclassFactory(cls): 
    ...:  class Foo(cls): 
    ...:   def fun(self): 
    ...:    return "this is fun" 
    ...:  return Foo 
    ...: 

In [2]: class A(object): 
    ...:  pass 
    ...: 

In [5]: C = subclassFactory(A) 

In [6]: C 
Out[6]: <class '__main__.Foo'> 
In [7]: c = C() 
In [9]: c.fun() 
Out[9]: 'this is fun' 
In [10]: isinstance(c, A) 
Out[10]: True 
संबंधित मुद्दे