newbie questions

H

houbahop

Hello everyone,
I'm new to python dev, and there are some things I don't understand
about arrays and subs

In my code, I have an array of strings (in the main function)

self.SortiesAnimeTitreLabel = []

then I pass this array to a sub that fill it it ( using.append('blabla') :

self.InstancierLabelsTitre(self.SortiesAnimeTitreLabel)

then, I need to reset this var, and this is my problem, I have created an
other sub to reset and it doesn't seems to work, like if the parameter was
pass by value instead of by reference. here is the sub :


def RAZVarAnimesDuJour(self,oSortiesAnimeTitreLabel):
for i in xrange(len(oSortiesAnimeTitreLabel)):
del oSortiesAnimeTitreLabel

it doesn't emty my var (i don't want to destroy the var, just make it like
if it just have been created

do yo have any idea of what is causing this problem?
is it possible to do self.SortiesAnimeTitreLabel = [] to reset the var? (it
seems to work outside of the sub, but I believe that the var I'm erasing is
not the one I want but a local copy.


Thank you for your help.
Dominique.
 
E

Erik Johnson

do yo have any idea of what is causing this problem?
is it possible to do self.SortiesAnimeTitreLabel = [] to reset the var? (it
seems to work outside of the sub, but I believe that the var I'm erasing is
not the one I want but a local copy.


Yeah. I'm no Python guru, but I have a pretty good idea. Your intuition
is correct - you're killing a local copy. Functions (and methods) have their
own namespace. Variables declared within a function are local that that
function's name space, as well as formal variables that appear on the
function declartion (definition) line.
.... print dir()
.... del x
.... print dir()
....

Secondly, within a class method, x and self.x are two different things.
The first is just a variable within the method namespace, the second is an
object attribute. So, for your example, there probably is no reason to go
kill each list element individually (unless perhaps other code is accessing
that list NOT through the object.) Within an object method, if you honestly
don't want to kill the variable, you could just say:

self.SortiesAnimeTitreLabel = []

and that replaces that object's list with an empty one. Unless there are
other references to that same list, hte garbage collector will take it.
Other code accessing the list through this object's handle will see the new,
empty list, which I think is what you want in this case.

HTH,
-ej
 
A

Adam DePrince

do yo have any idea of what is causing this problem?
is it possible to do self.SortiesAnimeTitreLabel = [] to reset the var? (it
seems to work outside of the sub, but I believe that the var I'm erasing is
not the one I want but a local copy.


Yeah. I'm no Python guru, but I have a pretty good idea. Your intuition
is correct - you're killing a local copy. Functions (and methods) have their
own namespace. Variables declared within a function are local that that
function's name space, as well as formal variables that appear on the
function declartion (definition) line.
... print dir()
... del x
... print dir()
...

Secondly, within a class method, x and self.x are two different things.
The first is just a variable within the method namespace, the second is an
object attribute. So, for your example, there probably is no reason to go
kill each list element individually (unless perhaps other code is accessing
that list NOT through the object.) Within an object method, if you honestly
don't want to kill the variable, you could just say:

self.SortiesAnimeTitreLabel = []

and that replaces that object's list with an empty one. Unless there are
other references to that same list, hte garbage collector will take it.
Other code accessing the list through this object's handle will see the new,
empty list, which I think is what you want in this case.

HTH,
-ej

At risk of encouraging a "newbie" from partaking in the hideous and vile
vice of "programming by side effect" there is a way to make python do
almost what you want.

First, lets look at the "is" operator. is is like ==, but instead of
answering the question "are these objects equivalent," it asks "are they
actually the same object."
a = []
b = []
a is b # They are different objects False
a == b # They have the sample value True
b = a # Now we are assigning to b the same object as a. # There are two references to it.
a is b
True

Alright. Now, as Erik pointed out if you assign to the variable the
computer will add that to the local name space. This happens at
"compile" time (which is right after you hit enter twice at the CPython
command line.)

For an example of this:
.... print a
........ print a
.... a = 1
....Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 2, in c
UnboundLocalError: local variable 'a' referenced before assignment

In b(), a was taken as being from the line above. In c, it was from the
local name space.

So, how do we affect what you want? Now promise me that you will never,
ever do this in code you consider yourself proud of. Realize I'm
sharing this in the same spirit that kids in a drivers ed class might
view gory accident pictures.

Fortunately for you, lists are mutable. Assigning to a auto-magically
makes it part of your local name space, hiding the global a. But, if
you don't assign to a, you can still access it. And because you can
access it you can mutate it.
.... a.append( 2 )
........ a[0] = 0 # Yes, an assignment, but not to a
........ a[:] = []
....
b()
a [1, 2]
c()
a [0, 2]
d()
a []

Now forgive me ... what you really want to do is follow Erik's advice.




Adam DePrince
 
M

Mike Meyer

Adam DePrince said:
Alright. Now, as Erik pointed out if you assign to the variable the
computer will add that to the local name space. This happens at
"compile" time (which is right after you hit enter twice at the CPython
command line.)

For an example of this:

... print a
...
... print a
... a = 1
...
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 2, in c
UnboundLocalError: local variable 'a' referenced before assignment

In b(), a was taken as being from the line above. In c, it was from the
local name space.

So, how do we affect what you want?

I *have* to point out here that you can write c as:
.... global a
.... print a
.... a = 1
....
The one (and so far only) place you can declare a variable in Python.

<mike
 
R

Roel Schroeven

houbahop said:
def RAZVarAnimesDuJour(self,oSortiesAnimeTitreLabel):
for i in xrange(len(oSortiesAnimeTitreLabel)):
del oSortiesAnimeTitreLabel

it doesn't emty my var (i don't want to destroy the var, just make it like
if it just have been created


Other posts are missing the point somewhat, I think. While they do
recommend better ways of doing what you want to do, they don't say why
your function doesn't work.

What exactly happens when you execute your code? When I try it, I get an
exception:
for i in xrange(len(alist)):
del alist


Traceback (most recent call last):
File "<pyshell#22>", line 1, in -toplevel-
a(alist)
File "<pyshell#21>", line 3, in a
del alist
IndexError: list assignment index out of range


What happens is this: the first time, the first element is deleted. This
causes all other elements to shift: the second element becomes the first
one, the third becomes the second, and so on. Or:

0, 1, 2, 3, 4
becomes
1, 2, 3, 4

The list gets shorter each time. But you're still looping over the whole
length of the list, which means after some time you're accessing
elements that no longer exist.

One way to solve it is to loop backwards: first delete the last element,
than the next to last, etc.


Apart from that, it's much easier and clearer to reset the list with just

alist = []
 
H

houbahop

Thank you everyone, but I still not understand why such a comon feature like
passing parameters byref that is present in most serious programming
languages is not possible in a clean way,here in python.

I have the habit to never use globals as far as possible and this involve
that my main function is passing some parameters by reference to subs to
allow them to modify the vars.

I would be sad to break my structured programming scheme because a lack of
feature.

In others languages you can use things like pointers to strings or
Mysub(byref MyVar) ....

and it does the trick :)
 
S

Steven Bethard

houbahop said:
Thank you everyone, but I still not understand why such a comon feature like
passing parameters byref that is present in most serious programming
languages is not possible in a clean way,here in python.

I understand from this statement that Java is not a serious programming
language? ;)
I have the habit to never use globals as far as possible and this involve
that my main function is passing some parameters by reference to subs to
allow them to modify the vars.

I don't see why lack of pass-by-reference would force you to use globals...
.... def __init__(self):
.... self.list = []
.... def fill(self, iterable):
.... self.list.extend(iterable)
.... def empty(self):
.... self.list = []
....
>>> c = C()
>>> c.list []
>>> c.fill(pow(x, 3, 29) for x in range(10))
>>> c.list [0, 1, 8, 27, 6, 9, 13, 24, 19, 4]
>>> c.empty()
>>> c.list
[]

Or by globals do you mean instance variables? If you don't want any
instance variables (which means you don't really want OO), you can still
clear your list as long as you have any name bound to the list object:
.... while lst:
.... lst.pop()
....
>>> x = [pow(x, 7, 19) for x in range(10)]
>>> x [0, 1, 14, 2, 6, 16, 9, 7, 8, 4]
>>> clear(x)
>>> x
[]

or alternatively:
.... lst[:] = []
....
>>> x = [pow(x, 7, 19) for x in range(10)]
>>> x [0, 1, 14, 2, 6, 16, 9, 7, 8, 4]
>>> clear(x)
>>> x
[]

Note that neither of these functions requires pass-by-reference; the lst
local in the function is not the same name as the x local outside the
function. But since you're basically just passing a "pointer" by value,
both "variables" still "point" to the same object (or in Python terms,
both "names" are "bound" to the same object). To apply an affect that
is visible to all names bound to an object, you simply need to mutate
the object. In the cases above, this is just a matter of using the
appropriate object method (list.pop or list.__setslice__ respectively
above).

Is this so bad?

Steve
 
M

Mel Wilson

Thank you everyone, but I still not understand why such a comon feature like
passing parameters byref that is present in most serious programming
languages is not possible in a clean way,here in python.

I have the habit to never use globals as far as possible and this involve
that my main function is passing some parameters by reference to subs to
allow them to modify the vars.

I would be sad to break my structured programming scheme because a lack of
feature.

In others languages you can use things like pointers to strings or
Mysub(byref MyVar) ....

and it does the trick :)

It isn't a problem with passing by reference. The
passing-by-reference part works just fine. Putting in a
print statement to trace what's actually happening:


Python 2.3 (#46, Jul 29 2003, 18:54:32) [MSC v.1200 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
.... for i in xrange (len (s)):
.... del s
.... print 'X:', s
....X: [2, 3, 4, 5]
X: [2, 4, 5]
X: [2, 4]
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File said:


As the last line shows, lots of things got removed from
`a` .. but not everything. Roel Schroeven explained why.

Regards. Mel.
 
H

houbahop

Hi,

Steven Bethard said:
I understand from this statement that Java is not a serious programming
language? ;)

;) I didn't want to say that.
In fact, python is the first language I use that is like java 100% oriented
object.
I didn't realise that the main function, was an object too ! (and I don't
really knew that self.something was meaning that it was a class attribute..
just grabed this in a code found on the net :) )
My habit in VB was to start a new project with a module (that is not an
object and doesn't have class functions) and then calling object functions
and passing them local to the main objects.

like this :

class a()
blabla
class b()
blabla

main()
create a instance
create b instance
b()
a(b)
end main

But in the very small script that I'm coding, I don't really need OOP and I
will not use it even if I really like that.


I don't see why lack of pass-by-reference would force you to use
globals...
Or by globals do you mean instance variables? If you don't want any
instance variables (which means you don't really want OO), you can still
clear your list as long as you have any name bound to the list object:

You're right.
... while lst:
... lst.pop()
...
x = [pow(x, 7, 19) for x in range(10)]
x [0, 1, 14, 2, 6, 16, 9, 7, 8, 4]
clear(x)
x
[]

or alternatively:
... lst[:] = []
...
x = [pow(x, 7, 19) for x in range(10)]
x [0, 1, 14, 2, 6, 16, 9, 7, 8, 4]
clear(x)
x
[]

Note that neither of these functions requires pass-by-reference; the lst
local in the function is not the same name as the x local outside the
function. But since you're basically just passing a "pointer" by value,
both "variables" still "point" to the same object

Passing a pointer by value appears to me as passing a var by reference.

(or in Python terms,
both "names" are "bound" to the same object). To apply an affect that is
visible to all names bound to an object, you simply need to mutate the
object. In the cases above, this is just a matter of using the
appropriate object method (list.pop or list.__setslice__ respectively
above).

Thanks I will try all of that, but what does really means mutating in
python? It's the first time I hear this word in programming :))
Dominique
 
D

Diez B. Roggisch

Thanks I will try all of that, but what does really means mutating in
python? It's the first time I hear this word in programming :))

An object is called mutable if you can alter it - immutable otherwise. In
java and python e.g. strings are immutable. In python, tuples are
immutable:
TypeError: object doesn't support item assignment

but lists are mutable:
[3,2]

But objects in tuples can be mutable:
a = (1, [2,3])
a[1].append(4)
a
(1,[2,3,4])

Numbers are also immutable. 1 is 1 always.


The most important thing to know about python and variables is that
variables are only names pointing/referring to values. You might be able to
modify the values if they are mutable, but assigning a value to a variable
means that you simply rebind its name to a new value - not that you alter
it. Consider this:
2 1
 
H

houbahop

Hello again everyone ,
var2[:]=[] has solved my problem, and I don't understand why it is
programming by side effect.
I don't think it's bad, look at this, it's what I've done :

def Clear(lvar)
lvar[:]=[]

def main (starting class)
var1=[]
var1.append('a')
Clear(var1)

var1 can only be modified by Clean(), so, if I need to debug var1, I
quickly know that I must look in Clean()


For me programming by side effect is that :

def Clear(lvar)
var1=[]

def main (starting class)
global var1=[]
var2=[]
var1.append('a')
Something(var2)


I am wrong?
Dominique.
 
S

Steven Bethard

houbahop said:
Passing a pointer by value appears to me as passing a var by reference.

Well, at least in the PL literature, there's a subtle difference. If
Python supported pass-by-reference, you could do something like:
.... lst = []
....
>>> x = [pow(x, 11, 17) for x in range(10)]
>>> clear(x)
>>> x
[]

Passing a variable by reference means that the *variable* in the
function is the same *variable* as outside the function. Notice that
this is not the same thing as saying that the variable in the function
is a pointer to the same object as the variable outside the function.

Python doesn't support pass-by-reference in this standard use of the
term. But Python is basically *only* passing pointers around; there is
no way to do anything else. So if passing a pointer by value is
sufficient for your purposes then you won't have any problems with
Python, because this is what it always does. =)
Thanks I will try all of that, but what does really means mutating in
python? It's the first time I hear this word in programming :))

The term is used most commonly in the pair accessor/mutator, also known
as getter/setter. In general, a mutator is just a method of an object
that changes that object's state. In Python, assignment does not invoke
a method of an object; it binds a name to an object. For this reason,
code like:

def clear(lst):
lst = [] # binds the name lst to a new value, []
# ignoring previous value

will not change the list because it is not calling methods of the list
object to change it. It will instead rebind the local name "lst" to a
new object, []. This does not change the previous object that was
associated with "lst" and so if you have another variable bound to the
previous value ("x" in my examples), it will still retain the old,
unchanged object.

So, while assignment does not invoke a method of an object, many other
things in Python do, and all of these things will appropriately modify
the state of the object. For example:

def clear(lst):
lst[:] = [] # implicitly calls the setter/mutator list.__setslice__

def clear(lst):
while lst: # implicitly calls the getter/accessor len(lst)
lst.pop() # explicit call to setter/mutator list.pop

# don't use this; it's inefficient, I'm just using it as an example
# of using a different setter/mutator
def clear(lst):
while lst: # implicitly calls the getter/accessor len(lst)
last_item = lst[-1] # implicitly calls the getter/accessor
# list.__getitem__
lst.remove(last_item) # explicitly calls setter/mutator
# list.remove

Note that all of these functions will successfully clear the list
because they mutate the object itself, instead of simply rebinding a
name that at one point had been associated with the object.

HTH,

STeve
 
S

Steven Bethard

houbahop said:
Hello again everyone ,
var2[:]=[] has solved my problem, and I don't understand why it is
programming by side effect.
I don't think it's bad, look at this, it's what I've done :

def Clear(lvar)
lvar[:]=[]

def main (starting class)
var1=[]
var1.append('a')
Clear(var1)

From http://en.wikipedia.org/wiki/Side-effect_(computer_science)

In computer science, a side-effect is a property of a programming
language function that it modifies some state other than its return value.

Given this definition, I think you're fine -- clearing the list isn't a
side effect of the function; it is the purpose of the function. Hence
the function has no return value.[1]



Of course, in this simple case, I wouldn't be likely to write the clear
function since the inline code is simpler and has less overhead:

def main()
var1 = []
var1.append('a')
var1[:] = []

or, since in this case, you only care about var1, you can just rebind it
(and let Python garbage-collect the old list):

def main()
var1 = []
var1.append('a')
var1 = []

Steve

[1] Technically, all Python functions without a return statement return
None, but for our purposes, we can consider a function like this to have
"no return value".
 
H

houbahop

Thank you Steven,
The funny thing is that I have taken a look at wikipedia just before to be
sure that I wasn't wrong :D
I agree with you about not making a clear function to just put what I've put
in my sample, but
this sample was more simple that what I really need for explaining purpose.

In reality My clear function is cleaning a dozen of arrays and since I need
to call it several time I have made a function of it.

a few days ago I was trying python for the little script I'm working on and
this language is more powerfull that I was thinking and very pleasant to
code.
I believe I will use it more in the future.
Dominique.


Steven Bethard said:
houbahop said:
Hello again everyone ,
var2[:]=[] has solved my problem, and I don't understand why it is
programming by side effect.
I don't think it's bad, look at this, it's what I've done :

def Clear(lvar)
lvar[:]=[]

def main (starting class)
var1=[]
var1.append('a')
Clear(var1)

From http://en.wikipedia.org/wiki/Side-effect_(computer_science)

In computer science, a side-effect is a property of a programming language
function that it modifies some state other than its return value.

Given this definition, I think you're fine -- clearing the list isn't a
side effect of the function; it is the purpose of the function. Hence the
function has no return value.[1]



Of course, in this simple case, I wouldn't be likely to write the clear
function since the inline code is simpler and has less overhead:

def main()
var1 = []
var1.append('a')
var1[:] = []

or, since in this case, you only care about var1, you can just rebind it
(and let Python garbage-collect the old list):

def main()
var1 = []
var1.append('a')
var1 = []

Steve

[1] Technically, all Python functions without a return statement return
None, but for our purposes, we can consider a function like this to have
"no return value".
 
J

John Machin

Steven said:
Of course, in this simple case, I wouldn't be likely to write the clear
function since the inline code is simpler and has less overhead:

def main()
var1 = []
var1.append('a')
var1[:] = []

Even less overhead: del var1[:]
 
D

Dennis Lee Bieber

Thank you everyone, but I still not understand why such a comon feature like
passing parameters byref that is present in most serious programming
languages is not possible in a clean way,here in python.
Well, in C, everything is also passed by value. The programmer
has to explicitly pass an "address as the value" instead of the actual
value if they want to change the contents. And, of course, the function
has to know that it is an address, and explicitly dereference the
address to gain access to the actual content value.

Using my overworked and not quite complete example...

Most languages variables can be described as named boxes (think
of a post office sorting rack -- each "person/address" has a separate
box.

In those languages, "A = B" means finding the BOX with belonging
to "B" (has "B" on the front of the box), COPYING what is inside it, and
then putting that COPY into the box belonging to "A" (taking out and
discarding whatever might have been in "A"'s box).

In Python, you still have those boxes (objects), but the label
(person/address) is not engraved on the box. Instead, it is on a
"Post-it" note. "A = B" means finding the "Post-it" note -- where ever
it is, since it isn't a fixed location -- and putting it on the box that
also has the "B" "Post-it" note. If the "A" was the last "Post-it" note
on the original box, the box contents are thrown away, and the box is
available for reuse. You now have ONE BOX with TWO "Post-it"s, "A" and
"B".

When you call a function, passing "A", for example, you create a
third "Post-it" note, with the function's dummy argument name "D", and
attach it to the same box. The box now has three "Post-it"s attached;
two from the outer scope, and one from the function scope.

An assignment to "D" moves the "Post-it" from that shared box,
to whatever box contains the value of the assignment. And when the
function exits, the clean-up code goes through and finds all the
"Post-it"s that belong to the function, and deletes the "Post-it" (the
contents of the box only get deleted if no other "Post-it" is attached).

The closest equivalent to the C, that I can imagine at the
moment, is to package your arguments into a list before the call, invoke
the function passing the list -- and access the arguments by list
subscripts, followed by extracting the list elements back into the
original "names" after the call returns... Untested:

args = [ a1, a2, a3 ]
function(args)
(a1, a2, a3) = tuple(args)

However, 'tis probably cleaner to just use a tuple return from
the function...

(a1, a2, a3) = function(a1, a2, a3)

Where the function can perform internal modifications to the
arguments passed in, and then returns ALL of them at the end. Other
languages can only return a single entity, Python can return the
"world"... (... return globals() <G>)

--
 
H

houbahop

Dennis Lee Bieber said:
Well, in C, everything is also passed by value. The programmer
has to explicitly pass an "address as the value" instead of the actual
value if they want to change the contents. And, of course, the function
has to know that it is an address, and explicitly dereference the
address to gain access to the actual content value.

Using my overworked and not quite complete example...

Hello and thank you,

To be honnest I must take a moment and translate your example into french to
really understand it (but I believe it's very well explained :) and I will
understand)
I remember at school when an unix teacher was explaining what was an UID and
a GID, like if the files were two persons talking and asking each other "
what's your UID?, we got the same, so, what is your GID ?", and I never had
problems with UID and GID since that :D

I have thinked to try to return an array of values like a function does
(instead of passing many params to a sub) but didn't take the time to do it.

I believe that programming in python involves to learn a kind of new
phillosophy, new words too. as an exemple of this, for me
a 'tuple' is related to database stuff. What I call an array seems to be
called a list in python (C programmers use the word 'matrix' when talking of
a two dimentionnal array, and 'vector' when talking of a one dimention
array...sorry, a list :D ).

Regards,
Dominique.
 
D

Dennis Lee Bieber

I believe that programming in python involves to learn a kind of new
phillosophy, new words too. as an exemple of this, for me
a 'tuple' is related to database stuff. What I call an array seems to be

"tuple" gets around... But yes, relational database theory uses
it for what most would call a "row" or "record". So think of a Python
tuple as being a "record" (or C "struct") with the condition that you
can not change the contents of it.
called a list in python (C programmers use the word 'matrix' when talking of

One difference in view is that most language have bounded arrays
-- you had to allocate how many elements are in the array. Python lists
are dynamic, you can add and remove elements. Also, many languages
restrict all elements of an array to being the same data type. Python
lists can be any of Pythons objects -- and can be mixed.

--
 
F

Fredrik Lundh

John said:
Of course, in this simple case, I wouldn't be likely to write the clear
function since the inline code is simpler and has less overhead:

def main()
var1 = []
var1.append('a')
var1[:] = []

Even less overhead: del var1[:]

even less overhead:

var1 = []

(if you rely on having multiple references to the same list, instead of referring
to the list by name, you may want to reconsider the design)

</F>
 
S

Steven Bethard

Fredrik said:
John Machin wrote:

Of course, in this simple case, I wouldn't be likely to write the clear
function since the inline code is simpler and has less overhead:

def main()
var1 = []
var1.append('a')
var1[:] = []

Even less overhead: del var1[:]


even less overhead:

var1 = []

(if you rely on having multiple references to the same list, instead of referring
to the list by name, you may want to reconsider the design)

Yes, that's what the next 4 lines of my message said. ;)

Steve
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,756
Messages
2,569,533
Members
45,007
Latest member
OrderFitnessKetoCapsules

Latest Threads

Top