Can you translate this debugging macro from C++ to

2019-02-19 18:55发布

I use this very helpful macro when developing in C++:

#define DD(a) std::cout << #a " = [ " << a << " ]" << std::endl;std::cout.flush();

Could you help me implement the same idea in python? I don't know how the #a could be implemented with a python function...

6条回答
Anthone
2楼-- · 2019-02-19 19:06

As @Andrea Spadaccini and @adirau point out, it is not possible to reliably map values back to Python variable names. You could trawl through all namespaces looking for some variable name that references the given value, but that would be fighting the system and liable to return the wrong variable name.

Much easier it is to just pass the variable name:

import inspect
def pv(name):
    frame,filename,line_number,function_name,lines,index=inspect.getouterframes(
        inspect.currentframe())[1]    
    # print(frame,filename,line_number,function_name,lines,index)
    val=eval(name,frame.f_globals,frame.f_locals)
    print('{0}: {1}'.format(name, val))


a=5
pv('a')

yields:

a: 5
查看更多
Anthone
3楼-- · 2019-02-19 19:10
import sys

def DD(expr):
    frame = sys._getframe(1)
    print '%s = %s' % (expr, repr(eval(expr, frame.f_globals, frame.f_locals)))

GLOBAL_VAR = 10

def test():
    local_var = 20
    DD('GLOBAL_VAR + local_var')


>>> test()
GLOBAL_VAR + local_var = 30
查看更多
叛逆
4楼-- · 2019-02-19 19:13

I think that this cannot be done.

The debugging macro that you posted works because it is expanded before compilation, during pre-processing, when you know the variable name. It is like you write all those couts by yourself.

Python does not have a pre-processor (AFAIK), there are external tools that do a similar thing (pyp and others), but you can not define a macro with the standard language.

So you should do your trick at run-time. Well, at run-time you don't know the "name" of the variable because the variable is just a reference to an object, when you call a method you call it on the object, not on the "variable". There can be many variables that point to that object, how does the object know which variable was used to call the method?

查看更多
该账号已被封号
5楼-- · 2019-02-19 19:13

You can't get a variable (well, object)'s name in python. But you can pass the object's name to get its value (kinda the opposite of what you do with that macro)

>>> a=4
>>> locals()['a']
4

EDIT: a detailed explanation may be found here

查看更多
爷、活的狠高调
6楼-- · 2019-02-19 19:18

The Rod solution is perfectly usable. It could be even extended to handle many vars. But you can get close to that with much less magic:

def dd(**kwargs):
    print ", ".join(str(k) + "=" + str(v) for k, v in kwargs.iteritems())

a = 1
dd(a=a,b=3)

output:

a=1, b=3
查看更多
萌系小妹纸
7楼-- · 2019-02-19 19:30

You could inspect the stack trace and "parse" it. Since you know the name of your function (dd in this case) it becomes fairly easy to find the call and extract the name of the variable.

    import inspect
    import re

    def dd(value):
        calling_frame_record = inspect.stack()[1]
        frame = inspect.getframeinfo(calling_frame_record[0])
        m = re.search( "dd\((.+)\)", frame.code_context[0])
        if m:
            print "{0} = {1}".format(m.group(1), value)

    def test():
        a = 4
        dd(a)

    test()

Output

a = 4
查看更多
登录 后发表回答