Re: Method default argument whose type is the class not yet defined

2012-11-11 Thread Oscar Benjamin
On 11 November 2012 02:47, Chris Angelico ros...@gmail.com wrote:
 On Sun, Nov 11, 2012 at 1:43 PM, Ian Kelly ian.g.ke...@gmail.com wrote:
 On Sat, Nov 10, 2012 at 7:13 PM, Chris Angelico ros...@gmail.com wrote:
 I would not assume that. The origin is a point, just like any other.
 With a Line class, you could deem a zero-length line to be like a
 zero-element list, but Point(0,0) is more like the tuple (0,0) which
 is definitely True.

 It's more like the number 0 than the tuple (0,0).

 0 is the origin on a 1-dimensional number line.
 (0,0) is the origin on a 2-dimensional number plane.

 In fact, it might be pointed out that Point(0, 0) is a generalization
 of 0+0j, which is equal to 0.

 Ah, good point. In any case, though, it'd be an utterly inconsequential bug.

You were right the first time, Chris. A point that happens to coincide
with the arbitrarily chosen origin is no more truthy or falsey than
any other. A vector of length 0 on the other hand is a very different
beast.

The significance of zero in real algebra is not that it is the origin
but rather that it is the additive and multiplicative zero:

   a + 0 = a  for any real number a
   a * 0 = 0 for any real number a

The same is true for a vector v0, of length 0:

   v + v0 = v for any vector v
   a * v0 = v0 for any scalar a

There is however no meaningful sense in which points (as opposed to
vectors) can be added to each other or multiplied by anything, so
there is no zero point.

The relationship between points and vectors is analogous to the
relationship between datetimes and timedeltas. Having Vector(0, 0)
evaluate to False is analogous to having timedelta(0) evaluate to
False and is entirely sensible. Having Point(0, 0) evaluate to False
is precisely the same conceptual folly that sees midnight evaluate as
False.


Oscar
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Method default argument whose type is the class not yet defined

2012-11-11 Thread Steven D'Aprano
On Sun, 11 Nov 2012 14:21:19 +, Oscar Benjamin wrote:

 On 11 November 2012 02:47, Chris Angelico ros...@gmail.com wrote:
 On Sun, Nov 11, 2012 at 1:43 PM, Ian Kelly ian.g.ke...@gmail.com
 wrote:
 On Sat, Nov 10, 2012 at 7:13 PM, Chris Angelico ros...@gmail.com
 wrote:
 I would not assume that. The origin is a point, just like any other.
 With a Line class, you could deem a zero-length line to be like a
 zero-element list, but Point(0,0) is more like the tuple (0,0) which
 is definitely True.

Don't conflate the set of all tuples of arbitrary length with points, 
which have fixed length. Points are not *sequences* -- in Python, we 
treat tuples as sequences first and records second, because that is a 
useful thing to do. (But it is not the only useful thing to do: if we 
treated them as records first and sequences second, we might want to say 
that a tuple t was falsey if all the fields in t were falsey.)

In the case of a Point class, a Point is definitely not a sequence. That 
we put the x-coordinate first and the y-coordinate second is a mere 
convention, like writing left to right. The mathematical properties of 
points do not depend on the x-coordinate coming first. Since points 
should not be treated as sequences, the requirement that non-empty 
sequences be treated as truthy is irrelevant.


 It's more like the number 0 than the tuple (0,0).

 0 is the origin on a 1-dimensional number line. (0,0) is the origin on
 a 2-dimensional number plane.

 In fact, it might be pointed out that Point(0, 0) is a generalization
 of 0+0j, which is equal to 0.

 Ah, good point. In any case, though, it'd be an utterly inconsequential
 bug.
 
 You were right the first time, Chris. A point that happens to coincide
 with the arbitrarily chosen origin is no more truthy or falsey than any
 other. A vector of length 0 on the other hand is a very different beast.

Nonsense. The length and direction of a vector is relative to the origin. 
If the origin is arbitrary, as you claim, then so is the length of the 
vector.

Just because we can perform vector transformations on the plane to move 
the origin to some point other that (0,0) doesn't make (0,0) an 
arbitrarily chosen origin. It is no more arbitrary than 0 as the origin 
of the real number line.

And yes, we can perform 1D vector transformations on the real number line 
too. Here's a version of range that sets the origin to 42, not 0:

def myrange(start, end=None, step=1):
if end is None:
start = 42
return range(start, end, step)


Nevertheless, there really is something special about the point 0 on the 
real number line, the point (0,0) on the complex number plane, the point 
(0,0,0) in the 3D space, (0,0,0,0) in 4D space, etc. It is not just an 
arbitrary convention that we set the origin to 0.

In other words: to the extent that your arguments that zero-vectors are 
special are correct, the same applies to zero-points, since vectors are 
defined as a magnitude and direction *from the origin*.

To put it yet another way:

The complex number a+bj is equivalent to the 2D point (a, b) which is 
equivalent to the 2D vector [a, b]. If (0, 0) shouldn't be considered 
falsey, neither should [0, 0].


 The significance of zero in real algebra is not that it is the origin
 but rather that it is the additive and multiplicative zero:
 
a + 0 = a  for any real number a
a * 0 = 0 for any real number a

I'm not sure what you mean by additive and multiplicative zero, you 
appear to be conflating two different properties here. 0 is the additive 
*identity*, but 1 is the multiplicative identity:

a + 0 = a
a * 1 = a
for any real number a.

If the RHS must be zero, then there is a unique multiplicative zero, but 
no unique additive zero:

a * 0 = 0 for any real number a
a + -a = 0 for any real number a


 The same is true for a vector v0, of length 0:
 
v + v0 = v for any vector v
a * v0 = v0 for any scalar a

Well that's a bogus analogy. Since you're talking about the domain of 
vectors, the relevant identify for the second line should be:

v * v0 = v0 for any vector v

except that doesn't work, since vector algebra doesn't define a vector 
multiplication operator.[1] It does define multiplication between a 
vector and a scalar, which represents a scale transformation.


 There is however no meaningful sense in which points (as opposed to
 vectors) can be added to each other or multiplied by anything, so there
 is no zero point.

I think that the great mathematician Carl Gauss would have something to 
say about that.

Points in the plane are equivalent to complex numbers, and you can 
certainly add and multiply complex numbers. Adding two points is 
equivalent to a translation; multiplication of a scalar with a point is 
equivalent to a scale transformation. Multiplying two points is 
equivalent to complex multiplication, which is a scale + a rotation.

Oh look, that's exactly the same geometric interpretation as for vectors. 
Hardly surprising, 

Re: Method default argument whose type is the class not yet defined

2012-11-11 Thread Oscar Benjamin
On 11 November 2012 22:31, Steven D'Aprano
steve+comp.lang.pyt...@pearwood.info wrote:
 On Sun, 11 Nov 2012 14:21:19 +, Oscar Benjamin wrote:

 On 11 November 2012 02:47, Chris Angelico ros...@gmail.com wrote:
 On Sun, Nov 11, 2012 at 1:43 PM, Ian Kelly ian.g.ke...@gmail.com
 wrote:
 On Sat, Nov 10, 2012 at 7:13 PM, Chris Angelico ros...@gmail.com
 wrote:
 I would not assume that. The origin is a point, just like any other.
 With a Line class, you could deem a zero-length line to be like a
 zero-element list, but Point(0,0) is more like the tuple (0,0) which
 is definitely True.
 It's more like the number 0 than the tuple (0,0).

 0 is the origin on a 1-dimensional number line. (0,0) is the origin on
 a 2-dimensional number plane.

 In fact, it might be pointed out that Point(0, 0) is a generalization
 of 0+0j, which is equal to 0.

 Ah, good point. In any case, though, it'd be an utterly inconsequential
 bug.

 You were right the first time, Chris. A point that happens to coincide
 with the arbitrarily chosen origin is no more truthy or falsey than any
 other. A vector of length 0 on the other hand is a very different beast.

 Nonsense. The length and direction of a vector is relative to the origin.
 If the origin is arbitrary, as you claim, then so is the length of the
 vector.

Wrong on all counts. Neither the length not the direction os a vector
are relative to any origin. When we choose to express a vector in
Cartesian components our representation assumes an orientation for the
axes of the coordinate system. Even in this sense, though, the origin
itself does not affect the components of the vector.

I have spent a fair few hours in the past few weeks persuading
teenaged Engineering students to maintain a clear distinction between
points, vectors and lines. One of the ways that I distinguish vectors
from points is to say that a vector is like an arrow but its base has
no particular position. A point on the other hand is quite simply a
position. Given an origin (an arbitrarily chosen point) we can specify
another point using a position vector: a vector from the origin to
the point in question.

 Just because we can perform vector transformations on the plane to move
 the origin to some point other that (0,0) doesn't make (0,0) an
 arbitrarily chosen origin. It is no more arbitrary than 0 as the origin
 of the real number line.

(0, 0) are the coordinates of the origin *relative to itself*. Had we
chosen a different origin, the point that was previously called (0, 0)
would now be called (a, b) for some other numbers a and b.

 And yes, we can perform 1D vector transformations on the real number line
 too. Here's a version of range that sets the origin to 42, not 0:

 def myrange(start, end=None, step=1):
 if end is None:
 start = 42
 return range(start, end, step)

This is lost on me...

 Nevertheless, there really is something special about the point 0 on the
 real number line

Agreed.

 , the point (0,0) on the complex number plane,

Also agreed.

 the point
 (0,0,0) in the 3D space, (0,0,0,0) in 4D space, etc. It is not just an
 arbitrary convention that we set the origin to 0.

Wrong. The point (0,0,0,...) in some ND space is an arbitrarily chosen
position. By this I don't mean to say that the sequence of coordinates
consisting of all zeros is arbitrary. The choice of the point *in the
real/hypothetical space* that is designated by the sequence of zero
coordinates is arbitrary.

 In other words: to the extent that your arguments that zero-vectors are
 special are correct, the same applies to zero-points, since vectors are
 defined as a magnitude and direction *from the origin*.

Plain wrong. Vectors are not defined *from any origin*.

 To put it yet another way:

 The complex number a+bj is equivalent to the 2D point (a, b) which is
 equivalent to the 2D vector [a, b]. If (0, 0) shouldn't be considered
 falsey, neither should [0, 0].

a+bj is not equivalent to the 2D point (a, b). It is possible to
define a mapping between complex numbers and a 2D space so that a+bj
corresponds to the point (a, b) *under that map*. However there are an
infinite number of such possible mappings between the two spaces
including a+bj - (a+1, b+1).

 The significance of zero in real algebra is not that it is the origin
 but rather that it is the additive and multiplicative zero:

a + 0 = a  for any real number a
a * 0 = 0 for any real number a

 I'm not sure what you mean by additive and multiplicative zero, you
 appear to be conflating two different properties here. 0 is the additive
 *identity*, but 1 is the multiplicative identity:

I mean that it has the properties that zero has when used in addition
and multiplication:
http://en.wikipedia.org/wiki/0_%28number%29#Elementary_algebra


 a + 0 = a
 a * 1 = a
 for any real number a.

No. I meant the two properties that I listed.


 If the RHS must be zero, then there is a unique multiplicative zero, but
 no unique additive zero:

 a * 0 = 0 

Re: Method default argument whose type is the class not yet defined

2012-11-11 Thread Steve Howell
On Nov 10, 11:33 am, Jennie namedotpor...@gmail.com wrote:
 What is the best solution to solve the following problem in Python 3.3?

 import math
   class Point:
 ...     def __init__(self, x=0, y=0):
 ...         self.x = x
 ...         self.y = y
 ...     def __sub__(self, other):
 ...         return Point(self.x - other.x, self.y - other.y)
 ...     def distance(self, point=Point()):
 ...         Return the distance from `point`.
 ...         return math.sqrt((self - point).x ** 2 + (self - point).y ** 2)

Before you do anything else, introduce a Vector class into your app.
The difference between two Points is not a Point; it's a Vector.
Create a magnitude() method in your Vector class, then make your
Point.distance return the results of Vector.magnitude(self - other).
To define the distance of a point from the origin, don't make your
distance() method have default arguments; instead, define another
method called distance_from_origin().

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Method default argument whose type is the class not yet defined

2012-11-11 Thread Steve Howell
On Nov 11, 4:31 pm, Oscar Benjamin oscar.j.benja...@gmail.com wrote:
 On 11 November 2012 22:31, Steven D'Aprano

  Nonsense. The length and direction of a vector is relative to the origin.
  If the origin is arbitrary, as you claim, then so is the length of the
  vector.

 Wrong on all counts. Neither the length not the direction os a vector
 are relative to any origin. When we choose to express a vector in
 Cartesian components our representation assumes an orientation for the
 axes of the coordinate system. Even in this sense, though, the origin
 itself does not affect the components of the vector.


Thank you for pushing back on Steven's imprecise statement that the
direction of a vector is relative to the origin.

You can't find an angle between two points.  That's absurd.  You need
axes for context.


 Vectors, points and complex numbers are not equivalent. There are
 cases in which it is reasonable to think of them as equivalent for a
 particular purpose. That does not diminish the fundamental differences
 between them.


I looked to wikipedia for clarity, but the definition of a Euclidean
vector is somewhat muddy:

http://en.wikipedia.org/wiki/Euclidean_vector

They say that the formal definition of a vector is a directed line
segment.  But then they define a free vector as an entity where only
the magnitude and direction matter, not the initial point.

As you say, it's not unreasonable to treat vectors, points, and
complex numbers as equivalent in many circumstances.  But, if you're
gonna be pedantic, they really are different things.

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Method default argument whose type is the class not yet defined

2012-11-11 Thread Mark Lawrence

On 12/11/2012 00:31, Oscar Benjamin wrote:


Plain wrong. Vectors are not defined *from any origin*.



So when the Captain says full speed ahead, steer 245 degrees, you 
haven't the faintest idea where you're going, because you have no origin?


--
Cheers.

Mark Lawrence.

--
http://mail.python.org/mailman/listinfo/python-list


Re: Method default argument whose type is the class not yet defined

2012-11-11 Thread Oscar Benjamin
On 12 November 2012 01:10, Mark Lawrence breamore...@yahoo.co.uk wrote:
 On 12/11/2012 00:31, Oscar Benjamin wrote:


 Plain wrong. Vectors are not defined *from any origin*.


 So when the Captain says full speed ahead, steer 245 degrees, you haven't
 the faintest idea where you're going, because you have no origin?

As Steve has just explained, the origin has nothing to do with the
orientation of the coordinate system.

But then I'm assuming you meant that 245 degrees was a bearing
relative to North. Was it supposed to be relative to my current angle?
Truthfully I wouldn't know what to do without asking the captain a
couple more questions.


Oscar
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Method default argument whose type is the class not yet defined

2012-11-11 Thread Roy Smith
In article mailman.3570.1352682390.27098.python-l...@python.org,
 Mark Lawrence breamore...@yahoo.co.uk wrote:

 On 12/11/2012 00:31, Oscar Benjamin wrote:
 
  Plain wrong. Vectors are not defined *from any origin*.
 
 
 So when the Captain says full speed ahead, steer 245 degrees, you 
 haven't the faintest idea where you're going, because you have no origin?

Vectors have a length (full speed ahead) and a direction (245 
degrees).  What they don't have is a fixed location in space.  The 
captain didn't say, Full speed ahead, steer 245 degrees, from 45.0N, 
20.0W.

In other words, you are correct.  The order, full speed ahead, steer 
245 degrees, doesn't give you the faintest idea of where you're going.  
If you were the helmsman, after you executed that order, without any 
additional information (such as your current location), you would have 
no idea what piece of land you will hit, or when you will hit it, if you 
maintain your current course and speed.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Method default argument whose type is the class not yet defined

2012-11-11 Thread Mark Lawrence

On 12/11/2012 01:18, Oscar Benjamin wrote:

On 12 November 2012 01:10, Mark Lawrence breamore...@yahoo.co.uk wrote:

On 12/11/2012 00:31, Oscar Benjamin wrote:



Plain wrong. Vectors are not defined *from any origin*.



So when the Captain says full speed ahead, steer 245 degrees, you haven't
the faintest idea where you're going, because you have no origin?


As Steve has just explained, the origin has nothing to do with the
orientation of the coordinate system.

But then I'm assuming you meant that 245 degrees was a bearing
relative to North. Was it supposed to be relative to my current angle?
Truthfully I wouldn't know what to do without asking the captain a
couple more questions.


Oscar



The only good acedemic is a dead acedemic?

--
Cheers.

Mark Lawrence.

--
http://mail.python.org/mailman/listinfo/python-list


Re: Method default argument whose type is the class not yet defined

2012-11-11 Thread Mark Lawrence

On 12/11/2012 01:15, Roy Smith wrote:

In article mailman.3570.1352682390.27098.python-l...@python.org,
  Mark Lawrence breamore...@yahoo.co.uk wrote:


On 12/11/2012 00:31, Oscar Benjamin wrote:


Plain wrong. Vectors are not defined *from any origin*.



So when the Captain says full speed ahead, steer 245 degrees, you
haven't the faintest idea where you're going, because you have no origin?


Vectors have a length (full speed ahead) and a direction (245
degrees).  What they don't have is a fixed location in space.  The
captain didn't say, Full speed ahead, steer 245 degrees, from 45.0N,
20.0W.

In other words, you are correct.  The order, full speed ahead, steer
245 degrees, doesn't give you the faintest idea of where you're going.
If you were the helmsman, after you executed that order, without any
additional information (such as your current location), you would have
no idea what piece of land you will hit, or when you will hit it, if you
maintain your current course and speed.



Thank you for your explanation.

--
Cheers.

Mark Lawrence.

--
http://mail.python.org/mailman/listinfo/python-list


Re: Method default argument whose type is the class not yet defined

2012-11-11 Thread Roy Smith
In article mailman.3571.1352683098.27098.python-l...@python.org,
 Oscar Benjamin oscar.j.benja...@gmail.com wrote:

 But then I'm assuming you meant that 245 degrees was a bearing
 relative to North. Was it supposed to be relative to my current angle?
 Truthfully I wouldn't know what to do without asking the captain a
 couple more questions.

Granted, this requires some domain-specific knowledge, but an order to 
steer 245 degrees means relative to north (and, technically, it's a 
heading, not a bearing, but that's another discussion).

If the captain wanted you to change you heading relative to your current 
heading, he would say something like, turn left 10 degrees (that may 
not be strictly the correct wording).
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Method default argument whose type is the class not yet defined

2012-11-11 Thread Oscar Benjamin
On 12 November 2012 01:29, Mark Lawrence breamore...@yahoo.co.uk wrote:
 On 12/11/2012 01:18, Oscar Benjamin wrote:

 On 12 November 2012 01:10, Mark Lawrence breamore...@yahoo.co.uk wrote:

 On 12/11/2012 00:31, Oscar Benjamin wrote:

 Plain wrong. Vectors are not defined *from any origin*.

 So when the Captain says full speed ahead, steer 245 degrees, you
 haven't
 the faintest idea where you're going, because you have no origin?


 As Steve has just explained, the origin has nothing to do with the
 orientation of the coordinate system.

 But then I'm assuming you meant that 245 degrees was a bearing
 relative to North. Was it supposed to be relative to my current angle?
 Truthfully I wouldn't know what to do without asking the captain a
 couple more questions.

 The only good acedemic is a dead acedemic?

Is that what happens when people ask questions on your ship: it's the
plank for him with the questions-askin'!

I'm glad you're not my captain.


Oscar
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Method default argument whose type is the class not yet defined

2012-11-11 Thread Steven D'Aprano
On Mon, 12 Nov 2012 00:31:53 +, Oscar Benjamin wrote:

[...]
 You were right the first time, Chris. A point that happens to coincide
 with the arbitrarily chosen origin is no more truthy or falsey than
 any other. A vector of length 0 on the other hand is a very different
 beast.

 Nonsense. The length and direction of a vector is relative to the
 origin. If the origin is arbitrary, as you claim, then so is the length
 of the vector.
 
 Wrong on all counts. Neither the length not the direction os a vector
 are relative to any origin. When we choose to express a vector in
 Cartesian components our representation assumes an orientation for the
 axes of the coordinate system. Even in this sense, though, the origin
 itself does not affect the components of the vector.


Draw a set of axes and mark the vector [1, 1]. Here's a crappy ASCII art 
diagram, with X marking the head of the vector and a line drawn from the 
origin to the head.

|
|   X
|  /
| /
|/
+--


Now draw a second set of axes with the origin set at the head of that 
vector. For reference, I leave the previous axis in place. As before, X 
represents the head of the vector.


|   |
X-
|   |
|   |
|   |
+---|--


Note that the body of the vector -- the line from the origin to the 
head -- is gone. That's because the vector [1, 1] is transformed to the 
vector [0, 0] under a translation of one unit in both the X and Y 
directions. The magnitude of the vector under one coordinate system is 1, 
under the second it is 0.

In a nutshell, you can't talk about either *distance* (magnitude) or 
*direction* without an answer to distance from where? direction relative 
to what?.


 I have spent a fair few hours in the past few weeks persuading teenaged
 Engineering students to maintain a clear distinction between points,
 vectors and lines. One of the ways that I distinguish vectors from
 points is to say that a vector is like an arrow but its base has no
 particular position. A point on the other hand is quite simply a
 position. Given an origin (an arbitrarily chosen point) we can specify
 another point using a position vector: a vector from the origin to the
 point in question.

Just because you have spent a lot of time and effort giving people advice 
doesn't make it *good* advice.



[...]
 Wrong. The point (0,0,0,...) in some ND space is an arbitrarily chosen
 position. By this I don't mean to say that the sequence of coordinates
 consisting of all zeros is arbitrary. The choice of the point *in the
 real/hypothetical space* that is designated by the sequence of zero
 coordinates is arbitrary.

So what? All you are saying is that there is more than one coordinate 
system, and we can choose the one we like for any problem. Of course we 
can, and that's a good thing.



 The significance of zero in real algebra is not that it is the origin
 but rather that it is the additive and multiplicative zero:

a + 0 = a  for any real number a
a * 0 = 0 for any real number a

 I'm not sure what you mean by additive and multiplicative zero, you
 appear to be conflating two different properties here. 0 is the
 additive *identity*, but 1 is the multiplicative identity:
 
 I mean that it has the properties that zero has when used in addition
 and multiplication:
 http://en.wikipedia.org/wiki/0_%28number%29#Elementary_algebra

I see no reference to additive and multiplicative zero there. Did you 
make up that terminology? The *identity* element is a common mathematical 
term, but 1 is the multiplicative identity element.

What you are describing is generally known as the absorbing element 
over multiplication: if X*a = X for any a, then X is an absorbing element 
under multiplication.

http://en.wikipedia.org/wiki/Absorbing_element


And by the way, the vector [0, 0] (generalised to however many dimensions 
you need) is not necessarily the only null (zero) vector. Some vector 
spaces have many null vectors with non-zero components.

http://en.wikipedia.org/wiki/Zero_vector

but I digress.

The exact terminology doesn't really change anything, since everything 
you say about vector [0,0] applies equally to the point (0,0) in the 
Cartesian plane.



[...]
 There is however no meaningful sense in which points (as opposed to
 vectors) can be added to each other or multiplied by anything, so
 there is no zero point.

 I think that the great mathematician Carl Gauss would have something to
 say about that.
 
 Is the text below a quote?

No.
 
 Points in the plane are equivalent to complex numbers, and you can
 certainly add and multiply complex numbers. Adding two points is
 equivalent to a translation; multiplication of a scalar with a point is
 equivalent to a scale transformation. Multiplying two points is
 equivalent to complex multiplication, which is a scale + a rotation.
 
 The last point is bizarre. Complex multiplication makes no sense when
 you're trying to think about vectors. Draw a 2D plot and convince
 yourself that the square of the 

Re: Method default argument whose type is the class not yet defined

2012-11-10 Thread Chris Angelico
On Sun, Nov 11, 2012 at 6:33 AM, Jennie namedotpor...@gmail.com wrote:
 ... def distance(self, point=None):
 ... p = point if point else Point()

I'd go with this one. Definitely not the third one, which mutates the
class according to a current global every time a Point is instantiated
- could be *extremely* confusing if the name distance were ever
rebound. You could also fiddle with the default args:

 class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __sub__(self, other):
return Point(self.x - other.x, self.y - other.y)
def distance(self, point=Point()):
return math.sqrt((self - p).x ** 2 + (self - p).y ** 2)

 Point.distance.__defaults__=Point(), # has to be a tuple

ChrisA
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Method default argument whose type is the class not yet defined

2012-11-10 Thread Terry Reedy

On 11/10/2012 2:33 PM, Jennie wrote:

What is the best solution to solve the following problem in Python 3.3?

import math
  class Point:
... def __init__(self, x=0, y=0):
... self.x = x
... self.y = y
... def __sub__(self, other):
... return Point(self.x - other.x, self.y - other.y)
... def distance(self, point=Point()):
... Return the distance from `point`.
... return math.sqrt((self - point).x ** 2 + (self - point).y ** 2)
...
Traceback (most recent call last):
   File stdin, line 1, in module
   File stdin, line 5, in Point
NameError: name 'Point' is not defined

I propose three solutions. The first one:

  class Point:
... def __init__(self, x=0, y=0):
... self.x = x
... self.y = y
... def __sub__(self, other):
... return Point(self.x - other.x, self.y - other.y)
... def distance(self, point=None):
... p = point if point else Point()
... return math.sqrt((self - p).x ** 2 + (self - p).y ** 2)
...
  p = Point()
  p.distance()
0.0
  p.distance(Point(3, 4))
5.0


What I do not like about this one is that it creates a new 0 point each 
time one is needed. Two solutions:


change Point() to point0 in the distance function and create
point0 = Point()
after the class.

-or-
instead of p = line,
px,py = point.x, point.y if point else 0.0, 0.0



The second one:

  class Point:
... def __init__(self, x=0, y=0):
... self.x = x
... self.y = y
... def __sub__(self, other):
... return Point(self.x - other.x, self.y - other.y)
...
  def distance(self, point=Point()):
... return math.sqrt((self - point).x ** 2 + (self - point).y ** 2)
...
  Point.distance = distance
  p = Point()
  p.distance(Point(3, 4))
5.0


my first thought



The last one:

  class Point:
... def __init__(self, x=0, y=0):
... self.x = x
... self.y = y
... Point.distance = distance
... def __sub__(self, other):
... return Point(self.x - other.x, self.y - other.y)
...
  def distance(self, point=Point()):
... return math.sqrt((self - point).x ** 2 + (self - point).y ** 2)
...
  p = Point()
  p.distance(Point(3, 4))
5.0

Is there a better solution?



--
Terry Jan Reedy

--
http://mail.python.org/mailman/listinfo/python-list


Re: Method default argument whose type is the class not yet defined

2012-11-10 Thread Jennie

On 11/10/2012 09:29 PM, Terry Reedy wrote:


On 11/10/2012 2:33 PM, Jennie wrote:


I propose three solutions. The first one:

  class Point:
... def __init__(self, x=0, y=0):
... self.x = x
... self.y = y
... def __sub__(self, other):
... return Point(self.x - other.x, self.y - other.y)
... def distance(self, point=None):
... p = point if point else Point()
... return math.sqrt((self - p).x ** 2 + (self - p).y ** 2)



What I do not like about this one is that it creates a new 0 point each
time one is needed. Two solutions:

change Point() to point0 in the distance function and create
point0 = Point()
after the class.

-or-
instead of p = line,
px,py = point.x, point.y if point else 0.0, 0.0


Thanks, I like the second one :)

--
Jennie
--
http://mail.python.org/mailman/listinfo/python-list


Re: Method default argument whose type is the class not yet defined

2012-11-10 Thread Dave Angel
On 11/10/2012 03:51 PM, Jennie wrote:
 On 11/10/2012 09:29 PM, Terry Reedy wrote:

 On 11/10/2012 2:33 PM, Jennie wrote:

 I propose three solutions. The first one:

   class Point:
 ... def __init__(self, x=0, y=0):
 ... self.x = x
 ... self.y = y
 ... def __sub__(self, other):
 ... return Point(self.x - other.x, self.y - other.y)
 ... def distance(self, point=None):
 ... p = point if point else Point()
 ... return math.sqrt((self - p).x ** 2 + (self - p).y ** 2)

 What I do not like about this one is that it creates a new 0 point each
 time one is needed. Two solutions:

 change Point() to point0 in the distance function and create
 point0 = Point()
 after the class.

 -or-
 instead of p = line,
 px,py = point.x, point.y if point else 0.0, 0.0

 Thanks, I like the second one :)

I like the first, once you fix the minor inefficiency in it;  add the
qualifier is None


... def distance(self, point=None):
... p = point if point is None else Point()
... return math.sqrt((self - p).x ** 2 + (self - p).y ** 2)

The advantage it then has over the second one is that the whole class is
defined inside the class.

-- 

DaveA


-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Method default argument whose type is the class not yet defined

2012-11-10 Thread Steven D'Aprano
On Sat, 10 Nov 2012 20:33:05 +0100, Jennie wrote:

[...]
 I propose three solutions. The first one:
 
   class Point:
 ... def __init__(self, x=0, y=0):
 ... self.x = x
 ... self.y = y
 ... def __sub__(self, other):
 ... return Point(self.x - other.x, self.y - other.y)

Don't do this, because it breaks subclassing. Your instance should 
dynamically get it's own class, not hard-code the name of Point.

return self.__class__(self.x - other.x, self.y - other.y)

That way, when you subclass Point, you can do arithmetic on the subclass 
instances and they will do the Right Thing.

Note: Python's builtin numeric types don't do this, and it is a damned 
nuisance:

py class MyInt(int):
... pass
...
py a, b = MyInt(23), MyInt(42)
py assert type(a) is MyInt and type(b) is MyInt
py type(a + b)
type 'int'


Back to your class:

 ... def distance(self, point=None):
 ... p = point if point else Point()
 ... return math.sqrt((self - p).x ** 2 + (self - p).y ** 2)

Almost but not quite. I assume that, in a full Point class, you would 
want Point(0, 0) to count as false in a boolean context. (A falsey 
value, like None, [], 0.0, etc.) So change the test to an explicit test 
for None, not just any falsey value:

if point is None:
point = self.__class__()  # Allow subclassing to work.


 The second one:
 
   class Point:
 ... def __init__(self, x=0, y=0):
 ... self.x = x
 ... self.y = y
 ... def __sub__(self, other):
 ... return Point(self.x - other.x, self.y - other.y)
 ...
   def distance(self, point=Point()):
 ... return math.sqrt((self - point).x ** 2 + (self - point).y ** 2)
 ...
   Point.distance = distance

Cute, but ugly and messy. You can inject methods into a class, of course, 
but that's an awfully big hammer to crack this tiny little nut. Your 
first solution is better.

Here is a variation which, according to your tastes, may count as more or 
less ugly: inject the default value into the method:

class Point:
def distance(self, other=None):  # None is a placeholder
delta = self - other
return math.sqrt(delta.x ** 2 + delta.y ** 2)

Point.distance.__defaults__ = (Point(),)
# In Python 2, use:
# Point.distance.__func__.func_defaults = (Point(),)



-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Method default argument whose type is the class not yet defined

2012-11-10 Thread Oscar Benjamin
On 10 November 2012 19:33, Jennie namedotpor...@gmail.com wrote:
 What is the best solution to solve the following problem in Python 3.3?

 import math
 class Point:
 ... def __init__(self, x=0, y=0):
 ... self.x = x
 ... self.y = y
 ... def __sub__(self, other):
 ... return Point(self.x - other.x, self.y - other.y)
 ... def distance(self, point=Point()):
 ... Return the distance from `point`.
 ... return math.sqrt((self - point).x ** 2 + (self - point).y ** 2)
 ...
 Traceback (most recent call last):
   File stdin, line 1, in module
   File stdin, line 5, in Point
 NameError: name 'Point' is not defined

I would use namedtuple and make it so that an ordinary tuple could be
used as in place of a Point instance:

 import math
 from collections import namedtuple
 class Point(namedtuple('Point', ['x', 'y'])):
...   def distance(self, other=(0, 0)):
... (myx, myy), (theirx, theiry) = self, other
... return math.sqrt((myx - theirx) ** 2 + (myy - theiry) ** 2)
...
 p = Point(3, 4)
 p.distance()
5.0
 p2 = Point(4, 5)
 p.distance(p2)
1.4142135623730951


Oscar
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Method default argument whose type is the class not yet defined

2012-11-10 Thread Chris Angelico
On Sun, Nov 11, 2012 at 12:13 PM, Steven D'Aprano
steve+comp.lang.pyt...@pearwood.info wrote:
 Almost but not quite. I assume that, in a full Point class, you would
 want Point(0, 0) to count as false in a boolean context. (A falsey
 value, like None, [], 0.0, etc.)

I would not assume that. The origin is a point, just like any other.
With a Line class, you could deem a zero-length line to be like a
zero-element list, but Point(0,0) is more like the tuple (0,0) which
is definitely True. In any case, this would not even matter, beyond
unnecessary work; the bug would occur only if you seek the distance to
Point(0,0), at which point[1] the code would throw out the incoming
Point and go with the default of 0,0. So it'd result in the same
distance.

ChrisA

[1] Sorry, couldn't resist
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Method default argument whose type is the class not yet defined

2012-11-10 Thread Ian Kelly
On Sat, Nov 10, 2012 at 7:13 PM, Chris Angelico ros...@gmail.com wrote:
 I would not assume that. The origin is a point, just like any other.
 With a Line class, you could deem a zero-length line to be like a
 zero-element list, but Point(0,0) is more like the tuple (0,0) which
 is definitely True.

It's more like the number 0 than the tuple (0,0).

0 is the origin on a 1-dimensional number line.
(0,0) is the origin on a 2-dimensional number plane.

In fact, it might be pointed out that Point(0, 0) is a generalization
of 0+0j, which is equal to 0.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Method default argument whose type is the class not yet defined

2012-11-10 Thread Chris Angelico
On Sun, Nov 11, 2012 at 1:43 PM, Ian Kelly ian.g.ke...@gmail.com wrote:
 On Sat, Nov 10, 2012 at 7:13 PM, Chris Angelico ros...@gmail.com wrote:
 I would not assume that. The origin is a point, just like any other.
 With a Line class, you could deem a zero-length line to be like a
 zero-element list, but Point(0,0) is more like the tuple (0,0) which
 is definitely True.

 It's more like the number 0 than the tuple (0,0).

 0 is the origin on a 1-dimensional number line.
 (0,0) is the origin on a 2-dimensional number plane.

 In fact, it might be pointed out that Point(0, 0) is a generalization
 of 0+0j, which is equal to 0.

Ah, good point. In any case, though, it'd be an utterly inconsequential bug.

ChrisA
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Method default argument whose type is the class not yet defined

2012-11-10 Thread Roy Smith
In article mailman.3549.1352601828.27098.python-l...@python.org,
 Ian Kelly ian.g.ke...@gmail.com wrote:

 On Sat, Nov 10, 2012 at 7:13 PM, Chris Angelico ros...@gmail.com wrote:
  I would not assume that. The origin is a point, just like any other.
  With a Line class, you could deem a zero-length line to be like a
  zero-element list, but Point(0,0) is more like the tuple (0,0) which
  is definitely True.
 
 It's more like the number 0 than the tuple (0,0).
 
 0 is the origin on a 1-dimensional number line.
 (0,0) is the origin on a 2-dimensional number plane.

 In fact, it might be pointed out that Point(0, 0) is a generalization
 of 0+0j, which is equal to 0.


If (0,0) is the origin on a plane, then (0,) should be the origin on a 
line.  If you consider 0 + 0j to be the origin of a plane, then 0 is the 
origin of a line.  Either way is plausible, but you need to be 
consistent.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Method default argument whose type is the class not yet defined

2012-11-10 Thread Ian Kelly
On Sat, Nov 10, 2012 at 7:53 PM, Roy Smith r...@panix.com wrote:
 In article mailman.3549.1352601828.27098.python-l...@python.org,
  Ian Kelly ian.g.ke...@gmail.com wrote:

 On Sat, Nov 10, 2012 at 7:13 PM, Chris Angelico ros...@gmail.com wrote:
  I would not assume that. The origin is a point, just like any other.
  With a Line class, you could deem a zero-length line to be like a
  zero-element list, but Point(0,0) is more like the tuple (0,0) which
  is definitely True.

 It's more like the number 0 than the tuple (0,0).

 0 is the origin on a 1-dimensional number line.
 (0,0) is the origin on a 2-dimensional number plane.

 In fact, it might be pointed out that Point(0, 0) is a generalization
 of 0+0j, which is equal to 0.


 If (0,0) is the origin on a plane, then (0,) should be the origin on a
 line.  If you consider 0 + 0j to be the origin of a plane, then 0 is the
 origin of a line.  Either way is plausible, but you need to be
 consistent.

Where I wrote (0,0) is the origin above I was not referring to a
point, not a tuple, but I can see how that was confusing.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Method default argument whose type is the class not yet defined

2012-11-10 Thread Ian Kelly
On Sat, Nov 10, 2012 at 11:43 PM, Ian Kelly ian.g.ke...@gmail.com wrote:
 Where I wrote (0,0) is the origin above I was not referring to a
 point, not a tuple, but I can see how that was confusing.

What I meant to say is I *was* referring to a point.  Gah!
-- 
http://mail.python.org/mailman/listinfo/python-list