[Tutor] Properties of an object

Alan Gauld alan.gauld at btinternet.com
Thu Jan 29 23:07:55 CET 2009


"Vicent" <vginer at gmail.com> wrote

> This is an easy question, I guess, but I am not able to find out the 
> answer.

Or in fact a series of not so easy questions! :-)

Andre has already answered most of them but I'll add a few extras.

> (1) Where are the right places to define PROPERTIES for my class, 
> and how (I
> mean, which is the right syntax) must I define them?
>
> As far as I know, the usual place where properties are "declared" 
> and
> assigned is in the   __init__   function.
>
> Can I define properties in other parts of the "Class" code? I am not 
> able to
> deduce it from the things I've read.

Yes but its generally best not to. It makes for easier to maintain 
code
to keep all definitions in the init method - even if the deefinition 
is just
to None initially!

However that is for instance variables, that is ones that are unique
to each instance of your class.

You can also have class variables which are shared by all instances
(and in fact exist even if no instances exist - they are owned by the
class which is itself an object! These are defined outside of a 
method.

> class ExampleFoo :
>    _property1 = 0


Thats a class variable as I've just described.

> And I think that later I found "self._property1" or "self.property1"

These will work as will ExampleFoo._property1

They will, all three, return the same object.

> am not sure of that. Anyway, why the prefix "_", and what does that
> definition "_property = 0" mean and imply?

The assignment simply creates the class variable with an initial value
of zero. The underscore is a Python convention to suggest that users
of the class should not directly access this variable. It is intended 
for
use internally by the class's methods. You will see self._foo as a
naming convention inside methods too.

> I want to get the second part of the list, I mean, the part of list

>>>> a.list[a.position:]
> [3, 4]
>
> Or, if I want the first part of the list:
>
>>>> a.list[:a.position]
> [1, 2]

A common naming convention to do this is

first and butfirst
or first and rest.

However those are usually applied where first means the first element.

In your case we might adapt the convention to be methods called

firstpart()
lastpart()

> For me, I see it as a property of the object, I mean: "tell me which 
> is your
> first part". It is not like an action over the object or 
> to/from/related to
> the object (that would be a method, then).

The way I think of objects is as actors on a stage receiving messages
and responding with actions or results. So a method is the function
carried out in response to a message. Thus you send the message
firstpart() and the object gives you back what you asked for. It also
removes the temptation to access the attributes directly. Although
in Python thats not considered such a heinous crime as in other
OO languages.

> So, this kind of "derived" properties (because they are based on two 
> other
> previously defined "primary" properties) are better to be defined as
> methods, or it is the same?

Now we come to an important terminology point. You are using the
term properties to refer to the internal data items. But in Python a
"property" is a little bit special. It is a variable within a class 
which
can be accessed as if it were a normal variable but in fact the
access will be via two methods (one for getting and one for
setting the value) This is described in the documentation and is
not used all that often in my experience but it can cause confusion
if you use the term property loosely in Python circles. (Actually
having worked through the rest of the mail you might actually
be aware of that and are intending the Pythonic use of property?)

> class ExampleList :
>    def __init__(self, list, position) :
>        self.list = list
>        self.position = position
>        self.list_1stpart = self.list[:self.position]
>        self.list_2ndpart = self.list[self.position:]

You can't do it quite like that or the 1stpart etc will be fixed as
reflections of how it was when you created it - which I assume
is not what you want! You either have to use metthods or create
properties - which will make things look like I think you would
prefer but at the expense of more work.


Also please don't name methods with the object type in the name
it leads to really ugly code. Use firstpart, secondpart or similar,
ie. lose the list_ bit

> Is that right? Is that good practice? If I want to define
> self.list_1stpart   as a property, is the  __init__  function the 
> only and
> the best place to do it?

init is the best place to define your instance variables but
defining properties requires you to define methods too. But
if you want the access to  firstpart/second part to reflect
changes in position you need metods anyway and I'd recommend
using methods called firstpart) and secondpart()

> If not, I suppose I'll have to define it as a method, and then it 
> will look
> like something like this:
>
>    [... within the class definition ...]
>
>    def list_1stpart(self) :
>        return self.list[:self.position]

Yes but please not with the list_ bit. We are trying to hide the
internal data not expose it. And you wind up with something like:

mylist = ExampleList([1,2,3,4,5,6], 3)
mylist.list_1stpart()

Do you see how that then gives a double list in the method call?
The user doesn't need to know you use a list inside! After all you
might change it to a generator someday!

> For me, the "()" look like artificial, not necessary. I would prefer 
> just to
> type    "a.list_1stpart"   , a property.

You can do that by writing a property but to me the () signifies
that I'm sending a message to an object :-)

> (2) properties which can be derived from other "primary" properties, 
> are
> they just methods??

Nope. But I'm not sure exactly what you mean here. In what sense
derived? And how primary? And do you mean real "Python properties"
or just attributes?

> the way, does the "property" approach consume much memory or space 
> than the
> "method" approach??

Not much more memory because the methods used to access the property
are stored once only in the class. Instances access methods via the 
class.

HTH,

-- 
Alan Gauld
Author of the Learn to Program web site
http://www.freenetpages.co.uk/hp/alan.gauld 




More information about the Tutor mailing list