2012-01-08 13 views
5

मैं एक परियोजना है कि एक समारोह परिभाषा इस के समान बनाए रखने:क्या `locals() 'में पहुंच योग्य` .0` चर या स्मृति या प्रदर्शन को प्रभावित करता है?

def f(a, (b1, b2), c): 
    print locals() 

कोड मुझे पता चला कि एक .1 कुंजी मान (b1, b2) साथ locals() में दिखाई दिया, डिबगिंग है। एक त्वरित जांच से पता चला कि निम्नलिखित की तरह एक समारोह परिभाषा:

def f((a1, a2)): 
    print locals() 

मूल्य (a1, a2) साथ locals() में एक .0 कुंजी होगा। मैं इस व्यवहार से हैरान था, लेकिन पाइथन दस्तावेज में कोई जानकारी नहीं मिली।

मेरे प्रश्न हैं: क्या इन अन्यथा-पहुंच योग्य स्थितित्मक चर स्मृति या प्रदर्शन को प्रभावित करते हैं? क्या वे कहीं भी दस्तावेज हैं? उनसे कौन सा उद्देश्य पूरा होता है?

प्रश्न में परियोजना फीडपार्सर है, जो सैक्स आधारित है और संभावित रूप से दर्जन या सैकड़ों फ़ंक्शन कॉल हो सकती हैं जो इस व्यवहार से प्रभावित होंगी।

+4

बहस में खोल स्वचालित टपल की यह शैली को पायथन 3 में स्पष्ट रूप से हटा दिया गया है, और यदि मुझे उस समय सही ढंग से याद किया गया था तो व्याकरण के दुर्घटना के रूप में वर्णित किया गया था। यह निश्चित रूप से एक शैली नहीं है जिसे मैं देखना चाहता हूं। –

+0

यह जानना अच्छा है! आप सही हैं, '2to3' उपकरण स्वचालित रूप से' xxx_todo_changeme' के साथ '(b1, b2)' वाक्यविन्यास को प्रतिस्थापित करता है। फिर भी, क्या आपके पास ऐसा लिंक है जो इस व्यवहार को स्पष्ट करने में मदद कर सकता है, या स्पष्ट निष्कासन के संबंध में एक लिंक? –

+3

@ कर्ट मैक्की [पीईपी 3113 - ट्यूपल पैरामीटर अनपॅकिंग को हटाने] [http://www.python.org/dev/peps/pep-3113/)। –

उत्तर

5

तो pep 3113, जैसा कि आर्टूर गैसपर बताते हैं, में एक पूर्ण उत्तर है। यह कारणों का एक पूरा समूह भी सूचीबद्ध करता है कि यह शायद पालन करने के लिए एक महान पैटर्न क्यों नहीं है। इनमें से एक आप डिबगिंग के कष्टप्रद साइड इफेक्ट्स में खोजे। एक बड़ा मुझे लगता है कि आपका कोड python3 में संक्रमण को तोड़ देगा, लेकिन मुझे यकीन नहीं है कि अभी भी 2.7 व्यक्तिगत रूप से है।

मैं क्या होता है इसके साथ खेलना चाहता था। (: Foo और बार समान bytecodes है स्पॉइलर): कुछ disassembled bytecodes हम देख सकते हैं कि इन तीन कार्यों के साथ होता है के रूप में देख रहे हैं

from dis import dis 

def foo(a, (b, c) ,d): 
    return a + b + c + d 

def bar(a, b_c, d): 
    b, c = b_c 
    return a + b + c + d 

def baz(a, b, c, d): 
    return a + b + c + d 

print '\nfoo:' 
dis(foo) 
print '\nbar:' 
dis(bar) 
print '\nbaz:' 
dis(baz) 

पैदावार:

foo: 
    3   0 LOAD_FAST    1 (.1) 
       3 UNPACK_SEQUENCE   2 
       6 STORE_FAST    3 (b) 
       9 STORE_FAST    4 (c) 

    4   12 LOAD_FAST    0 (a) 
      15 LOAD_FAST    3 (b) 
      18 BINARY_ADD   
      19 LOAD_FAST    4 (c) 
      22 BINARY_ADD   
      23 LOAD_FAST    2 (d) 
      26 BINARY_ADD   
      27 RETURN_VALUE   


bar: 
    7   0 LOAD_FAST    1 (b_c) 
       3 UNPACK_SEQUENCE   2 
       6 STORE_FAST    3 (b) 
       9 STORE_FAST    4 (c) 

    8   12 LOAD_FAST    0 (a) 
      15 LOAD_FAST    3 (b) 
      18 BINARY_ADD   
      19 LOAD_FAST    4 (c) 
      22 BINARY_ADD   
      23 LOAD_FAST    2 (d) 
      26 BINARY_ADD   
      27 RETURN_VALUE   


baz: 
11   0 LOAD_FAST    0 (a) 
       3 LOAD_FAST    1 (b) 
       6 BINARY_ADD   
       7 LOAD_FAST    2 (c) 
      10 BINARY_ADD   
      11 LOAD_FAST    3 (d) 
      14 BINARY_ADD   
      15 RETURN_VALUE   

आप देख सकते हैं। foo और bar समान हैं, जबकि baz अनपॅकिंग को छोड़ देता है। तो हाँ, इस प्रदर्शन थोड़ा प्रभावित करेगा, लेकिन केवल जब तक टपल unpacking ले जाता है, जो बहुत छोटे कार्यों और खिलौना उदाहरण (यह एक तरह; पी) के अलावा सब कुछ में नगण्य होना चाहिए

+0

मैंने कभी भी 'डी' मॉड्यूल का उपयोग नहीं किया है, यह दिखाने के लिए धन्यवाद कि यह कोड कैसे काम करता है!दुर्भाग्य से मैं टुपल अनपॅकिंग से बच नहीं सकता क्योंकि सभी सैक्स पार्सर्स एक एपीआई का उपयोग करते हैं जो टुपल्स पास करता है, लेकिन यह (और लिंक आर्टूर प्रदान किया गया) मैं जिस तरह का विश्लेषण ढूंढ रहा था वह था। –

3

हां, वे प्रदर्शन को प्रभावित करते हैं।

>>> import timeit 
>>> 
>>> 
>>> def function_1(a, (b1, b2), c): 
...  locals() 
... 
>>> def function_2(a, b1, b2, c): 
...  locals() 
... 
>>> 
>>> object_1 = object() 
>>> object_2 = object() 
>>> object_3 = object() 
>>> tuple_of_objects_2_and_3 = (object_2, object_3) 
>>> object_4 = object() 
>>> 
>>> n = 100000000 
>>> 
>>> time_1 = timeit.timeit(lambda: function_1(object_1, tuple_of_objects_2_and_3, 
...           object_4), 
...      number=n) 
>>> time_2 = timeit.timeit(lambda: function_2(object_1, object_2, object_3, 
...           object_4), 
...      number=n) 
>>> 
>>> print(time_1, time_2) 
(170.2440218925476, 151.92010402679443) 

अपनी दस्तावेज़ीकरण या उद्देश्य के बारे में, मैं नहीं जानता।

+2

उस परीक्षण में ट्यूपल पैकिंग के साथ-साथ टुपल अनपॅकिंग भी शामिल है। यह शायद कि एक 'tuple_23 = (object_2, object_3)' और संदर्भ का उपयोग करने के पहले लैम्ब्डा में न्यायपूर्ण होगा। – Robin

+0

@ रॉबिन आप सही हैं, धन्यवाद। मैंने अपना जवाब संपादित किया। –

+0

समय परीक्षण के लिए धन्यवाद, यह जानना उपयोगी है। –

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