[Tutor] Properties of an object

spir denis.spir at free.fr
Thu Jan 29 23:04:40 CET 2009


Le Thu, 29 Jan 2009 19:59:09 +0100,
Vicent <vginer at gmail.com> a écrit :

> This is an easy question, I guess, but I am not able to find out the answer.
> 
> In fact, it is both a Python question and a general programming "style"
> question.
> 
> I want to define a class that contains a list (or a NumPy array) of elements
> of a certain type, and an integer:
> 
> class ExampleList :
>     def __init__(self, list, position) :
>         self.list = list
>         self.position = position
> 
> 
> This is clear to me.
> 
> My first question, which is Python related:
> 
> (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.
> 
> I've also seen sometimes something like this:
> 
> 
> class ExampleFoo :
>     _property1 = 0
> 
>     [...]
> 
> And I think that later I found "self._property1" or "self.property1", but I
> am not sure of that. Anyway, why the prefix "_", and what does that
> definition "_property = 0" mean and imply?

Rather pleased to read such a question here, because when I speak like that the reactions let me feel like if I were a martian ;-}
[I think I get why you are trouble, why the "python way" seems strange, so I will try to answer. But my words are to be read strictly as a personal view. They probably do not reflect the views of the majority.]
There is no real native support for ordinary OOP in python, meaning as is done in most other languages, or according to the theory. There is instead a POOP, where the first P stands for 'python'. The python way lacks for constraints which are considered basic things elsewhere, such as defining a strict list of properties. You wont find e.g.:

class MyCLass
	# list of visible properties
	...
	# list of private things
	...

On the contrary, python is much more flexible. It lets you bind anything to an object, at anytime and from anywhere (inside/outside):

obj = MyClass("prop1")
obj.quality = "prop2"
obj.method()
# list obj's bound attributes,
# stored in "magic" attr '__dict__'
for attr in obj.__dict__.items(): print attr

==>

I'm doing something. I got a result.
('quality', 'prop2')
('result', 'present result')
('start_prop', 'prop1')

This way has huge advantages. It lets doing many things in a light, easy and straighforward manner, compared to many languages where simple things rapidly get heavy. On the other hand, there is a 'heavy' ;-) lack of structure, of frame, of standard, that easily lets code get chaotic -- especially because anything can be influenced by anything else "in the background". Good practice, clear code, sensible structure only depend on the developper's discipline.
There are also (more & more) special features (somewhat abstract and complicated for my taste), that allow a programmer forcing constraints and structure. But they hardly fit the python way. It's forced, indeed. For instance, there are several ways to forbid adding or changing properties -- so that the client willget  an error (that may let the old pythonist stuck).

> Coming back to my ExampleList, I have another "philosophic" question.
> 
> Suppose I'm interested (many times within my "main" program) to recover a
> part of the list contained by an ExampleList object. To be more clear:
> 
> >>> a = ExampleList([1,2,3,4], 2)
> >>> a.list
> [1, 2, 3, 4]
> >>> a.position
> 2
> 
> I want to get the second part of the list, I mean, the part of list
> a.list     that goes from position   a.position    until the last element in
> the list.
> 
> I know I can do it like this:
> 
> >>> a.list[a.position:]
> [3, 4]
> 
> Or, if I want the first part of the list:
> 
> >>> a.list[:a.position]
> [1, 2]
> 
> 
> My problem/question/dilemma:  I want to define it as a property or as a
> method in the class definition, because I am going to need many times "the
> first part of te list" or "the second part of the list".
> 
> 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).
> 
> 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?
> 
> I mean, what I would like to do is this:
> 
> 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:]
> 
> 
> 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?
> 
> 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]
> 
> 
> Then I'll call the method like this:
> 
> >>> a.list_1stpart()
> [1, 2]
> 
> For me, the "()" look like artificial, not necessary. I would prefer just to
> type    "a.list_1stpart"   , a property.
> 
> The general case is (the second question):
> 
> (2) properties which can be derived from other "primary" properties, are
> they just methods??
> 
> I don't know which approach is more correct, from any point of view... By
> the way, does the "property" approach consume much memory or space than the
> "method" approach??
> 
> Thank you very much for your patience...
> 
> 

This is not directly related to python, as you said -- if I well understand what you mean. For any property, you always have the choice between giving the client direct access to the data, or writing a method that returns it. It may be a question of style. When a property is dependant on others, such as a sum of 2 values, or the 2 parts of your list, then the choice becomes:
-1- Either, compute the prop each time the other values change, then let the result available as a simple data attribute.
-2- Or write a function that computes & returns the result on demand only.
Well, my opinion is: if the base data change much, and the result is not often required, choose -2- If the source data change few, and the result is often required, choose -1-.
If you want -1-, then you simply transfer the charge to the base properties -- or rather to methods the client will have to use for setting the properties:

	def set_list(new_list):
		self.list = new_list
		# compute parts 1 & 2
	def set_pos(new_pos):
		self.pos = new_pos
		# compute parts 1 & 2

Denis
------
la vida e estranya


More information about the Tutor mailing list