Need to pass Object by value into a list

Bruno Desthuilliers bdesth.quelquechose at free.quelquepart.fr
Mon Sep 26 16:41:26 EDT 2005


Aaron a écrit :

> I have a data sructure setup and I populate it in a loop like so:
> 
> y=0
> while X:
>    DS.name = "ASDF"
>    DS.ID = 1234
>    list[y] = DS;
>    y = y + 1
> 
> print list

Traceback (most recent call last):
   File "<stdin>", line 1, in ?
   File "/usr/tmp/python-9150sSF", line 2, in ?
     while X:
NameError: name 'X' is not defined

Please post running code. The rule is:
- explain what you did
- explain what you expected
- explain what you've got
- post the minimal running code that reproduce the problem

Here are a short listing of errors and bad style in this code:

1/ DS is not defined
2/ X is not defined
3/ 'list' is the name of the builtin class list. The list *class* is 
unsubscriptable.
4/ Assuming you rebound the name 'list' to a list instance (which is a 
very Bad Thing(tm)), you still can't assign to an inexistant index
5/ even if DS and X were defined, this loop would run forever
6/ In Python, identifiers in uppercase are constants (well... this is 
only a convention, but convention in Python are part of the language, 
even if there's nothing to enforce them)
7/ you mix arbitrary naming conventions ('DS.name' vs 'DS.ID', 'X' vs 'y').

Either this is not your real code or you did not try to run this code. 
In fact, I guess this is not your real code AND you did not try to run 
it. Please do *yourself* a favor: post running code (I don't mean 'code 
that don't crash', I mean: 'code that reproduce your real problem').

> This does not work 

"Does not work" is the worst possible description of a problem.

Now effectively, this code (the one you posted, not the one you are 
describing) crashes for a very obvious reason (see point n°1 above). The 
code you are describing (which is obviously different...) "works" - it 
may not behave how you'd expect it to, but this is another problem.

> because DS is passed in by reference causing all
> entries into the list to change to the most current value.

DS is not 'passed by reference', since there is no function call in your 
code. A reference to the object bound to the name DS is stored (well, I 
assume this is what happen in your real code) in the list  - which is 
not the same thing.

<digression>
BTW, you need to understand that, in Python, an identifier is just a 
name bound to a reference to an object. Think of the namespace as a 
hashtable with names as keys and references to objects as values (this 
exactly how it's implemented). When it comes to function calls, the 
*name* is local to the function, but the object referenced by the name 
is the original object. If you rebind the name (ie: 'assign' another 
object to it), this change will be local, because the *name* is local. 
But if you modify the object itself, this will impact the 'original' 
object, ie:

def fun(aList, anotherList):
   # rebind local name 'aList', original object not impacted
   aList = [1, 2, 3]

   # modify ('mutate') object bound to 'anotherList',
   # original object impacted
   anotherList.append(42)

listOne = [4, 5, 6]
listTwo = [7, 8, 9]

fun(listOne, listTow)
print listOne
print listTwo
</digression>


>  I cannot
> find a "new" function in Python like there is in C++.

<pedantic>
In C++, 'new' is an operator, not a function.
</pedantic>

In Python, classes are callable objects (a callable is something like a 
function - or, should I say, a function is a kind of callable object - 
everything in Python being an object...) that return an instance when 
called. So there is no need for a 'new' operator - just call the class 
object (like you'd call a function), and you'll get an instance. Also, 
if the class has an '__init__' method, this method will be called after 
object instanciation, with the arguments passed when calling the class.

ie:

class Foo(object):
   def __init__(self, name):
     self.name = name

f = Foo('foo')
f.name
=> 'foo'

>  How do you do
> this in Python?
> 

class Ds(object):
   def __init__(self, id, name):
     self.id = id
     self.name = name

x = 42 # or any other integer value

# short way
ds_list = [Ds(1234, "ASDF") for i in range(x)]
print ds_list

# verbose way:
ds=list = []
for i in range(x):
   ds_list.append(Ds(1234, "ASDF")

print ds_list
ds_list[0].name="FOO"
print ds_list

HTH



More information about the Python-list mailing list