Help understanding an Object Oriented Program example

G

goldtech

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:
print i.name + ' ' + i.email


aaa bbb
ccc ddd
eee fff'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
 
C

Chris Rebert

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:
print i.name + ' ' + i.email


aaa bbb
ccc ddd
eee fff'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
 
C

Chris Angelico

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:
print i.name + ' ' + i.email


aaa bbb
ccc ddd
eee fff'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:
[<__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).
print(i.name + ' ' + i.email)

Hope that helps!

Chris Angelico
 
U

Ulrich Eckhardt

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:

print i.name + ' ' + i.email


aaa bbb
ccc ddd
eee fff
'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
 

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,818
Messages
2,569,732
Members
45,691
Latest member
Dick331194

Latest Threads

Top