More random python observations from a perl programmer
Thomas Wouters
thomas at xs4all.nl
Thu Aug 19 11:48:00 EDT 1999
On Thu, Aug 19, 1999 at 08:22:49AM -0700, Tom Christiansen wrote:
> This article was posted to the Perl newsgroup, but I have duplicated
> the posting here without crossposting to avoid flame wars.
Sorry, i have to reply. I wont mention much, and i definately dont want to
start a flame war (i use perl about as often as python, but python fits my
soul, perl does not.)
> GOTCHA: (low)
> You can't use "in" on dicts. Instead, you must use
> d = { "fred":"wilma", "barney":"betty" }
> if d.has_key("fred"): # legal
> if "fred" in d: # ILLEGAL
> I don't understand why this was done.
It's an extension of Python's setup. Not everything is done to be immediately
obvious, but everything is done to be _consistent_, and instantly obvious if
you understand python. The 'in' statement works sort of like the pseudocode:
index = 0
try:
while 1:
if sequence[index] == findthis:
return index - 1
index = index + 1
except IndexError:
return 0
(same for the 'for' statement.)
You could of course write a dictionary wrapper that takes numeric arguments
to the __getitem__ to be index in a sorted list of keys, and other arguments
as normal key retrieval... but you'd lose the ability to index on numbers.
> GOTCHA: (low)
> I don't understand why we have so many C operators, such as "&" and
> "|" and "~", but we don't have "&&" or "||" or "!" We also have "<<"
> and ">>". It's bizarre that the relational and "?:" are missing.
> Python uses so much from C to make people see what they expect to see,
> but this is missing. Why?
&& and || are and and or.
> GOTCHA: (low)
> There are no loop labels, and therefore "break" and "continue" are
> only through the next level. This encourages the proliferation of
> spurious boolean condition variables. It was annoying when Pascal
> made you do the same thing. There is no "goto", which is how C
> works around it. As with many things in Python, here you force the
> user to be tangled up with exceptions just to do very simple things.
> That's not as clear a solution.
Only if you aren't used to exceptions. Exceptions are really very simple and
nice things. Especially back when they were just strings (before my time, but
still ;-)
> DISSIMILARITY:
> Python uses [] to create a new empty list, which you
> then reference with [] subscripts.
> Perl uses [] to create a new empty array, which you
> then reference with [] subscripts.
> Python uses {} to create a new empty dictionary, which you
> then reference with [] subscripts.
> Perl uses {} to create a new empty hash, which you
> then reference with {} subscripts.
You forget tuples, which you create with (), and subscript with [].
Subscripting is _always_ done with [], and it _always_ calls the
'__getitem__' member function (if any). There being no functional difference
is what makes it so nice :)
> DISSIMILARITY:
> A class method call gets no class name as its implicit extra
> argument the way an instance method would.
that's because it doesn't know what class it's going to be called with. You
can assign it to another class on the fly :)
> DISSIMILARITY:
> In Python, there is no difference between single and double quotes:
> both interpolate C-style escapes like \t, and neither
> interpolates variables. In Perl, single quotes do neither escapes
> nor variables, but double quotes do both.
There are 'raw' strings though, 'r"<string>"', that dont do backslashes.
> 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.)
> GOTCHA: (high)
> Python has no manpages! The horror!!!!!!!!!!!!!!!!!!!!!!
> ENODOC
Damn, i hadn't even noticed that. Can you imagine ? I guess the '__doc__'
attributes on objects are enough manpage for me. ;)
> DISSIMILARITY:
> Python doesn't convert between strings and numbers unless you tell
> it to. And if you don't tell it to, you get an exception. Therefore
> you have no idea what these
> x = y + z
> x = y - z
> x = y * z
> are really doing. The first would concat strings or lists, the last would
> repeat them. Personally, I don't care for this, because I always
> wonder what subtracting one string or list from another would be.
It's worse. _noone_ has any idea what you're doing until you're acutally
doing it. x, y and z can be any type of object, even a type of object that's
loaded in on demand or constructed on the fly.
> GOTCHA: (high)
> This is a big surprise: strings are not atomic (although they are
> immutable). They are instead sequences of characters. This comes
> up in strange places. For example:
> >>> for c in ("weird", "bits"):
> ... print c
> ...
> weird
> bits
> >>> for c in ("weird"):
> ... print c
> ...
> w
> e
> i
> r
> d
> The second case autosplit the characters! Here's another:
> >>> print map(None, "stuff")
> ['s', 't', 'u', 'f', 'f']
> >>> print map(None, "stuff", "here")
> [('s', 'h'), ('t', 'e'), ('u', 'r'), ('f', 'e'), ('f', None)]
> (Python's map None is like Perl's map $_.)
Wait, wait, you're doing two different things here. First off, you called
'for' with different types of arguments, the first time with a tuple of
strings, the second type with just a string. As a string is a sequence
object, it can be indexed, and the for loop wil 'iter' over the characters
in it. Perhaps you meant to do:
>>> for c in ("weird",):
... print c
...
weird
Or maybe
>>> for c in ("weird" + "bits"):
... print c
...
w
e
i
r
d
b
i
t
s
But they are definately not the same :)
As for the map(), almost the same. In the first instance you provide one
sequence, so map will pass 'None' a single argument, in the second 'None'
gets passed two items, and None returns it right back. If you want the
sequences turned into lists and concatenated, use + instead of ,
> GOTCHA: (high)
> Because everything is a reference, and there's no way to dereference
> that reference, it turns out that there is no trivial way to copy
> a list! This fails:
> x = [1,2]
> y = x
> Because you don't get a new list there, just a copy to an
> old one. Suggested work-arounds include
> y = x[0:]
> y = x[:]
> y = x + []
> y = x * 1
> This forces people to think about references, again.
> So much for lists being first class citizens! Compare
> this with Perl's
> @x = (1,2);
> @y = @x;
> Or even with references:
> $x = [1,2];
> $y = [ @$x ];
> or
> @y = @$x;
>>> import copy
>>> print copy.__doc__
Generic (shallow and deep) copying operations
=============================================
<etc>
> GOTCHA: (low)
> You have insert and append methods for lists, but only
> a del function. Why is it a function not a method, and
> why isn't it spelled out? Apprently the fashionable wayto do this is
> now
> a[2:3] = []
> Which of course, deletes only one element. ARG.
You can del a[3], or del a[3:5]
> 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. Personally, i think being able to say, say, '4**5/3%2' in any
instance where the program asks you for a number is a coolness.
> GOTCHA: (low)
> Regexes default to emacs style, not egrep style! Gads! This is
> surprising to anyone except an emacs weenie. Sigh. And just *try*
> to read the manpage on the differences based on passed in arguments
> establishing the style. There aren't any manpages! Have a nice day.
Use re, perl regexps.
> And I'd jolly well like to know why I wasn't allowed to use
> print "int of %f is %.0f" % (2.5) * 2
> or if needed,
> print "int of %f is %.0f" % ( (2.5) * 2 )
Try print "int of %f is %.0f" % ((2.5,) * 2 )
"Yes, the trailing comma counts" :)
> QUESTION:
> What is and what is not thread safe?
Everything is thread safe. Or rather, there will at all times be only one
thread executing the Python interpreter.
Oh, damn, i erased the pow() thing. Well, anyway,
>>> 2**2**2
16
>>> 4**4**4
Traceback (innermost last):
File "<stdin>", line 1, in ?
OverflowError: integer pow()
>>> 4**4**4L
13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084096L
Is that what you meant ? You missed that gotcha... no automatic conversion
between int and longint. <wink>
The worst thing about python is what it does to your programming skills. gcc
is getting tired of warning me of syntax errors due to python syntax in my C
:-)
Pyton'ly y'rs,
--
Thomas Wouters <thomas at xs4all.net>
Hi! I'm a .signature virus! copy me into your .signature file to help me spread!
More information about the Python-list
mailing list