Leon Chen
Leon Chen

Reputation: 175

Python variable scoping of two functions

I tried to search the question for a bit but can't find a actual answer. I'm trying to implement a function (magic_debug) so that when called in another function (somefunc), it can access the variable within the somefunc and print it out as follow:

def magic_debug(s, *args, **kwargs):
    s2 = s.format(x=x,y=y,z=args[0])
    print(s2)


def somefunc():
    x = 123
    y = ['a', 'b']
    magic_debug('The value of x is {x}, and the list is {y} of len {z}', len(y))

somefunc()

the expected output --> The value of x is 123, and the list is ['a', 'b'] of len 2

Upvotes: 1

Views: 69

Answers (5)

Change some of your code around to look like this:

def magic_debug(s, *args, **kwargs):
    s2 = s.format(x=args[1],y=kwargs.pop('y', ''),z=args[0])
    print(s2)


def somefunc():
    x = 123
    y = ['a', 'b']
    magic_debug('The value of x is {x}, and the list is {y} of len {z}', len(y), x, y=y)

somefunc()

Your output will be perfect. You're adding the **Kargs but you don't use it. The above code uses the **Karg to store the array.

Output:

The value of x is 123, and the list is ['a', 'b'] of len 2

Edit for fewer arguments:

def magic_debug(s, *args, **kwargs):
    s2 = s.format(x=args[1],y=args[0],z=len(args[0]))
    print(s2)


def somefunc():
    x = 123
    y = ['a', 'b']
    magic_debug('The value of x is {x}, and the list is {y} of len {z}', y, x)

somefunc()

Upvotes: 0

zwer
zwer

Reputation: 25789

If any modification is allowed as long as you keep the spirit of the question, you can use locals() to pass the local scope to the magic_debug function, i.e.:

def magic_debug(s, *args, **kwargs):
    s2 = s.format(z=args[0], **kwargs)
    print(s2)

def somefunc():
    x = 123
    y = ['a', 'b']
    magic_debug('The value of x is {x}, and the list is {y} of len {z}', len(y), **locals())

somefunc()
# The value of x is 123, and the list is ['a', 'b'] of len 2

And if you're allowed to change the function signatures you can pass the locals() without expansion, too. But if you cannot change the function being debugged, then peeking into the previous frame is the only way. @Sraw already covered that in his answer.

Upvotes: 1

0811张庆昊
0811张庆昊

Reputation: 548

Do you mean it?

def magic_debug(s, vars_dict):

    s2 = s.format(**vars_dict)
    print(s2)


def somefunc():
   x = 123         # variables are indent in python
   y = ['a', 'b']  # so they're in the function scope

                   # and so is this function that somefunc calls - 
   vars_dict = vars()
   vars_dict['z'] = len(y)
   magic_debug('The value of x is {x}, and the list is {y} of len {z}', vars_dict)

somefunc()

Upvotes: 1

Sraw
Sraw

Reputation: 20224

This is really a common question, try to use inspect.

def magic_debug(s, *args, **kwargs):
    import inspect
    parent_local_scope = inspect.currentframe().f_back.f_locals
    s2 = s.format(**parent_local_scope, z=args[0])
    print(s2)


def somefunc():
    x = 123
    y = ['a', 'b']
    magic_debug('The value of x is {x}, and the list is {y} of len {z}', len(y))

somefunc()

output:

The value of x is 123, and the list is ['a', 'b'] of len 2

Upvotes: 1

Steven Black
Steven Black

Reputation: 2232

try this - you need to indent your function

def magic_debug(s, *args, **kwargs):

    s2 = s.format(x=x,y=y,z=args[0])
    print(s2)


def somefunc():
   x = 123         # variables are indent in python
   y = ['a', 'b']  # so they're in the function scope

                   # and so is this function that somefunc calls - 
   magic_debug('The value of x is {x}, and the list is {y} of len {z}', len(y))

somefunc()

Upvotes: 0

Related Questions