Help understanding an Object Oriented Program example

Discussion in 'Python' started by goldtech, Oct 28, 2012.

  1. goldtech

    goldtech Guest

    Hi,

    Trying to learn Python OOP. An example from a book, may not be
    formated after sending post but:

    class Contact:
    all_contacts = []
    def __init__(self, name, email):
    self.name = name
    self.email = email
    Contact.all_contacts.append(self)

    OK, no I do this:

    >>> c = Contact('aaa','bbb')
    >>> c = Contact('ccc','ddd')
    >>> c = Contact('eee','fff')
    >>> for i in Contact.all_contacts:

    print i.name + ' ' + i.email


    aaa bbb
    ccc ddd
    eee fff
    >>>
    >>> c.name

    'eee'

    So wouldn't be good to add a check that the var (in this case c) does
    not point to any object before creating an object to keep the list
    correct?

    Also all_contacts is a class variable. I think the author is hinting
    that this would be a good idea for a contact list, But I don't fully
    see the usage of it. How would each object use a class variable like
    this? What would be the dot notation?

    I realize this is a code fragment and is no way implementable code.
    Any help appreciated. BTW, it's from "Python3 Object Oriented
    Programming..." by D. Philips - very clearly written and enjoying
    it...Thanks
     
    goldtech, Oct 28, 2012
    #1
    1. Advertising

  2. goldtech

    Chris Rebert Guest

    On Sun, Oct 28, 2012 at 4:30 PM, goldtech <> wrote:
    > Hi,
    >
    > Trying to learn Python OOP. An example from a book, may not be
    > formated after sending post but:
    >
    > class Contact:
    > all_contacts = []
    > def __init__(self, name, email):
    > self.name = name
    > self.email = email
    > Contact.all_contacts.append(self)
    >
    > OK, no I do this:
    >
    >>>> c = Contact('aaa','bbb')
    >>>> c = Contact('ccc','ddd')
    >>>> c = Contact('eee','fff')
    >>>> for i in Contact.all_contacts:

    > print i.name + ' ' + i.email
    >
    >
    > aaa bbb
    > ccc ddd
    > eee fff
    >>>>
    >>>> c.name

    > 'eee'
    >
    > So wouldn't be good to add a check that the var (in this case c) does
    > not point to any object before creating an object to keep the list
    > correct?


    I'm unclear on how the list would become "incorrect" or exactly what
    sort of check you're thinking of. Please explain what you mean in
    greater detail.
    Keep in mind that checking for the "definedness" of variables in
    Python is generally considered bad and is often infeasible.

    > Also all_contacts is a class variable. I think the author is hinting
    > that this would be a good idea for a contact list, But I don't fully
    > see the usage of it.


    I would think he just wants to demonstrate the use of class variables
    as opposed to instance variables. It's probably not a good idea for a
    serious contact list implementation. But the general technique to
    allow a class to keep track of all its instances can sometimes be
    useful (e.g. for caching).

    > How would each object use a class variable like
    > this? What would be the dot notation?


    All of the following would work:
    Contact.all_contacts # as in the example
    self.__class__.all_contacts
    self.all_contacts # probably not advisable

    Which one you ought to use becomes complicated when you consider the
    general case where there may be sub/superclasses, where you may want
    to rebind the variable, and where there may be an instance variable of
    the same name.
    Class variables are generally used quite infrequently compared to
    regular instance variables.

    Cheers,
    Chris
     
    Chris Rebert, Oct 29, 2012
    #2
    1. Advertising

  3. On Mon, Oct 29, 2012 at 10:30 AM, goldtech <> wrote:
    > Hi,
    >
    > Trying to learn Python OOP. An example from a book, may not be
    > formated after sending post but:
    >
    > class Contact:
    > all_contacts = []
    > def __init__(self, name, email):
    > self.name = name
    > self.email = email
    > Contact.all_contacts.append(self)
    >
    > OK, no I do this:
    >
    >>>> c = Contact('aaa','bbb')
    >>>> c = Contact('ccc','ddd')
    >>>> c = Contact('eee','fff')
    >>>> for i in Contact.all_contacts:

    > print i.name + ' ' + i.email
    >
    >
    > aaa bbb
    > ccc ddd
    > eee fff
    >>>>
    >>>> c.name

    > 'eee'


    Hi! Side point before we begin: You appear to be using Python
    2.something (since print is a statement, not a function), but your
    book (as you mention further down) refers to Python3. I recommend you
    get an interpreter that corresponds to your book, or you'll end up
    tripping over a triviality :) If the book doesn't specify a particular
    version, get 3.3 - it's the latest released Python, and a significant
    improvement over its predecessors.

    > So wouldn't be good to add a check that the var (in this case c) does
    > not point to any object before creating an object to keep the list
    > correct?


    Depends what you mean by "correct" there. If you're expecting the list
    to contain only those objects that are referenced somewhere else,
    you'll have to play around with weak references and such; normally,
    what's expected of code like this is that it will retain all objects
    created, even if there are no other references. So in that sense, the
    list's already correct.

    > Also all_contacts is a class variable. I think the author is hinting
    > that this would be a good idea for a contact list, But I don't fully
    > see the usage of it. How would each object use a class variable like
    > this? What would be the dot notation?


    Exactly the way you currently are, as Contact.all_contacts - but
    there's also some magic that lets you reference it from any instance:

    >>> Contact("foo","foo@foo")

    <__main__.Contact instance at 0x011B5030>
    >>> Contact("a","a@a")

    <__main__.Contact instance at 0x011BC828>
    >>> c=Contact("quux","")
    >>> c.all_contacts

    [<__main__.Contact instance at 0x011B5030>, <__main__.Contact instance
    at 0x011BC828>, <__main__.Contact instance at 0x011BC5D0>]

    Note how all three instances are listed in one instance's all_contacts
    member. (Note also that I didn't have to assign the other two to
    anything - the objects still get retained in all_contacts.) A common
    way to do this sort of thing is to simply use self:

    class Contact:
    all_contacts = []
    def __init__(self, name, email):
    self.name = name
    self.email = email
    self.all_contacts.append(self)

    As long as you don't rebind that name (eg "self.all_contacts = []"),
    this will work just fine.

    > I realize this is a code fragment and is no way implementable code.


    Actually, it's quite workable. It's enough to paste into the
    interactive interpreter and play with. That's one of Python's best
    features - it's really easy to play with. And if you put parentheses
    around your print argument, it'll be fully Python 3 compatible (though
    when you run it in Python 2, you get an old-style class - but since
    the book's assuming Py3, new-style is what you want anyway).

    >>> for i in Contact.all_contacts:

    print(i.name + ' ' + i.email)

    Hope that helps!

    Chris Angelico
     
    Chris Angelico, Oct 29, 2012
    #3
  4. Am 29.10.2012 00:30, schrieb goldtech:
    > class Contact:
    > all_contacts = []
    > def __init__(self, name, email):
    > self.name = name
    > self.email = email
    > Contact.all_contacts.append(self)


    Okay, a class that automatically registers all instances in a central list.


    > OK, no I do this:
    >
    >>>> c = Contact('aaa','bbb')
    >>>> c = Contact('ccc','ddd')
    >>>> c = Contact('eee','fff')
    >>>> for i in Contact.all_contacts:

    > print i.name + ' ' + i.email
    >
    >
    > aaa bbb
    > ccc ddd
    > eee fff
    >>>>
    >>>> c.name

    > 'eee'
    >
    > So wouldn't be good to add a check that the var (in this case c) does
    > not point to any object before creating an object to keep the list
    > correct?


    Since you don't use "c", there is no use storing it at all! Note that
    you don't have to store a reference to an object that you created, just
    calling "Contact('fou', 'barre')" without assigning to anything is fine.
    Note that I don't find this example good, in reality I would prefer a
    factory method (e.g. called "register(name, email)") that makes clear
    that you are not simply creating an instance.

    Also, concerning OOP, classes in Python are objects, too. Therefore,
    this could be decorated with "@classmethod" to allow the use with
    derived classes. However, I think that's going a bit too far at the
    moment. Just wanted to mention that there are more features waiting for
    you to discover.


    > Also all_contacts is a class variable. I think the author is hinting
    > that this would be a good idea for a contact list, But I don't fully
    > see the usage of it. How would each object use a class variable like
    > this? What would be the dot notation?


    How would an object use a method defined in the class? The point is that
    when calling "fou.barre(42)", the expression "fou.barre" is evaluated
    first and then used in a call expression with the parameter 42. Note
    that you can even evaluate that expression without calling the resulting
    function, but instead assign its result to a variable. In order to
    evaluate that expression, Python first looks for an attribute "barre" in
    the instance and returns that if found. If the instance doesn't have it,
    it looks in the class via the instances __class__ attribute. At that
    point, a little case-specific magic happens. If it finds a normal
    function without "@classmethod" or "@staticmethod" decorator, it returns
    this function with the first parameter (customary called "self") bound
    to the instance. If it finds a non-function, that object is returned
    as-is instead.

    To sum up, you can use "Contact.all_contacts" or e.g. "c.all_contacts"
    to refer to the list of contacts. The second syntax also includes
    "self.all_contacts" when inside a memberfunction, after all the "self"
    is nothing magic or special.

    Uli
     
    Ulrich Eckhardt, Oct 29, 2012
    #4
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Abs
    Replies:
    1
    Views:
    1,100
    Thomas Weidenfeller
    May 11, 2004
  2. Hung Jung Lu

    Pure Aspect-Oriented Program: an example

    Hung Jung Lu, Nov 6, 2003, in forum: Python
    Replies:
    5
    Views:
    353
    Hung Jung Lu
    Nov 9, 2003
  3. Replies:
    2
    Views:
    486
    Bruno Desthuilliers
    May 26, 2008
  4. Hung Jung Lu
    Replies:
    2
    Views:
    190
    Hung Jung Lu
    Nov 9, 2003
  5. rolo
    Replies:
    3
    Views:
    201
    Robert Klemme
    Apr 9, 2004
Loading...

Share This Page