Can you translate this debugging macro from C++ to python?

后端 未结 6 1173
没有蜡笔的小新
没有蜡笔的小新 2021-01-15 03:06

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

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


        
相关标签:
6条回答
  • 2021-01-15 03:43

    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

    0 讨论(0)
  • 2021-01-15 03:48

    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
    
    0 讨论(0)
  • 2021-01-15 03:54

    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
    
    0 讨论(0)
  • 2021-01-15 03:56

    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?

    0 讨论(0)
  • 2021-01-15 04:03
    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
    
    0 讨论(0)
  • 2021-01-15 04:05

    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
    
    0 讨论(0)
提交回复
热议问题