More random python observations from a perl programmer
Michael Hudson
mwh21 at cam.ac.uk
Thu Aug 19 13:06:03 EDT 1999
I'm going to be quite picky in some of what follows.
Tom Christiansen <tchrist at mox.perl.com> writes:
> COOLNESS:
> Python's print() function is more like the Perl debugger's
> "x" command; that is, it's recursive and pretty-printed.
Python doesn't have a print() function. It has a `print' statement.
> GOTCHA: (high)
> Local variables are never declared.
*Nothing* is ever delcared in Python.
> GOTCHA: (medium)
> If you have a function that expects two arguments, such as:
> def fn(x,y):
> return x + y
> and you have a tuple of the two elements:
> t = (1,2)
> You can't just call that function:
> print fn(t)
> Or you get a "TypeError: not enough arguments; expected 2, got 1"
> error. You have to use this apply() function to get around this
> issue:
> print apply(fn,t)
> 3
Well, no. How would you like to pass a tuple to a function?
> GOTCHA: (medium)
> Perl's hex() function is the opposite of Python's. Perl's hex
> function converts 22 into 37. Python's hex function converts 37 into
> 0x22. Oh my! Like hex, Python has oct() completely backwards from
> Perl. Python's oct(44) returns 054, but Perl's oct(44) return 36.
This would have to do with strings not being automatically coerced
into numbers, methinks.
> SIMILARITY:
> Constructors and destructors (__init__ and __del__) aren't
> automagically called in parent classes in Python. Neither
> in Perl.
This sucks, IMHO.
> GOTCHA: (medium)
> Things that return lists can't be used where a tuple is expected.
> A function that returns a list must be coerced into a tuple to
> use this, though.
> def fn: return [1,2]
> print "this %d is %d here\n" % fn() # ILLEGAL
> print "this %d is %d here\n" % tuple(fn())
> The illegal part points out that this is an
> TypeError: illegal argument type for built-in operation
> Which isn't very helpful.
I think this may have changed in the CVS sources. <quick check>, Oh
no, it hasn't. It should.
> GOTCHA: (high)
> Python has no manpages! The horror!!!!!!!!!!!!!!!!!!!!!!
> ENODOC
There's info format if you look for it and you have to have a CLI.
> GOTCHA: (low)
> Often Python's error messages leave something to be desired.
> I don't know whether
Is this a joke? This is improving.
> GOTCHA: (medium)
> All ranges are up to but *not including* that point. So range(3)
> is the list [0,1,2]. This is also true in slices, which is the
> real gotcha part. A slide t[2:5] does not include t[5] in it.
This does mean that range(a,b) or t[a:b] has b-a elements in it.
> DISSIMILARITY:
> This also means that instead of substr() in Perl, you slice a string
> as in
> s = "string"
> print s[2:4]
> ri
> Yes, that's all you got. Strange, eh? See below on ranges.
What were you expecting?
> GOTCHA: (medium)
> Slices in Python must be contiguous ranges of a sequence.
> In Perl, there's no such restriction.
At some point Python will probably support `extended slice syntax'
like so:
range(0,10)[1:4:2] => [1,3]
Numerical Python already does this.
> GOTCHA: (medium)
> You can't slice dictionaries at all in Python. In Perl, it's
> easy to slice a hash, and just as sensible.
Huh? What would that mean? There's no reason to suspect that the keys
of a dictionary are ordered.
> GOTCHA: (high)
> As we saw with lists, because everything is a reference, and there's
> no way to dereference that reference, this means that again there
> is also no built-in, intuitive way to copy a dictionary. Instead,
> the suggested work-around is to write a loop:
> new = {}
> for key in old.keys:
> new[key] = old[key]
> But this is guaranteed slower, because it's not at the C level.
new = old.copy()
> GOTCHA: (medium)
> There's no way to set up a permitted exports list. The caller may have
> anything they ask for.
This is a general Python convention; you *can* shoot yourself in the
foot if you try hard enough. Means the debugger can be written in
Python, for one thing.
> COOLNESS:
> DBM files seem (?) to automatically know about nested datatypes.
Ah, that's pickle. pickle is cool.
> GOTCHA: (high)
> Scopes don't nest in Python, but they they do in Pascal, Perl, or C.
> This is supposedly "simpler", but it's very suprising in many ways:
> x = 1 # global
> def fn1():
> x = 10 # implicit local
> def fn2():
> print x # whose?
> fn2()
> fn1()
> The answer is that it prints 1, because fn2 has no x in its local
> scope, so gets the global. The suggested work-around is
> def fn2(x=x):
> using default parameters.
Yes this is a bit annoying. The Right Way to attach state to a
function is a class, of course. Not that that helps much.
> GOTCHA: (low)
> List objects have built-in methods, like
> l.append(x)
> But string objects don't. You have to import
> from the string module to get them, and then they're
> functions, not methods.
This will change in 1.6.
> GOTCHA: (low)
> You have insert and append methods for lists, but only
> a del function.
del statement.
> 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.
Do people really do that? I don't. It can be made safe:
num = eval(string,{'__builtins__':{}})
but that's a bit hairy. Use float instead.
> 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.)
Python is more "dynamically typed" than "typeless", I'd say.
> GOTCHA: (low)
> Regexes default to emacs style, not egrep style!
Not any more. import re.
> GOTCHA: (low)
> Python's eval() only works on expressions, not full code blocks full
> of statements. You need exec() for the whole thing.
Writing exec() suggests it's a function; it isn't, it's a statement.
> GOTCHA: (medium)
> Anything that python doesn't like, it raises an exception about.
> There is no fail-soft. Even non-exception issues raise exceptions.
> It's pervasive. K&P curse languages that force people who want
> to open() a file to wrap everything in exception code, saying that
> "failing to open a file is hardly exceptional".
This is a bit of a flaw, IMHO. Mind you, it forces you to pay
attention.
> GOTCHA: (medium)
> You can't just interchange tuples and lists in python the way
> you can lists and arrays in Perl. This is an error:
> import sys # otherwise, no argv for you, buddy
> print "First arg %s and second %s" % sys.argv[1:3]
> because you need
> print "First arg %s and second %s" % tuple(sys.argv[1:3])
This has been changing over the last year or so. I expect the trend
will continue.
> COOLNESS:
> I believe that Python checks the prototype signature on methods
> as well as on functions. I wonder whether Tim Bunce's ideas run-time
> evaluation of prototypes for Perl might be able to do this.
You mean perl doesn't? Ouch.
> QUESTION:
> What is and what is not thread safe?
Everything is, but in a crude way. There's a global interpreter
lock. This isn't the best of situations.
I hope this post has raised the signal-to-noise ratio in the
perl/Python debate (it could hardly lower it).
Michael
More information about the Python-list
mailing list