2013-05-10 4 views
5

मेरे पास एक फ़ंक्शन है, और जब इसे कॉल किया जाता है, तो मैं जानना चाहता हूं कि वापसी मूल्य क्या सौंपा जा रहा है - विशेष रूप से जब इसे अनपॅक किया जाता है टपल। तो:पता लगाएं कि रिटर्न वैल्यू कितने मूल्य अनपॅक किए जाएंगे

a = func()   # n = 1 

बनाम

a, b, c = func() # n = 3 

मैं func में n के मूल्य का उपयोग करना चाहते हैं। inspect या _getframe के साथ कुछ जादू होना चाहिए जो मुझे ऐसा करने देता है। कोई विचार?


अस्वीकरण (क्योंकि यह आजकल आवश्यक प्रतीत हो रहा है): मैं जानता हूँ कि यह अजीब है, और बुरा व्यवहार, और उत्पादन कोड में नहीं किया जाना चाहिए। यह वास्तव में कुछ ऐसा लगता है जो मैं पर्ल में अपेक्षा करता हूं। मैं अपनी "वास्तविक" समस्या को हल करने के लिए एक अलग तरीके की तलाश नहीं कर रहा हूं, लेकिन मुझे उत्सुकता है कि मैंने उपरोक्त के लिए क्या पूछा है। इस चाल में से एक शांत उपयोग होगा:

ONE, TWO, THREE = count() 
ONE, TWO, THREE, FOUR = count() 

साथ
def count(): 
    n = get_return_count() 
    if not n: 
     return 
    return range(n) 
+0

आप लौटाए गए मूल्य की लंबाई की जांच कर सकते हैं और उस लंबाई के आधार पर असाइनमेंट कर सकते हैं। –

+0

इसका उद्देश्य क्या है? आप फ़ंक्शन से ही जान सकते हैं कि कितने आइटम लौटाए जाएंगे, या आप कॉलर में बस 'len (foo()) 'कर सकते हैं। मुझे लगता है कि यह एक समस्या की तलाश में समाधान का मामला है। –

+0

@ अश्विनी चौधरी: नहीं, मैं अभी भी फ़ंक्शन 'func' में हूं और अभी तक कुछ भी वापस नहीं किया है, इसलिए मैं' लेन 'नहीं कह सकता। यदि कॉलर 'ए, बी = func()' करता है, तो मैं 2 तत्व वापस कर दूंगा। यदि कॉलर 'ए, बी, सी = func()' करता है, तो मैं वापस आऊंगा। मैं func में जानना चाहता हूं कि कॉलर रिटर्न वैल्यू के साथ क्या करेगा। – jdm

उत्तर

4

वहाँ कैसे अजगर करता है के बारे में थोड़ा जादू है।

बस शब्दों में कहें, यदि आप बाएं हाथ के एक से अधिक लक्ष्य नाम का उपयोग करते हैं, तो दाईं ओर अभिव्यक्ति को अनुक्रम मिलान लंबाई की वापसी करनी होगी।

फ़ंक्शंस जो एक से अधिक मान लौटाते हैं वास्तव में केवल एक टुपल लौटाते हैं। यह एक मानक पायथन संरचना है, जो एक निश्चित लंबाई का अनुक्रम है। आपको लगता है कि लंबाई को मापने कर सकते हैं:

retval = func() 

print len(retval) 

असाइनमेंट unpacking पर निर्धारित किया जाता है समय संकलन, आप गतिशील समारोह आप बुला रहे हैं सूट करने के लिए बाएं हाथ की ओर के बारे में अधिक तर्क नहीं जोड़ सकते।

:

a, b, *c = func() 

c अब एक पहले 2 से परे किसी भी शेष मूल्यों के साथ सूची हो जाएगा:

अजगर 3 आप एक पैक काम के शेष पर कब्जा करने के लिए एक सूचक वाक्य रचना, एक वाइल्डकार्ड, उपयोग करने देता है

>>> def func(*a): return a 
... 
>>> a, b, *c = func(1, 2) 
>>> a, b, c 
(1, 2, []) 
>>> a, b, *c = func(1, 2, 3) 
>>> a, b, c 
(1, 2, [3]) 
>>> a, b, *c = func(1) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
ValueError: need more than 1 value to unpack 
+0

वाइल्डकार्ड चाल अच्छा है, मुझे इसे याद रखना होगा। – jdm

9

http://code.activestate.com/recipes/284742-finding-out-the-number-of-values-the-caller-is-exp/ से अनुकूलित:

import inspect 
import dis 

def expecting(offset=0): 
    """Return how many values the caller is expecting""" 
    f = inspect.currentframe().f_back.f_back 
    i = f.f_lasti + offset 
    bytecode = f.f_code.co_code 
    instruction = ord(bytecode[i]) 
    if instruction == dis.opmap['UNPACK_SEQUENCE']: 
     return ord(bytecode[i + 1]) 
    elif instruction == dis.opmap['POP_TOP']: 
     return 0 
    else: 
     return 1 

def count(): 
    # offset = 3 bytecodes from the call op to the unpack op 
    return range(expecting(offset=3)) 

या एक ओब के रूप में जेक्ट जो अनपॅक किए जाने पर पता लगा सकता है:

class count(object): 
    def __iter__(self): 
     # offset = 0 because we are at the unpack op 
     return iter(range(expecting(offset=0))) 
+0

+1: यह मेरी तुलना में एक बेहतर हैक है क्योंकि यह सही असाइनमेंट पर जा रहा है। – DSM

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