2015-08-24 8 views
5

में हार्ड कोड किए गए चर कभी-कभी, कुछ मान/स्ट्रिंग फ़ंक्शंस में हार्ड-कोड किए जाते हैं। उदाहरण के लिए, निम्नलिखित फ़ंक्शन में, मैं एक "स्थिर" तुलना स्ट्रिंग को परिभाषित करता हूं और इसके खिलाफ जांच करता हूं।पाइथन फ़ंक्शन

def foo(s): 
    c_string = "hello" 
    if s == c_string: 
     return True 
    return False 

क्यों यह बुरा है यह करने के लिए, और यह कैसे बाहरी दायरे में परिभाषित किया जाना चाहिए, मैं सोच रहा हूँ पर्दे के पीछे क्या होता है जब यह है इस तरह से परिभाषित बारे में बहुत ज्यादा चर्चा कर के बिना।
क्या स्ट्रिंग प्रत्येक कॉल बनाई जाती है?
यदि स्ट्रिंग "hello" की बजाय यह सूची थी: [1,2,3] (या यदि यह मायने रखती है तो परिवर्तनीय सामग्री वाली एक सूची) वही होगी?

उत्तर

11

क्योंकि स्ट्रिंग अपरिवर्तनीय है (जैसा कि एक ट्यूपल होगा), यह फ़ंक्शन के लिए बाइटकोड ऑब्जेक्ट के साथ संग्रहीत है। यह एक बहुत ही सरल और तेज़ इंडेक्स लुकअप से भरा हुआ है। यह वास्तव में वैश्विक खोज की तुलना में तेज है।

आप बाईटकोड के disassembly में देख सकते हैं, का उपयोग कर dis.dis() function:

>>> import dis 
>>> def foo(s): 
...  c_string = "hello" 
...  if s == c_string: 
...   return True 
...  return False 
... 
>>> dis.dis(foo) 
    2   0 LOAD_CONST    1 ('hello') 
       3 STORE_FAST    1 (c_string) 

    3   6 LOAD_FAST    0 (s) 
       9 LOAD_FAST    1 (c_string) 
      12 COMPARE_OP    2 (==) 
      15 POP_JUMP_IF_FALSE  22 

    4   18 LOAD_GLOBAL    0 (True) 
      21 RETURN_VALUE   

    5  >> 22 LOAD_GLOBAL    1 (False) 
      25 RETURN_VALUE   
>>> foo.__code__.co_consts 
(None, 'hello') 

LOAD_CONST opcode co_costs सरणी कि समारोह के लिए कोड वस्तु का हिस्सा है से स्ट्रिंग वस्तु को लोड करता है; संदर्भ ढेर के शीर्ष पर धक्का दिया जाता है। STORE_FAST ऑपोड स्टैक के शीर्ष से संदर्भ लेता है और इसे स्थानीय सरणी में संग्रहीत करता है, फिर से एक बहुत ही सरल और तेज़ ऑपरेशन।

परिवर्तनशील शाब्दिक के लिए ({..}, [..]) विशेष opcodes, वस्तु का निर्माण सामग्री अभी भी जितना संभव हो उतना स्थिरांक के रूप में इलाज के साथ (और अधिक जटिल संरचनाओं सिर्फ एक ही बिल्डिंग ब्लॉक्स का पालन करें):

>>> def bar(): return ['spam', 'eggs'] 
... 
>>> dis.dis(bar) 
    1   0 LOAD_CONST    1 ('spam') 
       3 LOAD_CONST    2 ('eggs') 
       6 BUILD_LIST    2 
       9 RETURN_VALUE   

BUILD_LIST कॉल दो निरंतर स्ट्रिंग ऑब्जेक्ट्स का उपयोग करके नई सूची ऑब्जेक्ट बनाता है।

दिलचस्प तथ्य: यदि आपने सदस्यता परीक्षण के लिए एक सूची वस्तु का उपयोग किया है (something in ['option1', 'option2', 'option3'] पायथन जानता है कि सूची वस्तु कभी भी उत्परिवर्तित नहीं होगी और इसे संकलित समय (एक तथाकथित पेफोल अनुकूलन) पर आपके लिए एक टुपल में परिवर्तित कर देगा। एक ही एक सेट शाब्दिक है, जो एक frozenset() वस्तु में बदल जाती है पर लागू होता है, लेकिन केवल अजगर 3.2 और नए में देखें Tuple or list when using 'in' in an 'if' clause?

ध्यान रखें कि आपके नमूना समारोह बूलियन्स बल्कि verbosely उपयोग कर रहा है, तो आप सिर्फ इस्तेमाल किया जा सकता था:।

def foo(s): 
    c_string = "hello" 
    return s == c_string 

सटीक उसी परिणाम के लिए,से परहेज करनापायथन 2 में कॉल (पायथन 3 True और False कीवर्ड बनाते हैं ताकि मूल्य स्थिरांक के रूप में भी संग्रहीत किए जा सकें)।

+0

क्या वही बात 's ==" हैलो "के साथ नहीं होती है? – jonrsharpe

+0

आप tuples पर टिप्पणी के बारे में सही हैं, मुझे इसके बजाय सूची के बारे में पूछा जाना चाहिए था। मैं सवाल सही कर रहा हूँ। बाकी का जवाब अब के लिए उत्कृष्ट है :) –

+0

@ आर्थर वैसेलबुह: मैंने अब भी सूचियों को कवर किया है, साथ ही '{...} 'शब्दकोश और सेट। –

संबंधित मुद्दे