2012-01-13 13 views
7

सी/सी ++ में पास किया गया था, मुझे मैक्रो को परिभाषित करने के लिए डिबगिंग करते समय अक्सर यह उपयोगी होता है, ECHO(x) कहता है, जो वैरिएबल नाम और उसके मान को मुद्रित करता है (यानी ECHO(variable) हो सकता है प्रिंट variable 7)। here वर्णित के रूप में आप 'स्ट्रिंगफिकेशन' ऑपरेटर # का उपयोग कर मैक्रो में परिवर्तनीय नाम प्राप्त कर सकते हैं। क्या Python में ऐसा करने का कोई तरीका है?एक पाइथन वैरिएबल का नाम ढूंढें जो एक फ़ंक्शन

दूसरे शब्दों में, मैं एक समारोह

def echo(x): 
    #magic goes here 

जो, अगर foo=7; echo(foo) (या foo=7; echo('foo'), हो सकता है) के रूप में कहा जाता है, foo 7 प्रिंट आउट होगा चाहते हैं। मुझे एहसास है कि यह करने के लिए यह छोटा है अगर मैं चर और उसके नाम दोनों को फ़ंक्शन पर पास करता हूं, लेकिन मैं डिबगिंग करते समय इस तरह के कार्यों का उपयोग करता हूं, और पुनरावृत्ति हमेशा मुझे परेशान करती है।

उत्तर

7
नहीं

वास्तव में समाधान है, लेकिन काम हो सकता है (वैसे भी आप प्रश्न में echo('foo') है):

def echo(**kwargs): 
    for name, value in kwargs.items(): 
     print name, value 

foo = 7 
echo(foo=foo) 

अद्यतन: साथ inspect

import inspect 
import re 

def echo(arg): 
    frame = inspect.currentframe() 
    try: 
     context = inspect.getframeinfo(frame.f_back).code_context 
     caller_lines = ''.join([line.strip() for line in context]) 
     m = re.search(r'echo\s*\((.+?)\)$', caller_lines) 
     if m: 
      caller_lines = m.group(1) 
     print caller_lines, arg 
    finally: 
     del frame 

foo = 7 
bar = 3 
baz = 11 
echo(foo) 
echo(foo + bar) 
echo((foo + bar)*baz/(bar+foo)) 

आउटपुट echo(foo) के लिए समाधान:

foo 7 
foo + bar 10 
(foo + bar)*baz/(bar+foo) 11 

इसमें सबसे छोटी कॉल है, लेकिन यह न्यूलाइन के प्रति संवेदनशील है, उदा।:

echo((foo + bar)* 
     baz/(bar+foo)) 

प्रिंट होगा: दूसरा समाधान अत्यंत चतुर है

baz/(bar+foo)) 11 
+0

है। काम करते समय यह कैसे काम करता है, मुझे एक डुप्लिकेट प्रश्न मिला [यहां] (http://stackoverflow.com/questions/5503363/can-you-translate-this-debugging-macro-from-c-to-python) - हालांकि आपका रेगेक्स वहां दिए गए समान उत्तर से थोड़ा अधिक मजबूत है। – James

+0

महान उत्तर, धन्यवाद। क्या आप संक्षेप में बता सकते हैं कि रेगेक्स कैसे काम करता है? – Ferguzz

+0

@ फ़र्गज़, यह 'echo', फिर '\ s *' - 0 या कई रिक्त स्थान की खोज करता है, '\ (' - कोष्ठक, '(। +?) \) $' - गैर-greddy सभी प्रतीकों के लिए ' \) '(कोष्ठक) लाइन के अंत में (' $ ')। Http://www.regular-expressions.info/repeat.html पर अधिक जानकारी। आप [regexps डीबग भी कर सकते हैं] (http://stackoverflow.com/a/143636/1052325)। इंटरैक्टिव पायथन सत्र में आज़माएं: 're.compile (r'echo \ s * \ ((। +?) \) $ ', Re.DEBUG)' – reclosedev

3
def echo(x): 
    import inspect 
    print "{0}: {1}".format(x, inspect.stack()[1][0].f_locals[x]) 
y = 123 
echo('y') 
# 'y: 123' 

यह भी देखें: https://stackoverflow.com/a/2387854/16361

ध्यान दें कि यह जीसी समस्याओं का कारण बन सकते हैं:

http://docs.python.org/library/inspect.html#the-interpreter-stack

यह भी लोग हैं, जो फ्रेम के साथ खिलवाड़ द्वारा जला दिया गया है बंद हो जाएगा, और छोड़ सकते हैं आपके मुंह में एक बुरा स्वाद। लेकिन यह काम करेगा।

3

यहां एक समाधान है जिसे आपने इसे कॉल करने के लिए थोड़ा और टाइप किया है। यह locals में निर्मित समारोह पर निर्भर करता है:

def print_key(dictionary, key): 
    print key, '=', dictionary[key] 


foo = 7 
print_key(locals(), 'foo') 

एक echo अर्थ विज्ञान आप का उल्लेख के साथ inspect मॉड्यूल का उपयोग कर भी संभव है,। हालांकि, निरीक्षण के दस्तावेज में चेतावनियां पढ़ें। यह एक बदसूरत गैर पोर्टेबल हैक (यह पायथन के सभी कार्यान्वयन में काम नहीं करता है)। डीबगिंग के लिए केवल इसका इस्तेमाल करना सुनिश्चित करें।

विचार कॉलिंग फ़ंक्शन के locals को देखना है। निरीक्षण मॉड्यूल केवल यह अनुमति देता है: f_back विशेषता द्वारा एकत्रित फ्रेम ऑब्जेक्ट्स द्वारा कॉल का प्रतिनिधित्व किया जाता है। प्रत्येक फ्रेम के स्थानीय और वैश्विक चर उपलब्ध हैं (यहां भी निर्मित हैं, लेकिन आपको उन्हें प्रिंट करने की आवश्यकता नहीं है)।

inspect docs में बताया गया है कि आप संदर्भ चक्र को रोकने के लिए किसी भी संदर्भ फ्रेम ऑब्जेक्ट को स्पष्ट रूप से हटाना चाहते हैं, लेकिन यह कड़ाई से जरूरी नहीं है - कचरा संग्रह उन्हें जल्द या बाद में मुक्त कर देगा।

import inspect 

def echo(varname): 
    caller = inspect.currentframe().f_back 
    try: 
     value = caller.f_locals[varname] 
    except KeyError: 
     value = caller.f_globals[varname] 
    print varname, '=', value 
    del caller 

foo = 7 
echo('foo') 
संबंधित मुद्दे