Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #47554 > unrolled thread
| Started by | Rui Maciel <rui.maciel@gmail.com> |
|---|---|
| First post | 2013-06-10 14:18 +0100 |
| Last post | 2013-06-13 19:23 +0100 |
| Articles | 20 on this page of 32 — 11 participants |
Back to article view | Back to comp.lang.python
Newbie: question regarding references and class relationships Rui Maciel <rui.maciel@gmail.com> - 2013-06-10 14:18 +0100
Re: Newbie: question regarding references and class relationships Roy Smith <roy@panix.com> - 2013-06-10 09:35 -0400
Re: Newbie: question regarding references and class relationships Rui Maciel <rui.maciel@gmail.com> - 2013-06-10 14:57 +0100
Re: Newbie: question regarding references and class relationships Rui Maciel <rui.maciel@gmail.com> - 2013-06-10 15:00 +0100
Re: Newbie: question regarding references and class relationships Ian Kelly <ian.g.kelly@gmail.com> - 2013-06-10 13:56 -0600
Re: Newbie: question regarding references and class relationships Rick Johnson <rantingrickjohnson@gmail.com> - 2013-06-11 17:02 -0700
Re: Newbie: question regarding references and class relationships Peter Otten <__peter__@web.de> - 2013-06-10 15:49 +0200
Re: Newbie: question regarding references and class relationships Rui Maciel <rui.maciel@gmail.com> - 2013-06-10 14:59 +0100
Re: Newbie: question regarding references and class relationships Peter Otten <__peter__@web.de> - 2013-06-10 16:28 +0200
Re: Newbie: question regarding references and class relationships Rui Maciel <rui.maciel@gmail.com> - 2013-06-10 15:38 +0100
Re: Newbie: question regarding references and class relationships Peter Otten <__peter__@web.de> - 2013-06-10 17:05 +0200
Re: Newbie: question regarding references and class relationships Rui Maciel <rui.maciel@gmail.com> - 2013-06-10 16:20 +0100
Re: Newbie: question regarding references and class relationships Peter Otten <__peter__@web.de> - 2013-06-10 17:55 +0200
Re: Newbie: question regarding references and class relationships Rui Maciel <rui.maciel@gmail.com> - 2013-06-10 17:09 +0100
Re: Newbie: question regarding references and class relationships Peter Otten <__peter__@web.de> - 2013-06-10 19:07 +0200
Re: Newbie: question regarding references and class relationships Rui Maciel <rui.maciel@gmail.com> - 2013-06-10 18:42 +0100
Re: Newbie: question regarding references and class relationships Dave Angel <davea@davea.name> - 2013-06-10 15:36 -0400
Re: Newbie: question regarding references and class relationships Rui Maciel <rui.maciel@gmail.com> - 2013-06-10 21:31 +0100
Re: Newbie: question regarding references and class relationships Terry Jan Reedy <tjreedy@udel.edu> - 2013-06-10 15:51 -0400
Re: Newbie: question regarding references and class relationships Rui Maciel <rui.maciel@gmail.com> - 2013-06-10 21:13 +0100
Re: Newbie: question regarding references and class relationships Terry Jan Reedy <tjreedy@udel.edu> - 2013-06-10 18:07 -0400
Re: Newbie: question regarding references and class relationships Grant Edwards <invalid@invalid.invalid> - 2013-06-10 22:39 +0000
Re: Newbie: question regarding references and class relationships Chris Angelico <rosuav@gmail.com> - 2013-06-11 08:54 +1000
Re: Newbie: question regarding references and class relationships Tim Chase <python.list@tim.thechases.com> - 2013-06-10 18:24 -0500
Re: Newbie: question regarding references and class relationships Dave Angel <davea@davea.name> - 2013-06-10 19:26 -0400
Re: Newbie: question regarding references and class relationships Jason Swails <jason.swails@gmail.com> - 2013-06-10 23:49 -0400
Re: Newbie: question regarding references and class relationships Terry Jan Reedy <tjreedy@udel.edu> - 2013-06-10 15:54 -0400
Re: Newbie: question regarding references and class relationships Rui Maciel <rui.maciel@gmail.com> - 2013-06-10 21:09 +0100
Re: Newbie: question regarding references and class relationships Rick Johnson <rantingrickjohnson@gmail.com> - 2013-06-11 16:50 -0700
Re: Newbie: question regarding references and class relationships Rui Maciel <rui.maciel@gmail.com> - 2013-06-13 13:06 +0100
Re: Newbie: question regarding references and class relationships Chris Angelico <rosuav@gmail.com> - 2013-06-14 00:07 +1000
Re: Newbie: question regarding references and class relationships Rui Maciel <rui.maciel@gmail.com> - 2013-06-13 19:23 +0100
Page 1 of 2 [1] 2 Next page →
| From | Rui Maciel <rui.maciel@gmail.com> |
|---|---|
| Date | 2013-06-10 14:18 +0100 |
| Subject | Newbie: question regarding references and class relationships |
| Message-ID | <kp4jf4$5fu$1@dont-email.me> |
Let:
- class Point be a data type which is used to define points in space
- class Line be a data type which possesses an aggregate relationship with
objects of type Point
- class Model be a container class which stores collections of Point and
Line objects
Essentially, a Model object stores lists of Point objects and Line objects,
and Line objects include references to Point objects which represent the
starting and ending point of a line.
To reflect this class relationship, I've defined the following classes:
<code>
class Point:
position = []
def __init__(self, x, y, z = 0):
self.position = [x, y, z]
class Line:
points = ()
def __init__(self, p_i, p_f):
self.points = (p_i, p_f)
class Model:
points = []
lines = []
</code>
It would be nice if, whenever a Point object was updated, the Line objects
which are associated with it could reflect those updates directly in
Line.p_i and Line.p_f.
What's the Python way of achieving the same effect?
Thanks in advance,
Rui Maciel
[toc] | [next] | [standalone]
| From | Roy Smith <roy@panix.com> |
|---|---|
| Date | 2013-06-10 09:35 -0400 |
| Message-ID | <roy-FBA6CB.09354310062013@news.panix.com> |
| In reply to | #47554 |
In article <kp4jf4$5fu$1@dont-email.me>, Rui Maciel <rui.maciel@gmail.com> wrote: > Essentially, a Model object stores lists of Point objects and Line objects, > and Line objects include references to Point objects which represent the > starting and ending point of a line. > > class Point: > position = [] > > def __init__(self, x, y, z = 0): > self.position = [x, y, z] > > class Line: > points = () > def __init__(self, p_i, p_f): > self.points = (p_i, p_f) > > class Model: > points = [] > lines = [] > > > It would be nice if, whenever a Point object was updated, the Line objects > which are associated with it could reflect those updates directly in > Line.p_i and Line.p_f. Have you tried running the code you wrote? It does that already! When you do something like: my_list = [obj1, obj2] in Python, the objects are stored by reference (not just lists, all assignments are by reference).
[toc] | [prev] | [next] | [standalone]
| From | Rui Maciel <rui.maciel@gmail.com> |
|---|---|
| Date | 2013-06-10 14:57 +0100 |
| Message-ID | <kp4lnn$hfi$1@dont-email.me> |
| In reply to | #47555 |
Roy Smith wrote: > Have you tried running the code you wrote? It does that already! When > you do something like: > > my_list = [obj1, obj2] > > in Python, the objects are stored by reference (not just lists, all > assignments are by reference). I've tested the following: <code> model = Model() model.points.append(Point(1,2)) model.points.append(Point(1,4)) line = Line( model.points[0], model.points[1]) # Case A: this works model.points[0].position = [2,3,4] line.points # Case B: this doesn't work test.model.points[0] = test.Point(5,4,7) line.points </code> Is there a Python way of getting the same effect with Case B? Thanks in advance, Rui Maciel
[toc] | [prev] | [next] | [standalone]
| From | Rui Maciel <rui.maciel@gmail.com> |
|---|---|
| Date | 2013-06-10 15:00 +0100 |
| Message-ID | <kp4lt7$hfi$3@dont-email.me> |
| In reply to | #47559 |
Rui Maciel wrote: > # Case B: this doesn't work > test.model.points[0] = test.Point(5,4,7) Disregard the "test." bit. I was testing the code by importing the definitions as a module. Rui Maciel
[toc] | [prev] | [next] | [standalone]
| From | Ian Kelly <ian.g.kelly@gmail.com> |
|---|---|
| Date | 2013-06-10 13:56 -0600 |
| Message-ID | <mailman.2985.1370894224.3114.python-list@python.org> |
| In reply to | #47559 |
On Mon, Jun 10, 2013 at 7:57 AM, Rui Maciel <rui.maciel@gmail.com> wrote:
> # Case A: this works
> model.points[0].position = [2,3,4]
> line.points
>
> # Case B: this doesn't work
> test.model.points[0] = test.Point(5,4,7)
> line.points
> </code>
>
>
> Is there a Python way of getting the same effect with Case B?
It's informative to think about what object is actually being mutated
in each of those examples. In A, you are mutating the Point instance
by replacing its "position" attribute with a new list. Since the Line
object references the same Point instance, it "sees" the change. In
B, you are actually mutating a list *containing* the Point instance,
by replacing the Point in the list with some new Point. The replaced
Point itself is not changed at all (apart from having one fewer
reference), and so from the perspective of the Line nothing has
changed.
There are a couple of ways you might get this to work the way you
want. One is by adding as an extra layer a proxy object, which could
be as simple as:
class Proxy(object):
def __init__(self, ref):
self.ref = ref
Instead of adding points to the model, add instances of Proxy that
contain the points. When adding points to the lines, add the same
Proxy objects instead. Later, when you want to replace a point in the
model, leave the Proxy in place but change the Point it contains by
modifying the "ref" attribute. Since the Line only directly
references the Proxy, it must follow the same ref attribute to access
the Point, and so in that way it will "see" the change. The downsides
to this approach are that you have to then use the Proxy objects all
over the place and explicitly "dereference" them by using the ref
attribute all over the place.
Another possibility is to subclass the list used to store the points,
in order to modify the way that it replaces items. That could look
something like this:
class UpdateList(list):
def __setitem__(self, index, item):
if isinstance(index, slice):
indices = range(* index.indices(len(self)))
items = list(item)
if len(indices) != len(items):
raise TypeError("Slice length does not match sequence length")
for i, x in zip(indices, items):
self[i].update(x)
else:
self[index].update(item)
Then you just need to add an "update" method to the Point class (and
any other class you might want to use this with) that would update the
Point's attributes to match those of another point. The downside here
is that this is not very Pythonic, in that somebody familiar with
Python who is reading the code would be surprised by the way the model
updates work.
A third possibility of course would be to just not try to do case B.
Cheers,
Ian
[toc] | [prev] | [next] | [standalone]
| From | Rick Johnson <rantingrickjohnson@gmail.com> |
|---|---|
| Date | 2013-06-11 17:02 -0700 |
| Message-ID | <cc0b10b6-1660-44a4-a9e4-05ab24b5eba1@googlegroups.com> |
| In reply to | #47597 |
On Monday, June 10, 2013 2:56:15 PM UTC-5, Ian wrote: > [...] > There are a couple of ways you might get this to work the way you > want. One is by adding as an extra layer a proxy object, which could > be as simple as: > class Proxy(object): > def __init__(self, ref): > self.ref = ref > Instead of adding points to the model, add instances of Proxy that > contain the points. When adding points to the lines, add the same > Proxy objects instead. Oh gawd just stop here! Are you joking? Are you playing coy? Are you attempting to confuse the lad? This type of complexity you suggest is what renders code bases unreadable and gives sloppy programmers "job security". > Later, when you want to replace a point in the > model, leave the Proxy in place but change the Point it contains by > modifying the "ref" attribute. Since the Line only directly > references the Proxy, it must follow the same ref attribute to access > the Point, and so in that way it will "see" the change. The downsides > to this approach are that you have to then use the Proxy objects all > over the place and explicitly "dereference" them by using the ref > attribute all over the place. Teacher: "What is the worse thing since memory management?" Jimmy Says: "ooh! ohh! i know! Teacher: "Yes jimmy?" Jimmy: "Superfluous memory management?" Teacher: "Oh no, I'm sorry Jimmy, you're so close but i was looking for: `Superfluous memory management by proxy`!"
[toc] | [prev] | [next] | [standalone]
| From | Peter Otten <__peter__@web.de> |
|---|---|
| Date | 2013-06-10 15:49 +0200 |
| Message-ID | <mailman.2967.1370872174.3114.python-list@python.org> |
| In reply to | #47554 |
Rui Maciel wrote:
> Let:
> - class Point be a data type which is used to define points in space
> - class Line be a data type which possesses an aggregate relationship with
> objects of type Point
> - class Model be a container class which stores collections of Point and
> Line objects
>
>
> Essentially, a Model object stores lists of Point objects and Line
> objects, and Line objects include references to Point objects which
> represent the starting and ending point of a line.
>
> To reflect this class relationship, I've defined the following classes:
>
> <code>
> class Point:
Don't add
> position = []
to your code. That's not a declaration, but a class attribute and in the
long run it will cause nothing but trouble.
> def __init__(self, x, y, z = 0):
> self.position = [x, y, z]
>
> class Line:
> points = ()
> def __init__(self, p_i, p_f):
> self.points = (p_i, p_f)
>
> class Model:
> points = []
> lines = []
>
>
> </code>
>
> It would be nice if, whenever a Point object was updated, the Line objects
> which are associated with it could reflect those updates directly in
> Line.p_i and Line.p_f.
>
> What's the Python way of achieving the same effect?
Your code already does that. Here's a minimally cleaned up version:
$ cat tmp_points.py
class Point:
def __init__(self, x, y, z=0):
self.position = (x, y, z)
def __str__(self):
return "%s" % (self.position,)
class Line:
def __init__(self, p_i, p_f):
self.points = (p_i, p_f)
def __str__(self):
return "%s-->%s" % self.points
a = Point(1, 2, 3)
b = Point(4, 5, 6)
ab = Line(a, b)
print(ab)
a.position = (10, 20, 30)
print(ab)
$ python3 tmp_points.py
(1, 2, 3)-->(4, 5, 6)
(10, 20, 30)-->(4, 5, 6)
[toc] | [prev] | [next] | [standalone]
| From | Rui Maciel <rui.maciel@gmail.com> |
|---|---|
| Date | 2013-06-10 14:59 +0100 |
| Message-ID | <kp4lrg$hfi$2@dont-email.me> |
| In reply to | #47557 |
Peter Otten wrote: > Don't add > >>position = [] > > to your code. That's not a declaration, but a class attribute and in the > long run it will cause nothing but trouble. Why's that? Rui Maciel
[toc] | [prev] | [next] | [standalone]
| From | Peter Otten <__peter__@web.de> |
|---|---|
| Date | 2013-06-10 16:28 +0200 |
| Message-ID | <mailman.2969.1370874511.3114.python-list@python.org> |
| In reply to | #47560 |
Rui Maciel wrote: > Peter Otten wrote: > >> Don't add >> >>>position = [] >> >> to your code. That's not a declaration, but a class attribute and in the >> long run it will cause nothing but trouble. > > Why's that? Especially with mutable attributes it's hard to keep track whether you are operating on the instance or the class: >>> class Point: ... position = [] ... def __init__(self, x, y, z): ... self.position = [x, y, z] ... >>> a = Point(1, 2, 3) >>> b = Point(10, 20, 30) >>> a.position [1, 2, 3] >>> del a.position >>> a.position [] # did you expect that? >>> del b.position >>> b.position.extend(["did you expect that?"]) >>> a.position ['did you expect that?'] >>> del a.position Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: position
[toc] | [prev] | [next] | [standalone]
| From | Rui Maciel <rui.maciel@gmail.com> |
|---|---|
| Date | 2013-06-10 15:38 +0100 |
| Message-ID | <kp4o3u$pv$1@dont-email.me> |
| In reply to | #47565 |
Peter Otten wrote: > Rui Maciel wrote: > >> Peter Otten wrote: >> >>> Don't add >>> >>>>position = [] >>> >>> to your code. That's not a declaration, but a class attribute and in the >>> long run it will cause nothing but trouble. >> >> Why's that? > > Especially with mutable attributes it's hard to keep track whether you are > operating on the instance or the class: > >>>> class Point: > ... position = [] > ... def __init__(self, x, y, z): > ... self.position = [x, y, z] > ... >>>> a = Point(1, 2, 3) >>>> b = Point(10, 20, 30) >>>> a.position > [1, 2, 3] >>>> del a.position >>>> a.position > [] # did you expect that? >>>> del b.position >>>> b.position.extend(["did you expect that?"]) >>>> a.position > ['did you expect that?'] >>>> del a.position > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > AttributeError: position How do you guarantee that any object of a class has a specific set of attributes? Rui Maciel
[toc] | [prev] | [next] | [standalone]
| From | Peter Otten <__peter__@web.de> |
|---|---|
| Date | 2013-06-10 17:05 +0200 |
| Message-ID | <mailman.2970.1370876729.3114.python-list@python.org> |
| In reply to | #47567 |
Rui Maciel wrote: > How do you guarantee that any object of a class has a specific set of > attributes? You don't. Such a guarantee is like the third wheel on a bike -- it doesn't improve the overall experience. PS: I'd rather not mention the memory-saving technique that is sometimes abused, but here goes: <http://docs.python.org/dev/glossary.html#term-slots>
[toc] | [prev] | [next] | [standalone]
| From | Rui Maciel <rui.maciel@gmail.com> |
|---|---|
| Date | 2013-06-10 16:20 +0100 |
| Message-ID | <kp4qi6$dno$1@dont-email.me> |
| In reply to | #47568 |
Peter Otten wrote: > Rui Maciel wrote: > >> How do you guarantee that any object of a class has a specific set of >> attributes? > > You don't. What's your point regarding attribute assignments in class declarations, then? Rui Maciel
[toc] | [prev] | [next] | [standalone]
| From | Peter Otten <__peter__@web.de> |
|---|---|
| Date | 2013-06-10 17:55 +0200 |
| Message-ID | <mailman.2972.1370879753.3114.python-list@python.org> |
| In reply to | #47571 |
Rui Maciel wrote: > Peter Otten wrote: > >> Rui Maciel wrote: >> >>> How do you guarantee that any object of a class has a specific set of >>> attributes? >> >> You don't. > > > What's your point regarding attribute assignments in class declarations, > then? I don't understand the question. My original point was that you should omit class attributes that don't fulfill a technical purpose.
[toc] | [prev] | [next] | [standalone]
| From | Rui Maciel <rui.maciel@gmail.com> |
|---|---|
| Date | 2013-06-10 17:09 +0100 |
| Message-ID | <kp4tf4$1on$1@dont-email.me> |
| In reply to | #47576 |
Peter Otten wrote: > I don't understand the question. My original point was that you should > omit class attributes that don't fulfill a technical purpose. > You've said the following: <quote> > class Point: Don't add > position = [] to your code. That's not a declaration, but a class attribute and in the long run it will cause nothing but trouble. </quote> We've established that you don't like attribute declarations, at least those you describe as not fulfill a technical purpose. What I don't understand is why you claim that that would "cause nothing but trouble". Rui Maciel
[toc] | [prev] | [next] | [standalone]
| From | Peter Otten <__peter__@web.de> |
|---|---|
| Date | 2013-06-10 19:07 +0200 |
| Message-ID | <mailman.2975.1370884029.3114.python-list@python.org> |
| In reply to | #47577 |
Rui Maciel wrote: > Peter Otten wrote: > >> I don't understand the question. My original point was that you should >> omit class attributes that don't fulfill a technical purpose. >> > > You've said the following: > > <quote> >> class Point: > > Don't add > >> position = [] > > to your code. That's not a declaration, but a class attribute and in the > long run it will cause nothing but trouble. > </quote> > > > We've established that you don't like attribute declarations, at least > those > you describe as not fulfill a technical purpose. What I don't understand > is why you claim that that would "cause nothing but trouble". Have you read the code in the interpreter session I posted? If you do not agree that the demonstrated behaviour is puzzling I'll have to drop my claim... Likewise if you can show a benefit of the >> position = [] line.
[toc] | [prev] | [next] | [standalone]
| From | Rui Maciel <rui.maciel@gmail.com> |
|---|---|
| Date | 2013-06-10 18:42 +0100 |
| Message-ID | <kp52tm$455$1@dont-email.me> |
| In reply to | #47583 |
Peter Otten wrote: > Have you read the code in the interpreter session I posted? > > If you do not agree that the demonstrated behaviour is puzzling I'll have > to drop my claim... I don't see how it should be puzzling. You've deleted the attribute, so it ceassed to exist. > Likewise if you can show a benefit of the > >>>position = [] > > line. I wrote the code that way to declare intent and help document the code. In this case that the class Point is expected to have an attribute named position which will point to a list. Rui Maciel
[toc] | [prev] | [next] | [standalone]
| From | Dave Angel <davea@davea.name> |
|---|---|
| Date | 2013-06-10 15:36 -0400 |
| Message-ID | <mailman.2980.1370893004.3114.python-list@python.org> |
| In reply to | #47584 |
On 06/10/2013 01:42 PM, Rui Maciel wrote: > Peter Otten wrote: > >> Have you read the code in the interpreter session I posted? >> >> If you do not agree that the demonstrated behaviour is puzzling I'll have >> to drop my claim... > > I don't see how it should be puzzling. You've deleted the attribute, so it > ceassed to exist. Clearly you didn't reason through all the code in Peter's example. > > >> Likewise if you can show a benefit of the >> >>>> position = [] >> >> line. > > I wrote the code that way to declare intent and help document the code. In > this case that the class Point is expected to have an attribute named > position which will point to a list. So why do you also have an instance attribute of the same name? If you really want all instances to have the same value for position, you'd better change the __init__() function so it doesn't mask that single value. Could it be that you really meant that instances of class Point are each expected to have an attribute named Position? Could it be that you want each instance's position to be independent of the others? By having a class attribute with the same name as the instance attribute, you're occasionally going to use the class version when you meant the instance one. I suspect you didn't realize the distinction between class attributes and instance attributes, and that a comment would be a much better way to communicate than creating a misleading value. In one of your other messages, you asked: > How do you guarantee that any object of a class has a > specific set of attributes? Answer is to define those INSTANCE attributes in the __init__() method (or occasionally in the __new__() method), and to make sure you don't ever delete them. The attributes of the object are instance attributes, while the attributes defined inside the class are class attributes. Occasionally, it can be useful to let a class attribute be a 'backup' to the instance attributes, but you've got to think through your use case. If memory is really tight, and if nearly all of the instances want the same value, then you could omit the instance attribute except for the exceptional ones, and let the class attribute fill in. But as Peter says, if it's mutable, you then open yourself to somebody changing them all, thinking it was only changing the one. But there are good reasons not to use this trick to save memory. -- DaveA
[toc] | [prev] | [next] | [standalone]
| From | Rui Maciel <rui.maciel@gmail.com> |
|---|---|
| Date | 2013-06-10 21:31 +0100 |
| Message-ID | <kp5cqh$3in$1@dont-email.me> |
| In reply to | #47591 |
Dave Angel wrote: > So why do you also have an instance attribute of the same name? Thanks to this thread, and after a bit of reading, I've finally managed to discover that in Python there are class attributes and instance attributes, the former working similarly to C++'s static member variables and the latter being more like proper member variables. And there was light. Python.org's tutorial could cover this issue a bit better than it does. Thanks for the help, Rui Maciel
[toc] | [prev] | [next] | [standalone]
| From | Terry Jan Reedy <tjreedy@udel.edu> |
|---|---|
| Date | 2013-06-10 15:51 -0400 |
| Message-ID | <mailman.2983.1370893881.3114.python-list@python.org> |
| In reply to | #47577 |
On 6/10/2013 12:09 PM, Rui Maciel wrote: > We've established that you don't like attribute declarations, at least those > you describe as not fulfill a technical purpose. What I don't understand is > why you claim that that would "cause nothing but trouble". Three answers: Look how much trouble it has already caused ;-) Since you are a self-declared newbie, believe us! Since, be definition, useless code can do no good, it can only cause trouble. Think about it. Terry
[toc] | [prev] | [next] | [standalone]
| From | Rui Maciel <rui.maciel@gmail.com> |
|---|---|
| Date | 2013-06-10 21:13 +0100 |
| Message-ID | <kp5bot$sh2$1@dont-email.me> |
| In reply to | #47595 |
Terry Jan Reedy wrote: > Three answers: > Look how much trouble it has already caused ;-) > Since you are a self-declared newbie, believe us! > Since, be definition, useless code can do no good, it can only cause > trouble. Think about it. I don't doubt that there might good reasons for that, but it is always preferable to get the rationale behind a decision to be able to understand how things work and how to do things properly. Rui Maciel
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | comp.lang.python
csiph-web