472,096 Members | 1,531 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,096 software developers and data experts.

Python newbie

I am a Python newbie who decided to see what that Python fuss is all about.
Quite frankly, I am a bit perplexed. After having had few months of
experience with Perl (started in 1994 with Perl v4, and doing it ever
since) , here is what perplexes me:

perl -e '@a=(1,2,3); map { $_*=2 } @a; map { print "$_\n"; } @a;'

The equivalent in Python looks like this:

Python 2.5.1 (r251:54863, Jun 15 2008, 18:24:51)
[GCC 4.3.0 20080428 (Red Hat 4.3.0-8)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>a=[1,2,3]
map((lambda x: 2*x),a)
[2, 4, 6]
>>map((print),a)
File "<stdin>", line 1
map((print),a)
^
SyntaxError: invalid syntax
>>for x in a: print x
....
1
2
3
>>for x in a: x=2*x
....
>>for x in a: print x
....
1
2
3
>>>
There are several questions:

1) Why is the array "a" unchanged after undergoing a transformation with
map?
2) Why is it illegal to pass a built-in function "print" to map?
3) Why is the array "a" unchanged after undergoing an explicit
transformation with the "for" loop?
4) Is there an equivalent to \$a (Perl "reference") which would allow me to
decide when a variable is used by value and when by reference?

PHP also allows changing arrays with "foreach" loop:
#!/usr/local/bin/php
<?php
$a=array(1,2,3);
foreach($a as &$x) { $x=$x*2; }
array_walk($a,create_function('$a','print("$a\n"); '));
?>

How can I make sure that
for x in a: x=2*x

actually changes the elements of the array "a"?
http://mgogala.freehostia.com
Sep 19 '08 #1
10 1274
Mladen Gogala wrote:
I am a Python newbie who decided to see what that Python fuss is all about.
Quite frankly, I am a bit perplexed. After having had few months of
experience with Perl (started in 1994 with Perl v4, and doing it ever
since) , here is what perplexes me:

perl -e '@a=(1,2,3); map { $_*=2 } @a; map { print "$_\n"; } @a;'

The equivalent in Python looks like this:

Python 2.5.1 (r251:54863, Jun 15 2008, 18:24:51)
[GCC 4.3.0 20080428 (Red Hat 4.3.0-8)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>a=[1,2,3]
map((lambda x: 2*x),a)
[2, 4, 6]
>>>map((print),a)
File "<stdin>", line 1
map((print),a)
^
SyntaxError: invalid syntax
>>>for x in a: print x
...
1
2
3
>>>for x in a: x=2*x
...
>>>for x in a: print x
...
1
2
3

There are several questions:

1) Why is the array "a" unchanged after undergoing a transformation with
map?
Because you evaluated an expression in which a was a variable, giving an
entirely new object as a result.
2) Why is it illegal to pass a built-in function "print" to map?
Because at present "print" isn't a built-in function, it's a keyword
designating a specific statement type. Try using sys.stdout.write instead.
3) Why is the array "a" unchanged after undergoing an explicit
transformation with the "for" loop?
Because you aren't transforming a. You are extracting references to a's
elements into a separate variable and rebinding that variable to a new
value, leaving the references in a's elements pointing to the original
objects.
4) Is there an equivalent to \$a (Perl "reference") which would allow me to
decide when a variable is used by value and when by reference?
No. Python implicitly dereferences all names when using them to compute
values, and only uses them as references on the left-hand side of an
assignment.

Please note the above statement is contentious, and will likely bring a
horde of screaming fanatics of various flavors down on my head for
terminological inexactitude.
PHP also allows changing arrays with "foreach" loop:
#!/usr/local/bin/php
<?php
$a=array(1,2,3);
foreach($a as &$x) { $x=$x*2; }
array_walk($a,create_function('$a','print("$a\n"); '));
?>

How can I make sure that
for x in a: x=2*x

actually changes the elements of the array "a"?
By saying something like

a = [2*x for x in a]

You don't modify the individual elements, you create a new list and
rebind a to that. AIf you insist on changing the elements of a, a more
cumbersome alternative is

for i, x in enumerate(a):
a[i] = 2+x

regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
Holden Web LLC http://www.holdenweb.com/

Sep 19 '08 #2
On Fri, 19 Sep 2008 09:13:48 +0200, Mladen Gogala wrote:
There are several questions:

1) Why is the array "a" unchanged after undergoing a transformation with
map?
Because `map()` creates a new list and doesn't change the elements in `a`.
2) Why is it illegal to pass a built-in function "print" to map?
Because ``print`` isn't a function but a keyword. This will be changed
in PythonÂ*3.0. On the other hand this use case is discouraged because
`map()` builds a new list with the return value of the given function.
So you would build a list full of `None`\s just for the side effect.
3) Why is the array "a" unchanged after undergoing an explicit
transformation with the "for" loop?
Because there is no explicit transformation. The loop binds elements to
the name `x` in your example and within the loop you rebind that name to
another value. Neither the name `x` nor the objects bound to it have any
idea that the object might be referenced in some container object.
4) Is there an equivalent to \$a (Perl "reference") which would allow me
to decide when a variable is used by value and when by reference?
No, variables in Python are always name to object bindings. Don't think
of variables as boxes with names on it where you put objects in, or
references to another box. Think of objects and sticky notes with names
on it.
How can I make sure that
for x in a: x=2*x

actually changes the elements of the array "a"?
Well, actually change the elements. ;-)

Either:

for index, item in enumerate(sequence):
sequence[index] = func(item)

Or:

sequence[:] = map(func, sequence)

But the need to do so doesn't seem to be that frequent. Usually one just
builds a new list instead of altering an existing one.

Ciao,
Marc 'BlackJack' Rintsch
Sep 19 '08 #3
On Fri, 19 Sep 2008 09:13:48 +0200, Mladen Gogala wrote:
I am a Python newbie who decided to see what that Python fuss is all
about. Quite frankly, I am a bit perplexed.
Naturally you will be perplexed if you assume that Python is just Perl
with a more verbose syntax. It isn't.

After having had few months
of experience with Perl (started in 1994 with Perl v4, and doing it ever
since) , here is what perplexes me:

perl -e '@a=(1,2,3); map { $_*=2 } @a; map { print "$_\n"; } @a;'

The equivalent in Python looks like this:
Actually, no it doesn't. The equivalent looks more like this:
$ python -c 'a=[1,2,3]; a=[2*x for x in a];
for x in a:
print x'
2
4
6

Now, to go on with your questions:
1) Why is the array "a" unchanged after undergoing a transformation with
map?

Because it hasn't undergone a transformation at all. The list (not array)
a remains unchanged, because map returns a new list.
2) Why is it illegal to pass a built-in function "print" to map?
Because print is not a function, it is a statement. However, in Python 3,
that design wart has been corrected.

3) Why is the array "a" unchanged after undergoing an explicit
transformation with the "for" loop?

Because the list a hasn't undergone any such transformation. Rebinding a
name is not an explicit transformation to the object that used to be
bound to the name. And if that sentence is gobbledygook to you, that
demonstrates that Python is not Perl and you shouldn't assume a one-to-
one semantic relationship between syntactical elements.
4) Is there an equivalent to \$a (Perl "reference") which would allow me
to decide when a variable is used by value and when by reference?
Python is neither call-by-reference nor call-by-value, although you will
have many people swear black and blue that it is one or the other. With
respect to all of them, they are wrong. Python's calling model is "call
by object". See here for more detail:

http://effbot.org/zone/call-by-object.htm
If you insist on a false dichotomy between call-by-reference and call-by-
value, then you won't often go wrong if you think of Python:

- being almost always call-by-reference, except for some odd corner cases
which look almost, but not quite, like call-by-value;

- being almost always call-by-value, but only if you think of the values
as pointers.

How can I make sure that
for x in a: x=2*x

actually changes the elements of the array "a"?
By explicitly changing the elements of the list. Here's one very old-
fashioned way of doing so:
>>a = [1,2,3]
for i in range(len(a)):
.... a[i] = a[i]*2
....
>>a
[2, 4, 6]
Here's a more Pythonic alternative:
>>a = [1,2,3]
a = [2*x for x in a]

--
Steven
Sep 19 '08 #4
On Fri, 19 Sep 2008 03:34:50 -0400, Steve Holden wrote:
Please note the above statement is contentious, and will likely bring a
horde of screaming fanatics of various flavors down on my head for
terminological inexactitude.
A pox on you and your descendants onto the tenth generation!
*wink*
--
Steven
Sep 19 '08 #5
Steve Holden wrote:
No. Python implicitly dereferences all names when using them to compute
values, and only uses them as references on the left-hand side of an
assignment.

Please note the above statement is contentious, and will likely bring a
horde of screaming fanatics of various flavors down on my head for
terminological inexactitude.
Actually, I am not a "screaming fanatic". I just want to learn. I am not
trying to compare Perl or PHP with Python. I don't know enough Python to
do that. I see an exponential increase in the use of Python and I want to
find out why is that. I don't plan on discarding my knowledge of Perl and
PHP and I don't know enough Python to make a reasonable comparison. whether
I will use Python on regular basis or not is still to be decided. One thing
is certain: it's easier to use what I already know but then, that's not the
point. I've heard very good things about Django and TurboGears and I got
my hands on the tool called orasachemadoc which is written in Python and
I want to check it out. True, I am coming from the "dark side", but I have
no preconceptions and am not a "screaming fanatic". Let me introduce myself:

http://www.dba-oracle.com/t_dbi_interface1.htm
http://www.rampant-books.com/book_2005_2_php_oracle.htm
http://www.oracle.com/technology/pub...a-symfony.html

Those articles are the only ones that are scripting related. There are some
other articles about Oracle, of no interest for this group. I am 47 years
old and I have learned many programming languages in my time. Learning
Python doesn't seem like a huge task. Conquering my own preconceptions
stemming from a very long use of other programming languages will not be a
big problem, either.

Hopefully, this explains who am I and what is my motivation for delving into
Python. I share your fears of screaming fanatics, too.

--
http://mgogala.freehostia.com
Sep 19 '08 #6
Mladen Gogala wrote:
Steve Holden wrote:
>No. Python implicitly dereferences all names when using them to compute
values, and only uses them as references on the left-hand side of an
assignment.

Please note the above statement is contentious, and will likely bring a
horde of screaming fanatics of various flavors down on my head for
terminological inexactitude.

Actually, I am not a "screaming fanatic". I just want to learn.
I'm sure Steve can speak for himself, but just to clarify:
the "screaming fanatics" referred to are those within the
Python community whose opinions of the terminology used are
at variance with Steve's. I think it was a comment which would
mean more to those of us who've seen such terminology-battles
come and go over the years.

But thanks for introducing yourself anyway. Knowing more about
where a poster is coming from never hurts when trying to answer
their questions. :)

TJG
Sep 19 '08 #7
On 19 sep, 10:13, Steven D'Aprano
<ste...@REMOVE.THIS.cybersource.com.auwrote:
On Fri, 19 Sep 2008 09:13:48 +0200, Mladen Gogala wrote:
I am a Python newbie who decided to see what that Python fuss is all
about. Quite frankly, I am a bit perplexed., here is what perplexes me:
perl -e '@a=(1,2,3); map { $_*=2 } @a; map { print "$_\n"; } @a;'
>
Naturally you will be perplexed if you assume that Python is just Perl
with a more verbose syntax. It isn't.
Indeed, it isn't ... at all:
$ python -c 'for s in [2*x for x in (1, 2, 3)]: print s'
2
4
6

And it's always (a lot) more readable :-)

kb
Sep 19 '08 #8
On 2008-09-19, Mladen Gogala <go***********@gmail.comwrote:
Steve Holden wrote:
>No. Python implicitly dereferences all names when using them
to compute values, and only uses them as references on the
left-hand side of an assignment.

Please note the above statement is contentious, and will
likely bring a horde of screaming fanatics of various flavors
down on my head for terminological inexactitude.

Actually, I am not a "screaming fanatic".
Steve was refering hyperbolically to people like me who find it
entertaining to argue about obscure technical points involving
useless, degenerate bits of example code. It's one of the
things we do here instead of Perl golfing. Though off hand I
don't really see anything much wrong with the statement for
which Steve predicted an impending onslaught of language
lawyers -- unless one wanted to jump right away into the stock
discussion on name-rebinding vs. dereferencing-pointer-lvalues
that we generally save for C/C++ programmers. I only used Perl
once about 15 years ago (that was more than enough for me), but
I would have guessed that an assigment in Perl was a
name-(re)binding more akin to Python than a store to a
variable's memory location like C/C++/Pascal/etc.
Hopefully, this explains who am I and what is my motivation
for delving into Python. I share your fears of screaming
fanatics, too.
We're actually quite harmless and much friendlier than those in
most other newsgroups.

--
Grant Edwards grante Yow! My EARS are GONE!!
at
visi.com
Sep 19 '08 #9
On 19 Sep 2008 08:13:05 GMT, Steven D'Aprano wrote:
On Fri, 19 Sep 2008 09:13:48 +0200, Mladen Gogala wrote:
[snip]
>perl -e '@a=(1,2,3); map { $_*=2 } @a; map { print "$_\n"; } @a;'

The equivalent in Python looks like this:

Actually, no it doesn't. The equivalent looks more like this:
$ python -c 'a=[1,2,3]; a=[2*x for x in a];
for x in a:
print x'
2
4
6
Good job, SD'A.

A note for Mladen Gogala: the [...for...] construction in

a=[2*x for x in a];

is called a list comprehension, and is wonderful for shortening
and clarifying code. One of the pleasures of following this
group is watching the old hands answer noob questions with one
or two list comprehensions.

--
To email me, substitute nowhere->spamcop, invalid->net.
Sep 19 '08 #10
Mladen Gogala:

Welcome to Python, you will need only one or few weeks to be able to
write useful Python programs. But even with the help of a good book
(that I suggest you to read) you may need several months or one year
to master it :-)
2) Why is it illegal to pass a built-in function "print" to map?
Maybe because one of the few original design mistakes of Python. The
new Python 3.0 "fixes" that problem, in Python 3 print is now a
function, so you can use it where you can use functions.
But in general I think it's better to not give map() a function that
has side effects like print().
So you want to use a list comp there instead, and create a new list:
[2 * el for el in a]

In Python (and several other modern languages, like Scala, plus some
more functional languages) you will find that people often prefer to
create new data structures instead of modifying old ones. This may
sound like a waste of memory and time, but using a more immutable-data
style has several advantages (often in code clarity) that are a bit
complex to explain here.

As you probably know, the good thing of learning new languages is that
they carry some principles, and they are the expression of some ideas
of the computer science. So learning Python may show you some new
ideas, or new ways to look at old computer science ideas you already
know. I think Alan J. Perlis said "A language that doesn't affect the
way you think about programming, is not worth knowing."

Bye,
bearophile
Sep 19 '08 #11

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

6 posts views Thread by post400 | last post: by
23 posts views Thread by Simon Wittber | last post: by
114 posts views Thread by Maurice LING | last post: by
16 posts views Thread by Raxit | last post: by
30 posts views Thread by Ivan Reborin | last post: by
reply views Thread by leo001 | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.