More random python observations from a perl programmer

Bernhard Herzog herzog at online.de
Thu Aug 19 14:58:03 EDT 1999


Thomas Wouters <thomas at xs4all.nl> writes:

> On Thu, Aug 19, 1999 at 08:22:49AM -0700, Tom Christiansen wrote:

> > DISSIMILARITY:
> >     There are no private variables in a module or a class.
> >     They can always be fully-qualified and accessed from
> >     without.  Perl can do this with file-scoped lexicals,
> >     but still can't do so with data members (modulo obscure
> >     tricks such as using a non-hash for an object).
> 
> There is some namemangling though, for datamembers/functions that start with
> a single _, for hiding/overriding purposes. (those mmebers get the classname
> encoded in, so it's dependant on the class it was called on.)

For class members it's a leading double underscore.

The single leading underscore only affects module globals in that they
are *not* imported by 'from module import *'


> > GOTCHA: (low)
> >     You have insert and append methods for lists, but only
> >     a del function.  Why is it a function not a method, and

del is a statement, not a function. 

> > GOTCHA: (high)
> >     Because you can't use readline() to get a number, people seem to enjoy
> >     calling eval() just to get a string turned into a number:
> > 	import sys
> > 	str = sys.stdin.readline()
> > 	num = eval(x)
> >     This is scary.  Even scarier is the propensity for calling input(),
> >     which auto-eval()s its input to make sure it's the right "type".
> >     (Funny that a soi-disant "typeless language" should be so danged
> >     picky about this.)  That means you see people write:
> > 	num = input("Pick a number? ")
> >     But the person can supply as an answer 0x23 or 2+9 or pow(2,4)
> >     or os.system("rm -rf *").  I am stunned.
> 
> Try eval(number, {}, {}). No sys or os module to call, no other variables
> what so ever. 

Passing empty dicts is not enough. You still have access to all builtin
functions:

>>> s = '''eval(compile("import os; os.system('pwd')", "", "exec"))'''
>>> eval(s, {}, {})
/home/herzog

You can disable the builtins by defining a '__builtins__' item in the
globals dict:

>>> eval(s, {'__builtins__':{}}, {})
Traceback (innermost last):
  File "<stdin>", line 1, in ?
  File "<string>", line 0, in ?
NameError: eval
>>> 

See the rexec module.


The safest way to read a number interactively is probably to use
raw_input and to convert the string explicitly to an int or float with
int() or float() respectively. You loose the automatic recognition of
ints and floats and syntaxes for octal or hexadecimal numbers, though.

A standard function eval_literal() that works like eval() but only
accepts literals would be convenient for this. E.g.

eval_literal('1.0')		-> float 1.0
eval_literal('0x10')		-> int 16
eval_literal('(10, "hallo")')	-> tuple with int a string
eval_literal('sin(0.5)')	-> raise exception


-- 
Bernhard Herzog	  | Sketch, a drawing program for Unix
herzog at online.de  | http://www.online.de/home/sketch/




More information about the Python-list mailing list