मैं पाइथन में रनटाइम पर गतिशील रूप से कक्षाएं बनाना चाहता हूं।रनटाइम पर कक्षाएं बनाते समय `exec` over` type() `का उपयोग करने में क्या फायदा है?
उदाहरण के लिए, मैं नीचे दिए गए कोड को दोहराने के लिए करना चाहते हैं:
>>> class RefObj(object):
... def __init__(self, ParentClassName):
... print "Created RefObj with ties to %s" % ParentClassName
... class Foo1(object):
... ref_obj = RefObj("Foo1")
... class Foo2(object):
... ref_obj = RefObj("Foo2")
...
Created RefObj with ties to Foo1
Created RefObj with ties to Foo2
>>>
... लेकिन मैं Foo1, foo2, फू कक्षाएं डायनामिक रूप से तैयार किया जाना है (यानी हैं: निष्पादन के दौरान बजाय पहले-पास पर संकलन)।
एक तरह से इस लक्ष्य को हासिल करने के लिए, type()
साथ है, इसलिए जैसे:
>>> class RefObj(object):
... def __init__(self, ParentClassName):
... print "Created RefObj with ties to %s" % ParentClassName
... def make_foo_class(index):
... name = "Foo%s" % index
... return type(name, (object,), dict(ref_obj = RefObj(name)))
...
>>> Foo1 = make_foo_class(1)
Created RefObj with ties to Foo1
>>> Foo2 = make_foo_class(2)
Created RefObj with ties to Foo2
>>> type(Foo1()), type(Foo2())
(<class 'Foo1'>, <class 'Foo2'>)
मैं भी exec
साथ इसे प्राप्त कर सकते हैं ताकि तरह:
>>> class RefObj(object):
... def __init__(self, ParentClassName):
... print "Created RefObj with ties to %s" % ParentClassName
... def make_foo_object(index):
... class_template = """class Foo%(index)d(object):
... ref_obj = RefObj("Foo%(index)d")
... """ % dict(index = index)
... global RefObj
... namespace = dict(RefObj = RefObj)
... exec class_template in namespace
... return namespace["Foo%d" % index]
...
>>> Foo1 = make_foo_object(1)
Created RefObj with ties to Foo1
>>> Foo2 = make_foo_object(2)
Created RefObj with ties to Foo2
>>> type(Foo1()), type(Foo2())
(<class 'Foo1'>, <class 'Foo2'>)
exec
के उपयोग अच्छी तरह से नहीं बैठता मेरे साथ (जैसा कि मुझे उम्मीद है कि यह बहुत से लोगों के साथ नहीं है जो इस प्रश्न को पढ़ते हैं) लेकिन exec
बिल्कुल कैसे पाइथन collections.namedtuple()
कक्षा is implemented (this line देखें)। क्लास (रेमंड हेटिंगर) के निर्माता द्वारा exec
here के इस उपयोग की रक्षा भी बहुत प्रासंगिक है। इस रक्षा में, यह कहा गया है कि "नामित टुपल्स के लिए यह एक प्रमुख विशेषता है कि वे एक हाथ से लिखित कक्षा" के बराबर हैं, जो कि यह संकेत दे सकता है कि type()
का उपयोग exec
का उपयोग करने के समान नहीं है ...
क्या कोई अंतर है? exec
बनाम type()
का उपयोग क्यों करें?
मैं उम्मीद जवाब हो सकता है कि दोनों तरीकों से ही कर रहे हैं और यह बस के माध्यम से यह peppered namedtuple चर का एक बहुत है कि namedtuple
कार्यान्वयन है, और के साथ ऐसा करने गतिशील बंद उत्पन्न सभी तरीकों के लिए बने कोड बोझल मिल , लेकिन मैं जानना चाहता हूं कि इसके लिए कुछ और है या नहीं।
exec
के साथ मेरी असुविधा के संबंध में, मुझे पता है कि अगर अविश्वासित पक्षों के लिए घृणास्पद कोड इंजेक्ट करने के लिए कोई रास्ता नहीं है, तो यह ठीक होना चाहिए ... यह केवल यह सुनिश्चित करना है कि मुझे परेशान करता है।
इस मुद्दे पर http://blog.ccpgames.com/kristjan/2011/05/28/namedtuple-and-exec/ पर भी अच्छी चर्चा है, और इसके बारे में एक और अच्छा ब्लॉग पोस्ट था मैं अब नहीं देखता आपने किसी भी कारण को प्रस्तुत नहीं किया है कि आपकी स्थिति में 'टाइप' समस्याग्रस्त क्यों है, इसलिए मुझे नहीं पता कि आप' exec 'से परेशान क्यों होंगे क्योंकि आप' प्रकार 'कार्यों को जानते हैं। (स्पष्ट रूप से जिज्ञासा के अलावा)। – agf
@agf - बढ़िया लिंक, धन्यवाद! मुझे मूल रूप से 'टाइप' के साथ कोई समस्या नहीं थी, क्योंकि दोनों दृष्टिकोण काम करते हैं। मैं मतभेदों के बारे में उत्सुक था, और 'नाम' के भीतर 'निष्पादन' उपयोग के कारण को समझने की कोशिश कर रहा था। प्रस्तुत किए गए वर्ग/फ़ंक्शन हस्ताक्षर तर्क उत्कृष्ट हैं, हालांकि ... मेरे पास अक्सर सजावटी समस्याएं होती हैं जिन्हें [सजावट] (http://pypi.python.org/pypi/decorator) पैकेज के उपयोग की आवश्यकता होती है। – Russ
क्या आप गतिशील वर्ग निर्माण की आवश्यकता के पीछे कारण दे सकते हैं या यह सिर्फ जिज्ञासा है? – dhill