1

I am trying to understand how exactly assignment operators, constructors and parameters passed in functions work in python specifically with lists and objects. I have a class with a list as a parameter. I want to initialize it to an empty list and then want to populate it using the constructor. I am not quite sure how to do it.

Lets say my class is --

class A:
    List = []                   # Point 1

    def __init1__(self, begin=[]): # Point 2
        for item in begin:
            self.List.append(item)

    def __init2__(self, begin):  # Point 3
        List = begin

    def __init3__(self, begin=[]): # Point 4
        List = list()
        for item in begin:
            self.List.append(item)


listObj = A()

del(listObj)

b = listObj

I have the following questions. It will be awesome if someone could clarify what happens in each case --

  1. Is declaring an empty like in Point 1 valid? What is created? A variable pointing to NULL?

  2. Which of Point 2 and Point 3 are valid constructors? In Point 3 I am guessing that a new copy of the list passed in (begin) is not made and instead the variable List will be pointing to the pointer "begin". Is a new copy of the list made if I use the constructor as in Point 2?

  3. What happens when I delete the object using del? Is the list deleted as well or do I have to call del on the List before calling del on the containing object? I know Python uses GC but if I am concerned about cleaning unused memory even before GC kicks in is it worth it?

  4. Also assigning an object of type A to another only makes the second one point to the first right? If so how do I do a deep copy? Is there a feature to overload operators? I know python is probably much simpler than this and hence the question.

EDIT: 5. I just realized that using Point 2 and Point 3 does not make a difference. The items from the list begin are only copied by reference and a new copy is not made. To do that I have to create a new list using list(). This makes sense after I see it I guess.

Thanks!

R11
  • 405
  • 2
  • 6
  • 15
  • 2
    Have you read [the Python tutorial](http://docs.python.org/tutorial/)? – BrenBarn Mar 30 '13 at 21:05
  • Note `List = []` and `__init1__(self, begin=[])` will result [same list among all objects of the class](http://stackoverflow.com/questions/1132941/least-astonishment-in-python-the-mutable-default-argument). This most likely not the behavior which you are expecting! – Igonato Mar 30 '13 at 21:13
  • @BrenBarn - I did initially to get the syntax and then jumped into code hoping to learn along the way. I think I understand it better now. Please see my edit above. – R11 Mar 30 '13 at 21:14
  • Variables are not pointers, they are "names" for objects. [See this illustration](http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#other-languages-have-variables). – Francis Avila Mar 30 '13 at 21:19
  • @Francis -- The link is nice. But pointers or references or "names" are all memory addresses. Its nice to understand from memory address standpoint what exactly happens. The link helps though. – R11 Mar 30 '13 at 21:28

2 Answers2

2

In order:

  1. using this form is simply syntactic sugar for calling the list constructor - i.e. you are creating a new (empty) list. This will be bound to the class itself (is a static field) and will be the same for all instances.
  2. apart from the constructor name which must always be init, both are valid forms, but mean different things.
    • The first constructor can be called with a list as argument or without. If it is called without arguments, the empty list passed as default is used within (this empty list is created once during class definition, and not once per constructor call), so no items are added to the static list.
    • The second must be called with a list parameter, or python will complain with an error, but using it without the self. prefix like you are doing, it would just create a new local variable name List, accessible only within the constructor, and leave the static A.List variable unchanged.
  3. Deleting will only unlink a reference to the object, without actually deleting anything. Once all references are removed, however, the garbage collector is free to clear the memory as needed. It is usually a bad idea to try to control the garbage collector. instead. just make sure you don't hold references to objects you no longer need and let it make its work.
  4. Assigning a variable with an object will only create a new reference to the same object, yes. To create a deep copy use the related functions or write your own.
  5. Operator overloading (use with care, it can make things more confusing instead of clearer if misused) can be done by overriding some special methods in the class definition.

About your edit: like i pointed above, when writing List=list() inside the constructor, without the self. (or better, since the variable is static, A.) prefix, you are just creating an empty variable, and not overriding the one you defined in the class body.

For reference, the usual way to handle a list as default argument is by using a None placeholder:

class A(object):
   def __init__(self, arg=None):
      self.startvalue = list(arg) if arg is not None else list()
      # making a defensive copy of arg to keep the original intact

As an aside, do take a look at the python tutorial. It is very well written and easy to follow and understand.

Grim
  • 1,608
  • 9
  • 12
  • Thanks for the reply. I just found the list() function myself. I will go through the tutorial again, this time at least I will know what I understand it better since I wrote some code in it. – R11 Mar 30 '13 at 21:30
  • About Point 1 you said that it will create a static list that is the same for all objects instantiated for that class? I do not want that. I want to use this Class simply to return multiple variables from a function and so I really want the variables to specific to the object itself. How do I create such variables in a class? – R11 Mar 30 '13 at 21:38
  • See the code i added at the end - it does exactly that - the usual way to create an instance field in python is to assign it within the class contructor, prefixing the assignation with *self.* - e.g. `self.foo = "bar"` will create a "foo" field in the object with the value of "bar". – Grim Mar 30 '13 at 21:45
1

"It will be awesome if someone could clarify what happens in each case" isn't that the purpose of the dis module ? http://docs.python.org/2/library/dis.html

bobrobbob
  • 1,251
  • 11
  • 21
  • It definitely covers the awesome part. I did not know about that till now. I need to start reading documentation properly. – R11 Mar 30 '13 at 23:05