3

When I call print from eval:

def printList(myList):
    maxDigits = len(str(len(myList)))
    Format = '0{0}d'.format(maxDigits)
    for i in myList:
        eval('print "#{0:' + Format + '}".format(i+1), myList[i]')

it gives an error:

    print "#{0:01d}".format(i+1), myList[i]
        ^
SyntaxError: invalid syntax

I tried to make use of this, and re-wrote it:

def printList(myList):
    maxDigits = len(str(len(myList)))
    Format = '0{0}d'.format(maxDigits)
    for i in myList:
        obj = compile(src, '', 'exec')
        eval('print "#{0:' + Format + '}".format(i+1), myList[i]')

but this complains about the i:

NameError: name 'i' is not defined

P.S. I'm dealing with python2.6

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
Adobe
  • 12,967
  • 10
  • 85
  • 126

4 Answers4

16

You can't eval() a print: eval() is used to evaluate expression, and print is a statement. If you want to execute a statement, use exec(). Check this question for a better explanation:

>>> exec('print "hello world"')
hello world

Now, you can pass your locals() variables if you want to make accessible the i in the exec:

>>> i = 1
>>> exec('print "hello world", i', locals())
hello world 1

In addition, in the last test you wrote, you compile() in 'exec' mode, that should give you a tip :)

Community
  • 1
  • 1
tito
  • 12,990
  • 1
  • 55
  • 75
8

You don't need eval:

def printList(myList):
    maxDigits = len(str(len(myList)))
    str_format = '#{0:0' + str(maxDigits) + '}'
    for i, elem in enumerate(myList, 1):
        print str_format.format(i), elem

or, as @SvenMarnach noted, you can put even the formatting parameter into one format call:

def printList(myList):
    maxDigits = len(str(len(myList)))
    for i, elem in enumerate(myList, 1):
        print '#{1:0{0}} {2}'.format(maxDigits, i, elem)
eumiro
  • 207,213
  • 34
  • 299
  • 261
3

To keep your code while making it shorter and easier to understand:

def printList(myList):
    # int(math.log10(len(myList))+1) would be the appropriate way to do that:
    maxDigits = len(str(len(myList)))
    for i in myList:
        print "#{0:0{1}d}".format(i+1, maxDigits), myList[i]
Gandaro
  • 3,427
  • 1
  • 17
  • 19
1

The simplistic view is this. Build the format separately from using it. Avoid eval().

    format =  "#{0:" + Format + "}"
    print format.format(i+1), myList[i]

Don't make things harder than they need to be. Here's another version that builds the format in one step.

    format = '#{{0:0{0}d}}'.format(maxDigits)
    print format.format(i+1), myList[i]
S.Lott
  • 384,516
  • 81
  • 508
  • 779