[Tutor] How do I do this in python?

Lie Ryan lie.1296 at gmail.com
Thu Jun 11 14:30:51 CEST 2009


Robert Lummis wrote:
> I want to write a function that I can use for debugging purposes that
> prints the values of whatever list of object references it is given as
> arguments, without knowing in advance how many object references it
> will be called with or what they might be. For example, the call:
> show(a,b,c) would output the values of the arguments like this:

In python, most objects does not know its own name (there are few
exceptions such as function and class object). An object may have
multiple names and often no name at all (e.g. objects inside a list,
constants). In fact, when the code is compiled to bytecode, all local
names (but not globals) are discarded and turns into some sort of array
access. So... the best solution would be:

print("a = ", a)

for globals this might work:
>>> def show(name):
...    value = eval("repr(%s)" % name)
...    print('%s = %s' % (name, value))
...
>>> g = 10
>>> show("g")
g = 10

for one that works with locals (although it's a bit of inconvenient as
you have to pass the locals() around):

>>> def show2(name, local):
...     value = eval('repr(%s)' % name, globals(), local)
...     print('%s = %s' % (name, value))
...
>>> g = 10
>>> show2('g', {})
g = 10
>>> def func(foo):
...     bar = 'abc'
...     show2('foo', locals())
...     show2('bar', locals())
...
>>> func(123)
foo = 123
bar = 'abc'

please note that some people might object to the liberal and careless
use of eval()... a more sophisticated approach would check that `name`
only contains alphanumeric characters that is valid identifiers

Aa more sophisticated approach might also use the *args, **kargs
variadic parameter construct...

>     a = 3
>     b = 'john'
>     c = 'Monday'
> 
> while show (x) would output (for example):
> 
>     x = 3.14
>
> of course displaying whatever the actual current values are. For a
> collection object it would make sense to output just the first few
> values.

If you need a custom print behavior, you need to override the object's
__str__ (and sometimes __repr__). Either that or something like this:

def myprint(*args):
    parens = {list: ('[', ']'), tuple: ('(', ')')}
    for arg in args:
        if isinstance(arg, (list, tuple)) and len(arg) > 5:
            open, close = parens[type(arg)]
            print('%s%s, %s, %s, ..., %s%s' % (open, arg[0], arg[1],
arg[2], arg[-1], close))
        else:
            print(arg)

>>> myprint(12, 'acv', [1, 2], [1, 4, 5, 6, 7, 8, 3, 2])
12
acv
[1, 2]
[1, 4, 5, ..., 2]

> So within the 'show' function definition I have to somehow get a list
> of the literal argument names it was called with and then use the
> names as globals to get the values. How do I do that?

If you're referring to this construct:

def func(a, b, opt=None, *args, **kargs):
    # args is a `list` of extra positional arguments
    # kargs is a `dict` of extra keyword arguments
    #
    # a and b are required parameters
    # opt is optional parameter with default value None


> If this can't be done but there is a completely different way to
> achieve a similar result, what is it?
> 
> I'm trying to learn python but it's a struggle because the
> documentation is so dispersed. If there is a solution to this
> question, what documentation could I have looked at to find it on my
> own?
>
> BTW I'm using python 3.01 if it matters.

You should use python 2.x for now. The documentations and various
tutorials for python 3.x hasn't caught up with the amount that python
2.x already has. Python 3.0 beginner tutorial is still very rare; most
python 3.x tutorials are aimed towards programmers that have used python
2.x and want to switch their codes to python 3.x.

I guess it will be around the release of python 3.2 when most Linux/Unix
python distro/projects have adapted their codes to python 3.x before we
start seeing beginner python 3.x tutorials popping around.



More information about the Tutor mailing list