[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