Re: Which part of the loop is it going through in this class frame?

2018-03-09 Thread Cameron Simpson

On 08Mar2018 20:25, C W  wrote:

Thank you guys, lots of great answers, very helpful. I got it!

A follow-up question:

How did the value of "object" get passed to "time"? Obviously, they have
different names. How did Python make that connection?

Code is below for convenience.

class Clock(object):
   def __init__(self, time):
   self.time = time
   def print_time(self):
   time = '6:30'
   print(self.time)

clock = Clock('5:30')
clock.print_time()
5:30


"object" isn't really passed anywhere, except to your class construction of 
"Clock". It hasn't any relation to the name "time" at all.


In Python, all classes are subclasses (directly or not) of the base class 
called "object", and your class definition makes that explicit here:


 class Clock(object):

This defines your class as just like the "object" class, but with the following 
extra features, which you go on the define below it.


With "new style classes" (a Python notion, not something special about OOP in 
general) the "object" base class is implicit, so you could just as well have 
written:


 class Clock:

to achieve the same purpose.

Being a subclass of "object" gets you an assortment of methods immediately, 
such as __str__ and __repr__ (used to present a class as a string). You even 
get an __init__ for free, but the default does nothing and that is usually not 
what you need.


Cheers,
Cameron Simpson  (formerly c...@zip.com.au)
--
https://mail.python.org/mailman/listinfo/python-list


Re: LXML: can't register namespace

2018-03-09 Thread Stefan Behnel
Andrew Z schrieb am 07.03.2018 um 05:03:
> Hello,
>  with 3.6 and latest greatest lxml:
> 
> from lxml import etree
> 
> tree = etree.parse('Sample.xml')
> etree.register_namespace('','http://www.example.com')

The default namespace prefix is spelled None (because there is no prefix
for it) and not the empty string.


> causes:
> Traceback (most recent call last):
>   File "/home/az/Work/flask/tutorial_1/src/xml_oper.py", line 16, in
> 
> etree.register_namespace('','http://www.example.com')
>   File "src/lxml/etree.pyx", line 203, in lxml.etree.register_namespace
> (src/lxml/etree.c:11705)
>   File "src/lxml/apihelpers.pxi", line 1631, in lxml.etree._tagValidOrRaise
> (src/lxml/etree.c:35382)
> ValueError: Invalid tag name ''
> 
> partial Sample.xml:
> 
> 
> http://www.example.com";>
>  
>md_status_nonpro="true" type="INDIVIDUAL" prefix="jadoe">
> 
> 
> 
> it seems to not be happy with the empty tag .
> But i'm not sure why and how to go about it.

Could you explain why you want to do that?

Stefan

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


Re: LXML: can't register namespace

2018-03-09 Thread Steven D'Aprano
On Fri, 09 Mar 2018 10:22:23 +0100, Stefan Behnel wrote:

> Andrew Z schrieb am 07.03.2018 um 05:03:
>> Hello,
>>  with 3.6 and latest greatest lxml:
>> 
>> from lxml import etree
>> 
>> tree = etree.parse('Sample.xml')
>> etree.register_namespace('','http://www.example.com')
> 
> The default namespace prefix is spelled None (because there is no prefix
> for it) and not the empty string.

Is that documented somewhere?

Is there a good reason not to support "" as the empty prefix?



-- 
Steve

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


Re: LXML: can't register namespace

2018-03-09 Thread Stefan Behnel
Steven D'Aprano schrieb am 09.03.2018 um 12:41:
> On Fri, 09 Mar 2018 10:22:23 +0100, Stefan Behnel wrote:
> 
>> Andrew Z schrieb am 07.03.2018 um 05:03:
>>> Hello,
>>>  with 3.6 and latest greatest lxml:
>>>
>>> from lxml import etree
>>>
>>> tree = etree.parse('Sample.xml')
>>> etree.register_namespace('','http://www.example.com')
>>
>> The default namespace prefix is spelled None (because there is no prefix
>> for it) and not the empty string.
> 
> Is that documented somewhere?

http://lxml.de/tutorial.html#namespaces


> Is there a good reason not to support "" as the empty prefix?

Well, the "empty prefix" is not an "empty" prefix, it's *no* prefix. The
result is not ":tag" instead of "prefix:tag", the result is "tag".

But even ignoring that difference, why should the API support two ways of
spelling the same thing, and thus encourage users to write diverging code?

Stefan

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


Re: LXML: can't register namespace

2018-03-09 Thread Steven D'Aprano
On Fri, 09 Mar 2018 13:08:10 +0100, Stefan Behnel wrote:

>> Is there a good reason not to support "" as the empty prefix?
> 
> Well, the "empty prefix" is not an "empty" prefix, it's *no* prefix. The
> result is not ":tag" instead of "prefix:tag", the result is "tag".

That makes sense, thanks.


-- 
Steve

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


Re: LXML: can't register namespace

2018-03-09 Thread Peter Otten
Stefan Behnel wrote:

> Andrew Z schrieb am 07.03.2018 um 05:03:
>> Hello,
>>  with 3.6 and latest greatest lxml:
>> 
>> from lxml import etree
>> 
>> tree = etree.parse('Sample.xml')
>> etree.register_namespace('','http://www.example.com')
> 
> The default namespace prefix is spelled None (because there is no prefix
> for it) and not the empty string.

Does that mean the OP shouldn't use register_namespace() at all or that he's 
supposed to replace "" with None?

If the latter -- it looks like None accepted either:

(lxml_again)$ python
Python 3.4.3 (default, Nov 28 2017, 16:41:13) 
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from lxml import etree
>>> etree.register_namespace(None, "http://www.example.com";)
Traceback (most recent call last):
  File "", line 1, in 
  File "src/lxml/etree.pyx", line 200, in lxml.etree.register_namespace 
(src/lxml/etree.c:11612)
  File "src/lxml/apihelpers.pxi", line 1442, in lxml.etree._utf8 
(src/lxml/etree.c:32933)
TypeError: Argument must be bytes or unicode, got 'NoneType'
>>> etree.__version__
'4.1.1'


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


Re: LXML: can't register namespace

2018-03-09 Thread Stefan Behnel
Peter Otten schrieb am 09.03.2018 um 14:11:
> Stefan Behnel wrote:
> 
>> Andrew Z schrieb am 07.03.2018 um 05:03:
>>> Hello,
>>>  with 3.6 and latest greatest lxml:
>>>
>>> from lxml import etree
>>>
>>> tree = etree.parse('Sample.xml')
>>> etree.register_namespace('','http://www.example.com')
>>
>> The default namespace prefix is spelled None (because there is no prefix
>> for it) and not the empty string.
> 
> Does that mean the OP shouldn't use register_namespace() at all or that he's 
> supposed to replace "" with None?

It meant neither of the two, but now that you ask, I would recommend the
first. ;)

An application global setup for the default namespace is never a good idea,
thus my question regarding the actual intention of the OP. Depending on the
context, the right thing to do might be be to either not care at all, or to
not use the default namespace but a normally prefixed one instead, or to
define a (default) namespace mapping for a newly created tree, as shown in
the namespace tutorial.

http://lxml.de/tutorial.html#namespaces

Usually, not caring about namespace prefixes is the best approach. Parsers,
serialisers and compressors can deal with them perfectly and safely, humans
should just ignore the clutter, pitfalls and complexity that they introduce.

Stefan

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


Re: I found strange thing while studying through idle

2018-03-09 Thread Rob Gaddi

On 03/08/2018 07:57 PM, Steven D'Aprano wrote:

[snip]

But it is possible that due to differences between platforms, the
OP's version of IDLE doesn't display a carriage return as \r but
rather as an invisible zero-width space.



Just to derail this conversation a bit, does anyone have a use case in 
the modern (Py3) age for '\r'?  I use b'\r' fairly regularly when 
talking to serial port devices.  But the string version?



--
Rob Gaddi, Highland Technology -- www.highlandtechnology.com
Email address domain is currently out of order.  See above to fix.
--
https://mail.python.org/mailman/listinfo/python-list


Re: I found strange thing while studying through idle

2018-03-09 Thread Paul Moore
On 9 March 2018 at 17:46, Rob Gaddi  wrote:
> On 03/08/2018 07:57 PM, Steven D'Aprano wrote:
>>
>> [snip]
>>
>> But it is possible that due to differences between platforms, the
>> OP's version of IDLE doesn't display a carriage return as \r but
>> rather as an invisible zero-width space.
>>
>
> Just to derail this conversation a bit, does anyone have a use case in the
> modern (Py3) age for '\r'?  I use b'\r' fairly regularly when talking to
> serial port devices.  But the string version?

It's fairly common for backing up and rewriting a progress line in
simple console programs:

for i in range(100):
print(f"\r  \rCompleted: {i}%", end='')
sleep(0.5)

Paul
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: I found strange thing while studying through idle

2018-03-09 Thread Chris Angelico
On Sat, Mar 10, 2018 at 5:10 AM, Paul Moore  wrote:
> On 9 March 2018 at 17:46, Rob Gaddi  wrote:
>> On 03/08/2018 07:57 PM, Steven D'Aprano wrote:
>>>
>>> [snip]
>>>
>>> But it is possible that due to differences between platforms, the
>>> OP's version of IDLE doesn't display a carriage return as \r but
>>> rather as an invisible zero-width space.
>>>
>>
>> Just to derail this conversation a bit, does anyone have a use case in the
>> modern (Py3) age for '\r'?  I use b'\r' fairly regularly when talking to
>> serial port devices.  But the string version?
>
> It's fairly common for backing up and rewriting a progress line in
> simple console programs:
>
> for i in range(100):
> print(f"\r  \rCompleted: {i}%", end='')
> sleep(0.5)
>

Yep, though I prefer end="\r" (or end="\33[K\r" if you can use ANSI
codes) rather than putting the \r at the beginning. It looks nicer to
have the cursor at the end of the line (which your way does, but mine
doesn't), but on the other hand, leaving the cursor at the beginning
means that any output lines (ending with a normal \n) will more
cleanly overwrite the completion percentage line. It's tradeoffs all
around, as always.

But yes, that's one VERY common use of \r.

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


Re: I am a student studying Python in Korea. I found strange thing while studying through idle

2018-03-09 Thread Chris Warrick
On 9 March 2018 at 01:07, 노연수  wrote:
> If you type print (" hello\ rpython ") into the python 3.7.0.b2, only the 
> python is printed and i learned it's a crystal. However, if you type print (" 
> hello\ rpython ") in the python 3.7.0.b2 idle, it is output as hellopython. I 
> wonder why it prints like this. I would appreciate your answer.
>
> I have attached the file so I would appreciate your reference.
> --
> https://mail.python.org/mailman/listinfo/python-list

In both cases, 'hellopython' is printed, only the behavior of the
cursor changes. The `\r` means “move cursor to the start of the line”
in some places, including Terminal/Command Prompt. But not everyone
processes the backspace character — IDLE ignores it, as do many other
text editors.

Another important thing to note about \r is this:

>>> print("python\rhi")
hithon

(PS. it’s better to use a stable version, especially when you’re
learning. PPS. file attachments do not work on this list.)

-- 
Chris Warrick 
PGP: 5EAAEA16On
9 March 2018 at 01:07, 노연수 clear0...@naver.com>
wrote:If you type print ("
hello\ rpython ") into the python 3.7.0.b2, only the python is printed
and i learned it's a crystal. However, if you type print (" hello\
rpython ") in the python 3.7.0.b2 idle, it is output as hellopython. I
wonder why it prints like this. I would appreciate your answer.

I have attached the file so I would appreciate your reference.
--
https://mail.python.org/mailman/listinfo/python-list";
data-saferedirecturl="https://www.google.com/url?hl=en-GB&q=https://mail.python.org/mailman/listinfo/python-list&source=gmail&ust=1520708438742000&usg=AFQjCNGayj8GjRvThJd0aWdvjz6jUEPsgA";
rel="noreferrer"
target="_blank">https://mail.python.org/mailman/listinfo/python-list
--
Chris Warrick https://chriswarrick.com/>PGP:
5EAAEA16

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


Re: I am a student studying Python in Korea. I found strange thing while studying through idle

2018-03-09 Thread Terry Reedy

On 3/8/2018 7:07 PM, 노연수 wrote:

If you type print (" hello\ rpython ") into the python 3.7.0.b2, only the 
python is printed and i learned it's a crystal.


'\r' is a control character than means 'return to the beginning of the 
line'.  When you execute "print('hello\rpython')" in Python running in 
an operating system console, the effect of '\r' depends on the console. 
If the console tries to emulate terminals which moved the cursor or 
printing head in response to '\r', then that is what happens.  The 
effect of various control codes depends on the terminal emulation and 
can be different on different systems.



However, if you type print (" hello\ rpython ") in the python 3.7.0.b2 idle, it 
is output as hellopython.


IDLE is a cross-platform development environment and its shell is not a 
terminal emulator.  Requests to imitate particular terminals/consoles 
have been rejected.  In the case of \r and backspace, it was felt that 
it is better to not erase what has been printed.  If one wants to know 
how a program will operate in a particular console, one should test it 
there.



I have attached the file.


Don't do this.  Copy and paste relevant snippets of code into the 
message.  Attachments are ignored and not sent to subscribers or mirrors. -

Terry Jan Reedy


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


Enumerating all 3-tuples

2018-03-09 Thread Steven D'Aprano
I am trying to enumerate all the three-tuples (x, y, z) where each of x, 
y, z can range from 1 to ∞ (infinity).

This is clearly unhelpful:

for x in itertools.count(1):
for y in itertools.count(1):
for z in itertools.count(1):
print(x, y, z)

as it never advances beyond x=1, y=1 since the innermost loop never 
finishes.

Georg Cantor to the rescue! (Well, almost...)

https://en.wikipedia.org/wiki/Pairing_function

The Russian mathematician Cantor came up with a *pairing function* that 
encodes a pair of integers into a single one. For example, he maps the 
coordinate pairs to integers as follows:

1,1  ->  1
2,1  ->  2
1,2  ->  3
3,1  ->  4
2,2  ->  5

and so forth. He does this by writing out the coordinates in a grid:

1,1  1,2  1,3  1,4  ...
2,1  2,2  2,3  2,4  ...
3,1  3,2  3,3  3,4  ...
4,1  4,2  4,3  4,4  ...
...

and then iterating over them along the diagonals, starting from the top 
corner. That's just what I'm after, and I have this function that works 
for 2-tuples:

def cantor(start=0):
"""Yield coordinate pairs using Cantor's Pairing Function.

Yields coordinate pairs in (Z*,Z*) over the diagonals:

>>> it = cantor()
>>> [next(it) for _ in range(10)]
[(0,0), (1,0), (0,1), (2,0), (1,1), (0,2), (3,0), (2,1), (1,2), (0,3)]

If ``start`` is given, it is used as the first x- and y-coordinate.
"""
i = start
while True:
for j in range(start, i+1):
yield (i-j+start, j)
i += 1


But I've stared at this for an hour and I can't see how to extend the 
result to three coordinates. I can lay out a grid in the order I want:

1,1,1   1,1,2   1,1,3   1,1,4   ...
2,1,1   2,1,2   2,1,3   2,1,4   ...
1,2,1   1,2,2   1,2,3   1,2,4   ...
3,1,1   3,1,2   3,1,3   3,1,4   ...
2,2,1   2,2,2   2,2,3   2,2,4   ...
...

and applying Cantor's diagonal order will give me what I want, but damned 
if I can see how to do it in code.

Clearly I'm having a "cannot brain today" moment.

Can anyone help me out here?



-- 
Steve

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


Re: Enumerating all 3-tuples

2018-03-09 Thread bartc

On 10/03/2018 01:13, Steven D'Aprano wrote:

I am trying to enumerate all the three-tuples (x, y, z) where each of x,
y, z can range from 1 to ∞ (infinity).

This is clearly unhelpful:

for x in itertools.count(1):
 for y in itertools.count(1):
 for z in itertools.count(1):
 print(x, y, z)

as it never advances beyond x=1, y=1 since the innermost loop never
finishes.

Georg Cantor to the rescue! (Well, almost...)

https://en.wikipedia.org/wiki/Pairing_function

The Russian mathematician Cantor came up with a *pairing function* that
encodes a pair of integers into a single one. For example, he maps the
coordinate pairs to integers as follows:

1,1  ->  1
2,1  ->  2
1,2  ->  3
3,1  ->  4
2,2  ->  5

and so forth. He does this by writing out the coordinates in a grid:

1,1  1,2  1,3  1,4  ...
2,1  2,2  2,3  2,4  ...
3,1  3,2  3,3  3,4  ...
4,1  4,2  4,3  4,4  ...
...

...

But I've stared at this for an hour and I can't see how to extend the
result to three coordinates. I can lay out a grid in the order I want:

1,1,1   1,1,2   1,1,3   1,1,4   ...
2,1,1   2,1,2   2,1,3   2,1,4   ...
1,2,1   1,2,2   1,2,3   1,2,4   ...
3,1,1   3,1,2   3,1,3   3,1,4   ...
2,2,1   2,2,2   2,2,3   2,2,4   ...
...



I can't see the patterns here that I can see in the 2-D grid (where the 
first number in each pair in the n'th row is n, and the second number in 
the n'th column is n).


Maybe it needs to be 3-D? (Eg if the 3rd number in the triple is the 
Plane number, then plane 1 looks like:


  1,1,1   1,2,1   1,3,1
  2,1,1   2,2,1   2,3,1
  3,1,1   3,2,1   3,3,1 ...
  ...

But whether that has an equivalent traversal path like the diagonals of 
the 2-D, I don't know. I'm just guessing.)


--
bartc
--
https://mail.python.org/mailman/listinfo/python-list


Re: Enumerating all 3-tuples

2018-03-09 Thread Chris Angelico
On Sat, Mar 10, 2018 at 12:13 PM, Steven D'Aprano
 wrote:
> The Russian mathematician Cantor came up with a *pairing function* that
> encodes a pair of integers into a single one. For example, he maps the
> coordinate pairs to integers as follows:
>
> 1,1  ->  1
> 2,1  ->  2
> 1,2  ->  3
> 3,1  ->  4
> 2,2  ->  5
>
> and so forth. He does this by writing out the coordinates in a grid:
>
> 1,1  1,2  1,3  1,4  ...
> 2,1  2,2  2,3  2,4  ...
> 3,1  3,2  3,3  3,4  ...
> 4,1  4,2  4,3  4,4  ...
> ...
>
> and then iterating over them along the diagonals, starting from the top
> corner.

The diagonals all have a constant sum. You catch the item with a sum
of 2, and then the two with a sum of 3, then the three with a sum of
4, etc. Can that pattern be extended to three dimensions?

(1, 1, 1)
(1, 1, 2) (1, 2, 1) (2, 1, 1)
(1, 1, 3) (1, 2, 2) (1, 3, 1) (2, 1, 2) (2, 2, 1) (3, 1, 1)
etc

Not sure if that helps or not.

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


Re: Enumerating all 3-tuples

2018-03-09 Thread MRAB

On 2018-03-10 01:13, Steven D'Aprano wrote:

I am trying to enumerate all the three-tuples (x, y, z) where each of x,
y, z can range from 1 to ∞ (infinity).

This is clearly unhelpful:

for x in itertools.count(1):
 for y in itertools.count(1):
 for z in itertools.count(1):
 print(x, y, z)

as it never advances beyond x=1, y=1 since the innermost loop never
finishes.

Georg Cantor to the rescue! (Well, almost...)

https://en.wikipedia.org/wiki/Pairing_function

The Russian mathematician Cantor came up with a *pairing function* that
encodes a pair of integers into a single one. For example, he maps the
coordinate pairs to integers as follows:

1,1  ->  1
2,1  ->  2
1,2  ->  3
3,1  ->  4
2,2  ->  5

and so forth. He does this by writing out the coordinates in a grid:

1,1  1,2  1,3  1,4  ...
2,1  2,2  2,3  2,4  ...
3,1  3,2  3,3  3,4  ...
4,1  4,2  4,3  4,4  ...
...

and then iterating over them along the diagonals, starting from the top
corner. That's just what I'm after, and I have this function that works
for 2-tuples:

def cantor(start=0):
 """Yield coordinate pairs using Cantor's Pairing Function.

 Yields coordinate pairs in (Z*,Z*) over the diagonals:

 >>> it = cantor()
 >>> [next(it) for _ in range(10)]
 [(0,0), (1,0), (0,1), (2,0), (1,1), (0,2), (3,0), (2,1), (1,2), (0,3)]

 If ``start`` is given, it is used as the first x- and y-coordinate.
 """
 i = start
 while True:
 for j in range(start, i+1):
 yield (i-j+start, j)
 i += 1


But I've stared at this for an hour and I can't see how to extend the
result to three coordinates. I can lay out a grid in the order I want:

1,1,1   1,1,2   1,1,3   1,1,4   ...
2,1,1   2,1,2   2,1,3   2,1,4   ...
1,2,1   1,2,2   1,2,3   1,2,4   ...
3,1,1   3,1,2   3,1,3   3,1,4   ...
2,2,1   2,2,2   2,2,3   2,2,4   ...
...

and applying Cantor's diagonal order will give me what I want, but damned
if I can see how to do it in code.

Clearly I'm having a "cannot brain today" moment.

Can anyone help me out here?

Think about the totals of each triple. You'll get totals of 3, then 
totals of 4, etc.


This might help, although the order they come out might not be what you 
want:


def triples():
for total in itertools.count(1):
for i in range(1, total):
for j in range(1, total - i):
yield i, j, total - (i + j)
--
https://mail.python.org/mailman/listinfo/python-list


Re: LXML: can't register namespace

2018-03-09 Thread Andrew Z
Stefan,
 thank you for the link. That explains the line of thinking of the package
designer(s).
I also looked@ beautifulsoup and found it to work better with my old brains.

On Fri, Mar 9, 2018 at 9:46 AM, Stefan Behnel  wrote:

> Peter Otten schrieb am 09.03.2018 um 14:11:
> > Stefan Behnel wrote:
> >
> >> Andrew Z schrieb am 07.03.2018 um 05:03:
> >>> Hello,
> >>>  with 3.6 and latest greatest lxml:
> >>>
> >>> from lxml import etree
> >>>
> >>> tree = etree.parse('Sample.xml')
> >>> etree.register_namespace('','http://www.example.com')
> >>
> >> The default namespace prefix is spelled None (because there is no prefix
> >> for it) and not the empty string.
> >
> > Does that mean the OP shouldn't use register_namespace() at all or that
> he's
> > supposed to replace "" with None?
>
> It meant neither of the two, but now that you ask, I would recommend the
> first. ;)
>
> An application global setup for the default namespace is never a good idea,
> thus my question regarding the actual intention of the OP. Depending on the
> context, the right thing to do might be be to either not care at all, or to
> not use the default namespace but a normally prefixed one instead, or to
> define a (default) namespace mapping for a newly created tree, as shown in
> the namespace tutorial.
>
> http://lxml.de/tutorial.html#namespaces
>
> Usually, not caring about namespace prefixes is the best approach. Parsers,
> serialisers and compressors can deal with them perfectly and safely, humans
> should just ignore the clutter, pitfalls and complexity that they
> introduce.
>
> Stefan
>
> --
> https://mail.python.org/mailman/listinfo/python-list
>
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Enumerating all 3-tuples

2018-03-09 Thread Ben Bacarisse
Steven D'Aprano  writes:

> I am trying to enumerate all the three-tuples (x, y, z) where each of x, 
> y, z can range from 1 to ∞ (infinity).
>
> This is clearly unhelpful:
>
> for x in itertools.count(1):
> for y in itertools.count(1):
> for z in itertools.count(1):
> print(x, y, z)
>
> as it never advances beyond x=1, y=1 since the innermost loop never 
> finishes.
>
> Georg Cantor to the rescue! (Well, almost...)
>
> https://en.wikipedia.org/wiki/Pairing_function
>
> The Russian mathematician Cantor came up with a *pairing function* that 
> encodes a pair of integers into a single one. For example, he maps the 
> coordinate pairs to integers as follows:
>
> 1,1  ->  1
> 2,1  ->  2
> 1,2  ->  3
> 3,1  ->  4
> 2,2  ->  5
>
> and so forth. He does this by writing out the coordinates in a grid:
>
> 1,1  1,2  1,3  1,4  ...
> 2,1  2,2  2,3  2,4  ...
> 3,1  3,2  3,3  3,4  ...
> 4,1  4,2  4,3  4,4  ...
> ...
>
> and then iterating over them along the diagonals, starting from the top 
> corner. That's just what I'm after, and I have this function that works 
> for 2-tuples:
>
> def cantor(start=0):
> """Yield coordinate pairs using Cantor's Pairing Function.
>
> Yields coordinate pairs in (Z*,Z*) over the diagonals:
>
> >>> it = cantor()
> >>> [next(it) for _ in range(10)]
> [(0,0), (1,0), (0,1), (2,0), (1,1), (0,2), (3,0), (2,1), (1,2), (0,3)]
>
> If ``start`` is given, it is used as the first x- and y-coordinate.
> """
> i = start
> while True:
> for j in range(start, i+1):
> yield (i-j+start, j)
> i += 1
>
>
> But I've stared at this for an hour and I can't see how to extend the 
> result to three coordinates. I can lay out a grid in the order I want:
>
> 1,1,1   1,1,2   1,1,3   1,1,4   ...
> 2,1,1   2,1,2   2,1,3   2,1,4   ...
> 1,2,1   1,2,2   1,2,3   1,2,4   ...
> 3,1,1   3,1,2   3,1,3   3,1,4   ...
> 2,2,1   2,2,2   2,2,3   2,2,4   ...
> ...
>
> and applying Cantor's diagonal order will give me what I want, but damned 
> if I can see how to do it in code.

Rather than a grid you would need a cube, and the diagonals become
planes.  But I think that is an easier way (no code yet though!) unless
you are set on one particular enumeration: consider the triple as a pair
one element of which runs over the enumeration of pairs you already
have.

Start with

  1,1  <->  1
  2,1  <->  2
  1,2  <->  3
  3,1  <->  4
  2,2  <->  5
  1,3  <->  6
  ...

but replace the first element by the numbered pair from this same list:

  (1,1),1
  (2,1),1
  (1,1),2
  (1,2),1
  (2,1),2
  (1,1),3
  ...

If it were a sane time here I'd try to code this.  Looks like fun but it
must wait...

-- 
Ben.
-- 
https://mail.python.org/mailman/listinfo/python-list