यहां एक साधारण उदाहरण मॉड्यूल के लिए कोड का पृथक्करण है। एक कोड ऑब्जेक्ट बाइटकोड, स्थिरांक और नामों के उपयोग के लिए केवल पढ़ने योग्य कंटेनर है, और स्थानीय चर की संख्या, आवश्यक स्टैक आकार इत्यादि के बारे में मेटाडेटा नोटिस करें कि सभी कोड ऑब्जेक्ट्स को स्थिरांक के रूप में संकलित किया गया है। ये संकलन समय पर बनाए जाते हैं। लेकिन वस्तुओं class A
और function test
निष्पादन समय पर तत्काल हैं (उदाहरण के लिए जब मॉड्यूल आयात किया जाता है)।
वर्ग बनाने के लिए, BUILD_CLASS
नाम 'A'
, अड्डों tuple
(object,)
, और एक dict
उस वर्ग नाम स्थान की विशेषताओं में शामिल है लेता है। यह type(name, bases, dict)
पर कॉल करके मैन्युअल रूप से एक प्रकार को तुरंत चालू करने जैसा है। dict
बनाने के लिए, कोड ऑब्जेक्ट A
से फ़ंक्शन बनाया गया है और कहा जाता है। अंत में, क्लास ऑब्जेक्ट मॉड्यूल नेमस्पेस में STORE_NAME
के माध्यम से संग्रहीत किया जाता है।
कोड ऑब्जेक्ट A
, self.z
को MAKE_FUNCTION
पर तर्क के रूप में ढेर पर लोड किया गया है। बाइटकोड सेशन LOAD_NAME
वर्तमान स्थानीय क्षेत्रों में self
की खोज करेगा (यानी कक्षा नामस्थान परिभाषित किया जा रहा है), मॉड्यूल ग्लोबल्स और बिल्टिन। यदि self
वैश्विक या बिल्टिन स्कोप में परिभाषित नहीं किया गया है तो यह स्पष्ट रूप से विफल हो जाएगा; यह स्पष्ट रूप से स्थानीय दायरे में परिभाषित नहीं है।
यदि यह सफल हुआ, तो फ़ंक्शन (self.z,)
के साथ __defaults__
विशेषता के रूप में बनाया जाएगा, और फिर स्थानीय नाम test
पर संग्रहीत किया जाएगा।
>>> code = compile('''
... class A(object):
... def test(self, a=self.z): pass
... ''', '<input>', 'exec')
>>> dis.dis(code)
2 0 LOAD_CONST 0 ('A')
3 LOAD_NAME 0 (object)
6 BUILD_TUPLE 1
9 LOAD_CONST 1 (<code object A ...>)
12 MAKE_FUNCTION 0
15 CALL_FUNCTION 0
18 BUILD_CLASS
19 STORE_NAME 1 (A)
22 LOAD_CONST 2 (None)
25 RETURN_VALUE
>>> dis.dis(code.co_consts[1]) # code object A
2 0 LOAD_NAME 0 (__name__)
3 STORE_NAME 1 (__module__)
3 6 LOAD_NAME 2 (self)
9 LOAD_ATTR 3 (z)
12 LOAD_CONST 0 (<code object test ...>)
15 MAKE_FUNCTION 1
18 STORE_NAME 4 (test)
21 LOAD_LOCALS
22 RETURN_VALUE
@uselpa: आपका pastebin उदाहरण (2.x के लिए फिर से लिखा):
>>> code = compile('''
... default = 1
... class Cl(object):
... def __init__(self, a=default):
... print a
... Cl()
... default = 2
... Cl()
... ''', '<input>', 'exec')
>>> dis.dis(code)
2 0 LOAD_CONST 0 (1)
3 STORE_NAME 0 (default)
3 6 LOAD_CONST 1 ('Cl')
9 LOAD_NAME 1 (object)
12 BUILD_TUPLE 1
15 LOAD_CONST 2 (<code object Cl ...>)
18 MAKE_FUNCTION 0
21 CALL_FUNCTION 0
24 BUILD_CLASS
25 STORE_NAME 2 (Cl)
6 28 LOAD_NAME 2 (Cl)
31 CALL_FUNCTION 0
34 POP_TOP
7 35 LOAD_CONST 3 (2)
38 STORE_NAME 0 (default)
8 41 LOAD_NAME 2 (Cl)
44 CALL_FUNCTION 0
47 POP_TOP
48 LOAD_CONST 4 (None)
51 RETURN_VALUE
आप देख सकते हैं, वर्ग वस्तु Cl
(और समारोह वस्तु __init__
) केवल instantiated है और एक बार स्थानीय नाम 'Cl'
में संग्रहीत किया गया। मॉड्यूल अनुक्रमिक रूप से रन टाइम पर निष्पादित करता है, इसलिए बाद में default
नाम को पुनर्निर्मित करने से __init__
में डिफ़ॉल्ट मान पर कोई प्रभाव नहीं पड़ेगा।
आप गतिशील रूप से पहले से संकलित कोड और एक नया डिफ़ॉल्ट मान का उपयोग कर एक नया कार्य का दृष्टांत सकता है: एक नया __defaults__
टपल के साथ एक समारोह बनाने के लिए
>>> default = 1
>>> class Cl(object):
... def __init__(self, a=default):
... print a
...
>>> from types import FunctionType
>>> default = 2
>>> Cl.__init__ = FunctionType(
... Cl.__init__.__code__, globals(), '__init__', (default,), None)
>>> c = Cl()
2
यह __init__.__code__
से पहले से ही संकलित कोड वस्तु पुनः उपयोग कर लेता:
>>> Cl.__init__.__defaults__
(2,)
यदि तर्क गलत मूल्यों पर नहीं ले सकता है, तो आपको केवल 'अगर: a = self.z' या यहां तक कि' a = a या self.z' लिखना चाहिए। – danijar
मुझे लगता है कि आपका मतलब है 'अगर नहीं: a = self.z' – BBischof
क्या यह एक मानक पायथनिक पैटर्न है, यानी एक क्लास प्रॉपर्टी को डिफॉल्ट के साथ एक वैकल्पिक विधि प्रॉपर्टी से फॉल-बैक के रूप में उपयोग किया जाता है? या वैकल्पिक 'z = none' प्रॉपर्टी को शामिल करने के लिए' विस्तारित क्लास '__init__ कन्स्ट्रक्टर को बदलना बेहतर है, और यदि' कोई नहीं 'विधि के अंदर कुछ डिफ़ॉल्ट पर सेट करता है, और इसे विधि पैरामीटर के रूप में नहीं रखता है? मैं केवल इतना सोच सकता हूं कि हार्ड-कोडेड क्लास प्रॉपर्टी उपयोगी है यदि यह वास्तव में स्थिर है, और एक से अधिक तरीकों से आवश्यक है, अन्यथा क्यों नहीं, विधि के दायरे में 'z' को प्रतिबंधित करें, शायद कोई वर्ग या ऑब्जेक्ट न हो संपत्ति बिल्कुल? – Davos