How to debug an unfired tkinter event?

2017-10-18 Thread jfong
In last few days, I tried to experiment with the scrolling table implemented in 
canvas, started from this example: 
http://code.activestate.com/recipes/580793-tkinter-table-with-scrollbars/. 
Everything works fine until I moved the scrolling_area instance (which the 
canvas is in) from column=0 to column=1.

The canvas has a binding:
self.canvas.bind('', self._on_canvas_configure)

After this movement, the callback was only triggered when dragging the root 
widget to resize canvas vertically, but not horizontally.

Event seems has OS involved(it's MS Windows XP in my case). How to debug this 
kind of problem, under pdb?

Best Regards,
Jach Fong
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How to debug an unfired tkinter event?

2017-10-19 Thread jfong
Peter Otten at 2017-10-19 UTC+8 PM 3:24:30 wrote:
> It's not clear to me what you mean with this. Did you place the table from 
> the recipe elsewhere inside a window that you created or did you make 
> changes in the recipe's code?

Thank you, Peter. I am using Python 3.4.4 under WinXP. 

When running the file directly from download, I get a table scrolling 
vertically only. If its Table class's __init__ parameter "scroll_horizontally" 
changed to True, it can be scrolled horizontally also. But there is a problem 
when scrolled horizontally, the header field will not align with data field 
anymore. I make some modifications to make it does. So far so good.

Later, I want to make the table also has a vertical header. The first step I 
had taken was to move all 2nd top-level widgets(not much, just four) to right 
one column further to make room for this new widget. I though it's a simple 
work, just increase their grid column value by 1. But Murphy's Law comes, the 
xscrollbar even don't show up when the table was squeezed horizontally.

> > The canvas has a binding:
> > self.canvas.bind('', self._on_canvas_configure)
> > 
> > After this movement, the callback was only triggered when dragging the
> > root widget to resize canvas vertically, but not horizontally.
> > 
> > Event seems has OS involved(it's MS Windows XP in my case). How to debug
> > this kind of problem, under pdb?
> 
> I don't know, but if you can post a small example script that demonstrates 
> the problem, and you are lucky, someone will see the problem.

This is a ~5xx lines file and I think it's not fare to ask forum members to 
look through it. So I decide to ask for help on how to debug it, instead of the 
solution.

I try to change the binding to
 self.bind_all('', self._on_canvas_configure)
and add a line into the callback
 print(event.widget)

I got some info below each time when I squeeze the table:
.
.5006
.5006.50712528
.5006.50712496
.5006.50712464
.5006.50712144
.5006.50712528.50712560.50782256
.5006.50712528.50712560.50782256.50783024
.5006.50712528.50712560.50782256
.5006.50712528.50712560.50782256.50783024

How to change these number(is it a widget ID?) to a meaning name?

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


Re: How to debug an unfired tkinter event?

2017-10-19 Thread jfong
Peter Otten於 2017年10月19日星期四 UTC+8下午6時04分39秒寫道:
> jf...@ms4.hinet.net wrote:
> 
> > Peter Otten at 2017-10-19 UTC+8 PM 3:24:30 wrote:
> >> It's not clear to me what you mean with this. Did you place the table
> >> from the recipe elsewhere inside a window that you created or did you
> >> make changes in the recipe's code?
> > 
> > Thank you, Peter. I am using Python 3.4.4 under WinXP.
> > 
> > When running the file directly from download, I get a table scrolling
> > vertically only. If its Table class's __init__ parameter
> > "scroll_horizontally" changed to True, it can be scrolled horizontally
> > also. But there is a problem when scrolled horizontally, the header field
> > will not align with data field anymore. I make some modifications to make
> > it does. So far so good.
> > 
> > Later, I want to make the table also has a vertical header. The first step
> > I had taken was to move all 2nd top-level widgets(not much, just four) to
> > right one column further to make room for this new widget. I though it's a
> > simple work, just increase their grid column value by 1. But Murphy's Law
> > comes, the xscrollbar even don't show up when the table was squeezed
> > horizontally.
> 
> Thank you for the clarification; I understand your problem much better now.
> 
> > 
> >> > The canvas has a binding:
> >> > self.canvas.bind('', self._on_canvas_configure)
> >> > 
> >> > After this movement, the callback was only triggered when dragging the
> >> > root widget to resize canvas vertically, but not horizontally.
> >> > 
> >> > Event seems has OS involved(it's MS Windows XP in my case). How to
> >> > debug this kind of problem, under pdb?
> >> 
> >> I don't know, but if you can post a small example script that
> >> demonstrates the problem, and you are lucky, someone will see the
> >> problem.
> > 
> > This is a ~5xx lines file and I think it's not fare to ask forum members
> > to look through it. So I decide to ask for help on how to debug it,
> > instead of the solution.
> > 
> > I try to change the binding to
> >  self.bind_all('', self._on_canvas_configure)
> > and add a line into the callback
> >  print(event.widget)
> > 
> > I got some info below each time when I squeeze the table:
> > .
> > .5006
> > .5006.50712528
> > .5006.50712496
> > .5006.50712464
> > .5006.50712144
> > .5006.50712528.50712560.50782256
> > .5006.50712528.50712560.50782256.50783024
> > .5006.50712528.50712560.50782256
> > .5006.50712528.50712560.50782256.50783024
> > 
> > How to change these number(is it a widget ID?) to a meaning name?
> 
> That's the name of the widget in the underlying tcl/tk. You can specify it 
> in Python:
> 
> >>> import tkinter as tk
> >>> print(tk.Button())
> .139817813335904
> >>> print(tk.Button(name="mybutton"))
> .mybutton
> 
> You have to ensure that names are unique.

Thank you. It's very helpful information.

By the way, I just found this problem can be easily seen by not modifing the 
original file too much with the following steps:

1. copy and get the file from the link.
2. change the "scroll_horizontally" parameter in the "Table" class's __init__ 
method to "True"

Running it you will see it perform correctly.

3. Change the "column=x" at line 268, 282, 288, 292, 303 to "column=x+1"

Now it has the problem.

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


Re: How to debug an unfired tkinter event?

2017-10-19 Thread jfong
Peter Otten於 2017年10月20日星期五 UTC+8上午4時37分10秒寫道:
> jf...@ms4.hinet.net wrote:
> 
> > Peter Otten於 2017年10月19日星期四 UTC+8下午6時04分39秒寫道:
> >> jf...@ms4.hinet.net wrote:
> >> 
> >> > Peter Otten at 2017-10-19 UTC+8 PM 3:24:30 wrote:
> >> >> It's not clear to me what you mean with this. Did you place the table
> >> >> from the recipe elsewhere inside a window that you created or did you
> >> >> make changes in the recipe's code?
> >> > 
> >> > Thank you, Peter. I am using Python 3.4.4 under WinXP.
> >> > 
> >> > When running the file directly from download, I get a table scrolling
> >> > vertically only. If its Table class's __init__ parameter
> >> > "scroll_horizontally" changed to True, it can be scrolled horizontally
> >> > also. But there is a problem when scrolled horizontally, the header
> >> > field will not align with data field anymore. I make some modifications
> >> > to make it does. So far so good.
> >> > 
> >> > Later, I want to make the table also has a vertical header. The first
> >> > step I had taken was to move all 2nd top-level widgets(not much, just
> >> > four) to right one column further to make room for this new widget. I
> >> > though it's a simple work, just increase their grid column value by 1.
> >> > But Murphy's Law comes, the xscrollbar even don't show up when the
> >> > table was squeezed horizontally.
> >> 
> >> Thank you for the clarification; I understand your problem much better
> >> now.
> >> 
> >> > 
> >> >> > The canvas has a binding:
> >> >> > self.canvas.bind('', self._on_canvas_configure)
> >> >> > 
> >> >> > After this movement, the callback was only triggered when dragging
> >> >> > the root widget to resize canvas vertically, but not horizontally.
> >> >> > 
> >> >> > Event seems has OS involved(it's MS Windows XP in my case). How to
> >> >> > debug this kind of problem, under pdb?
> >> >> 
> >> >> I don't know, but if you can post a small example script that
> >> >> demonstrates the problem, and you are lucky, someone will see the
> >> >> problem.
> >> > 
> >> > This is a ~5xx lines file and I think it's not fare to ask forum
> >> > members to look through it. So I decide to ask for help on how to debug
> >> > it, instead of the solution.
> >> > 
> >> > I try to change the binding to
> >> >  self.bind_all('', self._on_canvas_configure)
> >> > and add a line into the callback
> >> >  print(event.widget)
> >> > 
> >> > I got some info below each time when I squeeze the table:
> >> > .
> >> > .5006
> >> > .5006.50712528
> >> > .5006.50712496
> >> > .5006.50712464
> >> > .5006.50712144
> >> > .5006.50712528.50712560.50782256
> >> > .5006.50712528.50712560.50782256.50783024
> >> > .5006.50712528.50712560.50782256
> >> > .5006.50712528.50712560.50782256.50783024
> >> > 
> >> > How to change these number(is it a widget ID?) to a meaning name?
> >> 
> >> That's the name of the widget in the underlying tcl/tk. You can specify
> >> it in Python:
> >> 
> >> >>> import tkinter as tk
> >> >>> print(tk.Button())
> >> .139817813335904
> >> >>> print(tk.Button(name="mybutton"))
> >> .mybutton
> >> 
> >> You have to ensure that names are unique.
> > 
> > Thank you. It's very helpful information.
> > 
> > By the way, I just found this problem can be easily seen by not modifing
> > the original file too much with the following steps:
> > 
> > 1. copy and get the file from the link.
> > 2. change the "scroll_horizontally" parameter in the "Table" class's
> > __init__ method to "True"
> > 
> > Running it you will see it perform correctly.
> > 
> > 3. Change the "column=x" at line 268, 282, 288, 292, 303 to "column=x+1"
> > 
> > Now it has the problem.
> 
> There may be other less obvious places that are affected by your 
> modifications. Does changing
> 
> self.grid_columnconfigure(0, weight=1)
> 
> to
> 
> self.grid_columnconfigure(1, weight=1)
> 
> in Table.__init__() help?

There is description about those numbers in the "tkinter 8.5 reference manual" 
section 5.11 Window names. It can be read by w.winfo_name().

After I give every widget a name(using the same Python instance name), the 
utput looks better. Below is the output of the failed one when squeezed 
horizontally:

.table
.table.scrolling_area
.table.yscrollbar
.table.xscrollbar
.table.canvasH
.table.scrolling_area.canvas.innerframe
.table.scrolling_area.canvas.innerframe._body
.table.scrolling_area.canvas.innerframe
.table.scrolling_area.canvas.innerframe._body

Compared to the output of a good one:

.table
.table.scrolling_area
.table.yscrollbar
.table.xscrollbar
.table.canvasH
.table.scrolling_area.canvas

It shows, when the size changed, the failed one fires onto the wrong 
widgets(the innerframe and innerframe._body), not the canvas. The canvas widget 
didn't absorb the space changing!!

That's prove your intuition is correct. The problem is at the column's weight 
setting. After does the changes according to your suggestion, the problem is 
solved. La la!

Thank yo

Re: How to debug an unfired tkinter event?

2017-10-19 Thread jfong
Terry Reedy於 2017年10月20日星期五 UTC+8上午7時37分59秒寫道:
> On 10/19/2017 5:07 AM, jf...@ms4.hinet.net wrote:
> 
> > I got some info below each time when I squeeze the table:
> > .
> > .5006
> > .5006.50712528
> > .5006.50712496
> > .5006.50712464
> > .5006.50712144
> > .5006.50712528.50712560.50782256
> > .5006.50712528.50712560.50782256.50783024
> > .5006.50712528.50712560.50782256
> > .5006.50712528.50712560.50782256.50783024
> > 
> > How to change these number(is it a widget ID?) to a meaning name?
> 
> The number strings as names are the defaults that came from tkinter, not 
> tcl/tk.  In 3.6, the default names were changed to be versions of the 
> class name.
> 
>  >>> import tkinter as tk
>  >>> r = tk.Tk()
>  >>> b = tk.Button(r)
>  >>> b
> 
>  >>> b2 = tk.Button(r)
>  >>> b2
> 
> 
> -- 
> Terry Jan Reedy

It's very nice to have this improvment.

What it will be to the previous number output format, say, .5006.50712528? 
Will it become something like this:



then, that's really great:-)

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


Re: How to debug an unfired tkinter event?

2017-10-21 Thread jfong
Terry Reedy at 2017-10-20 UTC+8 AM 7:37:59 wrote:
> On 10/19/2017 5:07 AM, jf...@ms4.hinet.net wrote:
> 
> > I got some info below each time when I squeeze the table:
> > .
> > .5006
> > .5006.50712528
> > .5006.50712496
> > .5006.50712464
> > .5006.50712144
> > .5006.50712528.50712560.50782256
> > .5006.50712528.50712560.50782256.50783024
> > .5006.50712528.50712560.50782256
> > .5006.50712528.50712560.50782256.50783024
> > 
> > How to change these number(is it a widget ID?) to a meaning name?
> 
> The number strings as names are the defaults that came from tkinter, not 
> tcl/tk.  In 3.6, the default names were changed to be versions of the 
> class name.
> 
>  >>> import tkinter as tk
>  >>> r = tk.Tk()
>  >>> b = tk.Button(r)
>  >>> b
> 
>  >>> b2 = tk.Button(r)
>  >>> b2
> 
> 
I have a question about this change. When there are multiple buttons in the 
same widget hierarchy level and a ".xxx.yyy.!button2" showing up, how to figure 
out which button it means?

By the way, where is the document of this change? Now it doesn't fit the 
description in the "tkinter 8.5 reference manual" anymore.

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


How to modify this from Python 2.x to v3.4?

2017-11-11 Thread jfong
I learned python start from using v3.4 and never has any v2.x experience. There 
is a Pypi project "ctypesgen" I like to use, but it seems is for v2.x. 
(un)Fortunately I found one of its branch on github which announced is for 
Python3, but strangely it still use some v2.x words, for example, print. Its 
last update was at July 2009, maybe at the early age of v3? The one below which 
I can't figure out how to modify. Can someone show me the answer? (I don't want 
to spend time on learning the old history:-)

-
# Available instance types.  This is used when lexers are defined by a class.
# It's a little funky because I want to preserve backwards compatibility
# with Python 2.0 where types.ObjectType is undefined.

try:
   _INSTANCETYPE = (types.InstanceType, types.ObjectType)
except AttributeError:
   _INSTANCETYPE = types.InstanceType
   class object: pass   # Note: needed if no new-style classes present
...
...
...
if module:
# User supplied a module object.
if isinstance(module, types.ModuleType):
ldict = module.__dict__
elif isinstance(module, _INSTANCETYPE):
_items = [(k,getattr(module,k)) for k in dir(module)]
...
...
---

Best Regards,
Jach Fong
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How to modify this from Python 2.x to v3.4?

2017-11-11 Thread jfong
Ned Batchelder於 2017年11月11日星期六 UTC+8下午8時49分27秒寫道:
> This looks like fairly advanced code.  It will be difficult to port to 
> Python 3 *without* understanding some of the old history.  There seem to 
> be forks on GitHub, including one with a pull request about Python 3 
> made in the last few days: 
> https://github.com/davidjamesca/ctypesgen/pull/58 .  I'd recommend 
> working with others on this.

Thank you, Ned.

As I remember that I had opened a thread here last year, trying to use "2To3" 
tool to convert the ctypesgen package, but didn't success.
https://groups.google.com/forum/#!topic/comp.lang.python/9G0FJXmtwbA

This time, somehow I find this "ctypesgen-python-3" package and can't wait to 
give it a try, but is disappointed again. I suppose there are many v3.x users 
who like to use ctypesgen to ease the using of ctypes. But obviously, it's not 
an easy work to do, convert 2 to 3:-)

By the way, does anyone know what the following codes does? (in printer.py 
file) and how to convert it to v3.x?

class WrapperPrinter:
def __init__(self,outpath,options,data):
...
...
self.print_header()
print >>self.file

self.print_preamble()
print >>self.file

self.print_loader()
print >>self.file
...
...

--Jach

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


Re: How to modify this from Python 2.x to v3.4?

2017-11-12 Thread jfong
Rick Johnson於 2017年11月12日星期日 UTC+8上午11時07分20秒寫道:
> `print` was changed from a statement to a function, so it's
> just a matter of converting it to a function call. If you
> read the docs for the new print function, it should be
> relatively easy to translate. I don't understand why you're
> having so much trouble.
> 
> 
> https://docs.python.org/3/whatsnew/3.0.html?highlight=print#common-stumbling-blocks

It's a shame I didn't read its doc in v3.4 thoughtfully:

print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False) 

I thought position argument is essential, but it's not in this function:

If no objects are given, print() will just write end.

Thanks for your reminder.

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


Re: How to modify this from Python 2.x to v3.4?

2017-11-12 Thread jfong
Thomas Jollans於 2017年11月12日星期日 UTC+8下午5時17分38秒寫道:
> By all means, port ctypesgen to Python 3 (and publish your port) if you
> want to, 

I am not the right person because I have never use Python2 before:-)

> but you might want to consider whether it's easier to port your
> code from ctypes/ctypesgen to cffi instead.

CFFI seems is a little complex, at least to me. I had read its document but 
didn't get through yet:-(

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


How to exec a string which has an embedded '\n'?

2017-12-30 Thread jfong
I have a multiline string, something like '''...\nf.write('\n')\n...'''
when pass to exec(), I got
SyntaxError: EOL while scanning string literal

How to get rid of it?

Best Regards,
Jach Fong
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How to exec a string which has an embedded '\n'?

2017-12-31 Thread jfong
Random832於 2017年12月31日星期日 UTC+8下午1時25分50秒寫道:
> On Sat, Dec 30, 2017, at 23:57, jf...@ms4.hinet.net wrote:
> > I have a multiline string, something like '''...\nf.write('\n')\n...'''
> > when pass to exec(), I got
> > SyntaxError: EOL while scanning string literal
> > 
> > How to get rid of it?
> 
> Use \\n for this case, since you want the \n to be interpreted by the exec 
> parser rather than the newline being part of the string.

Thank you, it's very helpful. This answer makes me think about '\' more 
thoughtful:-)

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


Re: How to exec a string which has an embedded '\n'? (Posting On Python-List Prohibited)

2017-12-31 Thread jfong
Lawrence D’Oliveiro於 2018年1月1日星期一 UTC+8上午7時56分02秒寫道:
> On Sunday, December 31, 2017 at 11:04:19 PM UTC+13, jf...@ms4.hinet.net wrote:
> >
> > This answer makes me think about '\' more thoughtful:-)
> 
> Python generating HTML containing JavaScript which generates HTML:
> 
> out.write \
>   (
> "\nfunction %(paramname)s_UpdateProjects()\n"
> # /* refreshes the project list to show enabled and/or disabled 
> projects as appropriate. */
> "  {\n"
> "var IncludeEnabled = document.forms[\"%(formname)s\"]."
> "elements[\"%(paramname)s_show_enabled\"].checked\n"
> "var IncludeDisabled = document.forms[\"%(formname)s\"]."
> "elements[\"%(paramname)s_show_disabled\"].checked\n"
> "var TheList = \"\"\n"
> "for (var i = 0; i < %(paramname)s_ProjectList.length; ++i)\n"
> "  {\n"
> "var ThisProject = %(paramname)s_ProjectList[i]\n"
> "if (ThisProject.enabled ? IncludeEnabled : 
> IncludeDisabled)\n"
> "  {\n"
> "TheList += \" " \"\\\"\" + (ThisProject.selected ? \" SELECTED\" : \"\") + 
> \">\" +"
> " ThisProject.name + \"\\n\"\n"
> "  } /*if*/\n"
> "  } /*for*/\n"
> "DocumentElt(\"%(formname)s_%(paramname)s_list\").innerHTML 
> =\n"
> "\" SIZE=\\\"5\\\"\"%(on_selection_changed)s"
> " + \">\\n\" + TheList + \"\\n\"\n"
> "  } /*%(paramname)s_UpdateProjects*/\n"
> %
> {
> "formname" : FormName,
> "paramname" : ParamName,
> "on_selection_changed" : OnSelectionChanged,
> }
>   )

I don't even dare to read through this code:-( 

How to run it?
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: File opening modes (r, w, a ...)

2018-02-22 Thread jfong
ast於 2018年2月22日星期四 UTC+8下午8時33分00秒寫道:
> Hello
> 
> I share a very valuable table I found on
> StackOverflow about file opening modes
> 
> If like me you always forget the details of
> file opening mode, the following table provides
> a good summary
> 
>| r   r+   w   w+   a   a+
> --|--
> read  | +   +++
> write | ++   ++   +
> write after seek  | ++   +
> create|  +   ++   +
> truncate  |  +   +
> position at start | +   ++   +
> position at end   |   +   +

What the "write after seek" means?

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


Re: File opening modes (r, w, a ...)

2018-02-22 Thread jfong
Lew Pitcher於 2018年2月23日星期五 UTC+8上午9時43分19秒寫道:
> jf...@ms4.hinet.net wrote:
> 
> > ast於 2018年2月22日星期四 UTC+8下午8時33分00秒寫道:
> >> Hello
> >> 
> >> I share a very valuable table I found on
> >> StackOverflow about file opening modes
> >> 
> >> If like me you always forget the details of
> >> file opening mode, the following table provides
> >> a good summary
> >> 
> >>| r   r+   w   w+   a   a+
> >> --|--
> >> read  | +   +++
> >> write | ++   ++   +
> >> write after seek  | ++   +
> >> create|  +   ++   +
> >> truncate  |  +   +
> >> position at start | +   ++   +
> >> position at end   |   +   +
> > 
> > What the "write after seek" means?
> 
> It /should/ mean that programs are permitted to seek to a point in the file, 
> and then write from that point on.
> 
> A write to a read mode ("r") file isn't permitted at all,
> so neither is "write after seek" to a read mode file.
> 
> A write to an append mode ("a" and "a+") file always write to the end of the 
> file, effectively negating any seek.
> 
> HTH
> 
> -- 
> Lew Pitcher
> "In Skills, We Trust"
> PGP public key available upon request

Thank you for explanation.

Mode 'r+', 'a' and 'a+' all can be seek and write, but only 'r+' was marked in 
the table. That's why I was confused. This row seems redundant to me:-)

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


How to make a foreign function run as fast as possible in Windows?

2016-09-26 Thread jfong
This function is in a DLL. It's small but may run for days before complete. I 
want it takes 100% core usage. Threading seems not a good idea for it shares 
the core with others. Will the multiprocessing module do it? Any suggestion?

Thanks ahead.

--Jach

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


Re: How to make a foreign function run as fast as possible in Windows?

2016-09-27 Thread jfong
eryk sun at 2016/9/27 11:44:49AM wrote:
> The threads of a process do not share a single core. The OS schedules
> threads to distribute the load across all cores

hmmm... your answer overthrow all my knowledge about Python threads 
completely:-( I actually had ever considered using ProcessPoolExecutor to do it.

If the load was distributed by the OS schedules across all cores, does it means 
I can't make one core solely running a piece of codes for me and so I have no 
contol on its performance?
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How to make a foreign function run as fast as possible in Windows?

2016-09-28 Thread jfong
eryk sun at 2016/9/28 1:05:32PM wrote:
> In Unix, Python's os module may have sched_setaffinity() to set the
> CPU affinity for all threads in a given process.
> 
> In Windows, you can use ctypes to call SetProcessAffinityMask,
> SetThreadAffinityMask, or SetThreadIdealProcessor (a hint for the
> scheduler). On a NUMA system you can call GetNumaNodeProcessorMask(Ex)
> to get the mask of CPUs that are on a given NUMA node. The cmd shell's
> "start" command supports "/numa" and "/affinity" options, which can be
> combined.

Seems have to dive into Windows to understand its usage:-)
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How to make a foreign function run as fast as possible in Windows?

2016-09-28 Thread jfong
Paul  Moore at 2016/9/28 11:31:50PM wrote:
> Taking a step back from the more detailed answers, would I be right to assume 
> that you want to call this external function multiple times from Python, and 
> each call could take days to run? Or is it that you have lots of calls to 
> make and each one takes a small amount of time but the total time for all the 
> calls is in days?
> 
> And furthermore, can I assume that the external function is *not* written to 
> take advantage of multiple CPUs, so that if you call the function once, it's 
> only using one of the CPUs you have? Is it fully utilising a single CPU, or 
> is it actually not CPU-bound for a single call?
> 
> To give specific suggestions, we really need to know a bit more about your 
> issue.

Forgive me, I didn't notice these detail will infulence the answer:-)

Python will call it once. The center part of this function was written in 
assembly for performance. During its execution, this part might be called 
thousands of million times. The function was written to run in a single CPU, 
but the problem it want to solve can be easily distributed into multiple CPUs.

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


Re: How to make a foreign function run as fast as possible in Windows?

2016-09-30 Thread jfong
Paul  Moore at 2016/9/30 7:07:35PM wrote:
> OK. So if your Python code only calls the function once, the problem needs to 
> be fixed in the external code (the assembly routine). But if you can split up 
> the task at the Python level to make multiple calls to the function, each to 
> do a part of the task, then you could set up multiple threads in your Python 
> code, each of which handles part of the task, then Python merges the results 
> of the sub-parts to give you the final answer. Does that make sense to you? 
> Without any explicit code, it's hard to be sure I'm explaining myself clearly.
> 

That's what I will do later, to split the task into multiple cores by passing a 
range parameter (such as 0~14, 15~29, ..) to each instance. Right now, I just 
embedded the range in the function to make it simple on testing.

At this moment my interest is how to make it runs at 100% core usage. Windows 
task manager shows this function takes only ~70% usage, and the number varies 
during its execution, sometimes even drop to 50%.

I also had test a batch file (copied from another discussion forum):
@echo off
:loop
goto loop
It takes ~85% usage, and the number is stable.

The result is obviously different. My question is how to control it:-)

--Jach

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


Re: How to make a foreign function run as fast as possible in Windows?

2016-10-01 Thread jfong
Chris Angelico at 2016/10/1 11:25:03AM wrote:
> What's it doing? Not every task can saturate the CPU - sometimes they
> need the disk or network more.
> 
This function has no I/O or similar activity, just pure data processing, and it 
takes less than 200 bytes of data area to work with.

My CPU is an i3 (4 threads/2 cores). I suppose after this job was assigned to 
run on a particular core, the OS shouldn't bother it by other system related 
tasks anymore. If it does, won't be this OS designed stupidly?

I was puzzled why the core has no 100% usage? Why always has some percentage of 
idle?

--Jach

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


Is it possible Python can distinguish capital letter and small letter in the path of Windows?

2016-10-11 Thread jfong
I have two files in the Q:\lib directory:

Q:\lib>dir
2007/03/11 AM 08:025,260  lib_MARK.so
2007/03/11 AM 08:024,584  lib_mark.so

Under Python 3.4.4 I got:

>>> f = open('lib_MARK.so', 'br')
>>> data = f.read()
>>> f.close()
>>> len(data)
4584

I know Windows won't, but can Python make it true?

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


Re: Is it possible Python can distinguish capital letter and small letter in the path of Windows?

2016-10-11 Thread jfong
Hi, eryk, thanks for your solution.

I had try to find the document of the _winapi module, but can't find any in my 
installed Python directory. Can you give me a link to look for?

> This alone doesn't make the Windows API case sensitive, but it does
> enable individual CreateFile calls to be case sensitive, via the POSIX
> semantics flag.

Does it means that an application program which uses the POSIX semantics flag 
in its API call will perform case-sensitive automatically after the 
"obcaseinsensitive" flag was modified by the user?

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


Re: Is it possible Python can distinguish capital letter and small letter in the path of Windows?

2016-10-11 Thread jfong
wxjm...@gmail.com at 2016/10/11 9:40:21PM wrote:
> If you are about to modify your registry, do not
> forget to switch your Windows in a *utf-8 mode*.

Have no idea how to "switch" Windows in a "utf-8 mode"? What will happens if 
not? Can you give a simple example? Thanks ahead.

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


help on "from deen import *" vs. "import deen"

2016-11-13 Thread jfong
Running the following codes (deen.py) under Win32 python 3.4.4 terminal:

tbli = [0x66, 0x27, 0xD0]
tblm = [0 for x in range(3)]
def gpa(data):
td = data ^ tblm[2]
return td

I can get a correct answer this way:
>>> import deen
>>> deen.tblm = deen.tbli
>>> deen.gpa(0x7d)
173  # 0xad (= 0x7d ^ 0xd0) is decimal 173

But I get a wrong answer this way:
>>> from deen import *
>>> tblm = tbli
>>> gpa(0x7d)
125  # it's 0x7d, the tblm[2] is 0

Why? why! why:-(

--Jach

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


Re: help on "from deen import *" vs. "import deen"

2016-11-14 Thread jfong
Ned Batchelder at 2016/11/15 6:33:54AM wrote:
> > But I get a wrong answer this way:
> > >>> from deen import *
> > >>> tblm = tbli
> > >>> gpa(0x7d)
> > 125  # it's 0x7d, the tblm[2] is 0
> > 
> > Why? why! why:-(
> 
> Here you are assigning a value to your own tblm, not deen.tblm,
> so gpa does not see the new value.
> 
Hi Ned, below is the capture of my terminal screen:

D:\Temp>python
Python 3.4.4 (v3.4.4:737efcadf5a6, Dec 20 2015, 19:28:18) [MSC v.1600 32 bit (In
tel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> dir()
['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__']

>>> from deen import *
>>> dir()
['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__',
 'gpa', 'tbli', 'tblm']
>>> tblm
[0, 0, 0]
>>> tblm=tbli
>>> tblm
[102, 39, 208]
>>> dir()
['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__',
 'gpa', 'tbli', 'tblm']
>>>

Do you mean the last 'tblm' is my own? How it can be? The 'tblm' already exist 
before the assignment and this assignment shouldn't create a new one, right? 
and how do I assign the 'deen.tblm' under this circumstance?

--Jach

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


Re: help on "from deen import *" vs. "import deen"

2016-11-14 Thread jfong
MRAB at 2016/11/15 11:31:41AM wrote:
> When you say "from deen import *" you're copying names and their 
> references from the module's namespace to your local namespace:
> 
>  [module deen]   [locally]
> 
>  tblm > [0, 0, 0] <- tblm
> 
>  tbli > [102, 39, 208] < tbli

hmm...I always thought that the picture of "from deen import *" is

[locally]

 [0, 0, 0] <- tblm

 [102, 39, 208] < tbli

But obviously it's not. The compiled code of function gpa is still reference to 
a hidden deen.tblm 'global' object which I can't access anymore. A bad news:-(

--Jach

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


Re: help on "from deen import *" vs. "import deen"

2016-11-15 Thread jfong
Michael Torrie at 2016/11/15 10:43:58PM wrote:
> Seems like you're still not understanding Python variables.

I do, just not get used to it yet:-)

>  However once
> you assign to these names in your current module you are breaking this
> link to the deen module and assigning a new object to these names in
> your current module's namespace.

Why? the name "tblm" is already exist and is a mutable one, should be changed 
intuitional by "tblm=tbli". If I really need a new list, I can create one by 
using a new name. Python shouldn't have its finger in my pie:-(

> You're getting hung up on the names,
> when you should be concentrating on what the names refer to.

That's one problem I was concerned. Human beings are very deeply binding on 
words (names?). We think in words, talk in words, communicate in words. 
Actually we are living in words. I really don't like that when I said "John is 
a boy" and was told "No, John is a dog now":-)

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


Re: help on "from deen import *" vs. "import deen"

2016-11-16 Thread jfong
Steve D'Aprano at 2016/11/16 8:33:23AM wrote:
> `import foo` imports the module foo, that is all. (To be pedantic: it is
> *nominally* a module. By design, it could be any object at all.)
> 
> `from foo import *` imports all the visible public attributes of foo.
> 
> They do completely different things, equivalent to something similar to:
> 
> five = int('5')
> 
> 
> versus:
> 
> 
> _tmp = int('5')
> for name in dir(_tmp):
> if not name.startswith('_'):
> locals()[name] = getattr(_tmp, name)
> del _tmp

This is far beyond my comprehension:-(

--Jach

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


Re: help on "from deen import *" vs. "import deen"

2016-11-16 Thread jfong
Michael Torrie at 2016/11/16 11:15:11AM wrote:
> ... The globals object is a dictionary and is itself
> mutable.  But when we assign a new object to a particular dictionary
> key, it tosses out the old reference and makes the key now refer to the
> new object.  It does not do anything to the old object itself.

The last question: Is it possible, in the current Python version, to re-bind a 
global name in module "deen" after it was imported "from deen import *"?

> > That's one problem I was concerned. Human beings are very deeply
> > binding on words (names?). We think in words, talk in words,
> > communicate in words. Actually we are living in words. I really don't
> > like that when I said "John is a boy" and was told "No, John is a dog
> > now":-)
> 
> Not quite sure where you're going with that. I would think the idea of
> labels on objects would be fairly natural. I could stick a label that
> says "chair" on a chair, and then later move that label to the couch.
> Same label, different object.  Whether the label makes sense is up to you.

I mean it might be better to have two labels to label chair and couch 
separately, instead of one:-)

--Jach

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


Re: help on "from deen import *" vs. "import deen"

2016-11-16 Thread jfong
Steven D'Aprano at 2016/11/17 12:06:19PM wrote:
> You understand how this works?

Yes, thank you for your detail explanation.

> import russia as _tmp
> president = _tmp.president
> del _tmp

This one I can understand. But the previous one

>>_tmp = int('5')
>>for name in dir(_tmp):
>>if not name.startswith('_'):
>>locals()[name] = getattr(_tmp, name)
>>del _tmp

which I am still on scratching my head.

Now the question moves from "how" to "why":

Why "del _tmp" at the last step? The only reason I can thought of is 
"information hiding", but from whom? A global variable has its reason to be as 
a global. It may need to be modified later to influence others behavior. Using 
delete to hide the name seems unnecessary and redundant. If someone really 
want, he can follow the solution Chris had provided in his reply.

>>from deen import *
>>...
>>import deen
>>deen.some_name = new_value

A little strange, but effective:-)

--Jach

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


Re: help on "from deen import *" vs. "import deen"

2016-11-17 Thread jfong
Steven D'Aprano at 2016/11/17 4:04:04PM wrote:
> The most important thing you should learn from this thread is:
> 
> - avoid using "from module import *" as it is usually more trouble 
>   than it is worth.
> 
> 
> It is confusing and leads to more problems than it solves. If Python was 
> being 
> invented now, rather than 20 years ago, I would expect that there would be no 
> "import *" in the language.

It's the greatest advice I ever had in Python:-)

--Jach

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


Re: help on "from deen import *" vs. "import deen"

2016-11-17 Thread jfong
Michael Torrie at 2016/11/17 11:38:32PM wrote:
> Like I said, whether the names you use are appropriate is completely up
> to you.  But this statement seems to imply you're still not getting it
> and still thinking of variables as boxes like they are in other
> languages, rather than labels that can only point to one thing at a
> time.

As a knowledge, I do know the re-bind tricky Python had on its variable, and 
that's mostly I stumbled so far when writing Python codes.

> Python's variables are different from other languages, but in an
> understandable way.  

Unfortunately it's also different from human language.

> As Dennis said, understanding Python variables,
> though not difficult, needs to be second nature to you or you'll be
> fighting Python and hating the experience.

That's the point: to build a second nature.

But it won't be easy because of we use human language used everyday:-(

--Jach



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


Re: help on "from deen import *" vs. "import deen"

2016-11-17 Thread jfong
Michael Torrie at 2016/11/18 11:03:12AM wrote:
> >> Python's variables are different from other languages, but in an
> >> understandable way.  
> > 
> > Unfortunately it's also different from human language.
> 
> How so? I don't find this to be true at all.

The fact that most novices will stumble on Python variable many times until it 
becomes his "second nature" proves it's different from the human language:-)

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


How to append a modified list into a list?

2016-11-18 Thread jfong
I have a working list 'tbl' and recording list 'm'. I want to append 'tbl' into 
'm' each time when the 'tbl' was modified. I will record the change by append 
it through the function 'apl'.

For example:

>>>tbl=[0,0]
>>>m=[]

>>>tbl[0]=1
>>>apl(tbl)
>>>m
[[1,0]]

>>>tbl[1]=2
>>>apl(tbl)
>>>m
[[1,0], [1,2]]

How to define this function properly?

Obviously the most intuitive way doesn't work.
def apl0(tbl):
m.append(tbl)

and introducing a local variable will not help either.
def apl1(tbl):
w=tbl
m.append(w)

I figure out a workable way, but looks ugly.
def apl2(tbl):
w=[]
w[:]=tbl
m.append(w)

I know those binding tricks between names and objects. Just wondering if there 
is an elegant way of doing this:-)

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


Re: How to append a modified list into a list?

2016-11-18 Thread jfong
Oh, I don't know slice well enough:-(

So, slice tbl[:] will create a new object (a copy of tbl) which can be passed 
as a function argument
m.append(tbl[:])

or bind to a new name
w=tbl[:]

or re-bind to itself
w[:]=tbl

Thanks you, Ian and Steve.

Steve D'Aprano at 2016/11/19 11:01:26AM wrote:
> In newer versions of Python, you can do this:
> m.append(tbl.copy())

I like it:-)

--Jach

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


Re: help on "from deen import *" vs. "import deen"

2016-11-19 Thread jfong
Chris Angelico at 2016/11/19 2:58:41PM wrote:
> On Sat, Nov 19, 2016 at 3:34 PM, Steve D'Aprano
>  wrote:
> > What happens if you do this?
> >
> > spam = eggs = cheese = obj
> >
> > Is that different from:
> >
> > spam = obj
> > eggs = obj
> > cheese = obj
> >
> >
> > or from this?
> >
> > spam = obj
> > eggs = spam
> > cheese = eggs
> > ...
> > These aren't silly questions.
> 
> Indeed, they are not silly. It surprised me (as a C programmer) that
> the assignments happen left-to-right, rather than right-to-left (in C,
> cheese would be set first, then eggs, then spam). These are questions
> filled with subtleties.
> 
> ChrisA

Why this conversation makes me feel like a fool? Are they different?

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


Re: How to append a modified list into a list?

2016-11-19 Thread jfong
Peter Otten at 2016/11/19 5:40:34PM wrote:
> And now for something completely different ;)
> 
> What if you only record the changes to the list? For a long list that would 
> save space at the expense of calculation time. For example:

Excellent! Although not 100% fit into my application, I must study how this 
Class works. Thank you.

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


Re: help on "from deen import *" vs. "import deen"

2016-11-20 Thread jfong
Tristan B. Kildaire at 2016/11/20 8:23:37PM wrote:
> From deen import * imports all the things in deen but accessable with no 
> `deen.`

These "accessible" objects become read-only even if it's mutable. For immutable 
objects, you can't even create a new one in the deen's namespace.

> import deen imports all of deen but accessible via `deen.thing` 

:-)

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


{:2X} didn't output what I expected

2018-03-19 Thread jfong
D:\Temp>py
Python 3.4.4 (v3.4.4:737efcadf5a6, Dec 20 2015, 19:28:18) [MSC v.1600 32 bit 
(Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> '{:02X}'.format(256)
'100'
>>>
What I expected is '00'. Am I wrong?

Best Regards,
Jach Fong
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: {:2X} didn't output what I expected

2018-03-19 Thread jfong
Chris Angelico於 2018年3月20日星期二 UTC+8上午8時06分05秒寫道:
> On Tue, Mar 20, 2018 at 10:46 AM,   wrote:
> > D:\Temp>py
> > Python 3.4.4 (v3.4.4:737efcadf5a6, Dec 20 2015, 19:28:18) [MSC v.1600 32 
> > bit (Intel)] on win32
> > Type "help", "copyright", "credits" or "license" for more information.
>  '{:02X}'.format(256)
> > '100'
> 
> > What I expected is '00'. Am I wrong?
> >
> 
> Python avoids losing data. If you really want to enforce that this is
> two characters long, you can either restrict the data first (maybe
> with "% 256"), or trim the resulting string:
> 
> >>> '{:02X}'.format(256)[-2:]
> '00'
> 
> ChrisA

I had overlooked the document there it says "width ... defining the minimum 
field width...'. I was wrong, it's not a demand. Thank you, ChrisA.

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


In asyncio, does the event_loop still running after run_until_complete returned?

2018-04-02 Thread jfong
I am new to the asyncio subject, just trying to figure out how to use it. Below 
is the script I use for testing:
-
# asyncio_cancel_task2.py

import asyncio

@asyncio.coroutine
def task_func():
print('in task_func, sleeping')
try:
yield from asyncio.sleep(1)
except asyncio.CancelledError:
print('task_func was canceled')
raise
print('return result')
return 'the result'

def task_canceller(task):
task.cancel()
print('canceled the task')

@asyncio.coroutine
def main(loop):
print('first, scheduling a task')
task = loop.create_task(task_func())
print('second, scheduling its cancellation')
loop.call_later(0.5, task_canceller, task)
try:
print('waiting task to complete')
yield from task
except asyncio.CancelledError:
print('main() also sees task as canceled')


event_loop = asyncio.get_event_loop()
try:
event_loop.run_until_complete(main(event_loop))
finally:
print('wait 3 seconds before closing event_loop')
asyncio.sleep(3)
print('event_loop was closed')
event_loop.close()
---

It schedules two tasks, the task_func and the task_canceller, in main. Before 
the task_func completed, the task_canceller was fired to cancel it. Hence its 
output below seems reasonable.

D:\Works\Python>py
Python 3.4.4 (v3.4.4:737efcadf5a6, Dec 20 2015, 19:28:18) [MSC v.1600 32 bit 
(Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import asyncio_cancel_task2
first, scheduling a task
second, scheduling its cancellation
waiting task to complete
in task_func, sleeping
canceled the task
task_func was canceled
main() also sees task as canceled
wait 3 seconds before closing event_loop
event_loop was closed
>>>

Then, I changed the call_later delay from 0.5 to 1.5, expect it to be called 
after the task_func completed and before the event loop closed. The output 
seems not quite right. Why the task_canceller hasn't been called?

>>> import asyncio_cancel_task2
first, scheduling a task
second, scheduling its cancellation
waiting task to complete
in task_func, sleeping
return result
wait 3 seconds before closing event_loop
event_loop was closed
>>>

Best Regards,
Jach Fong

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


Re: In asyncio, does the event_loop still running after run_until_complete returned?

2018-04-02 Thread jfong
Ian於 2018年4月2日星期一 UTC+8下午9時37分08秒寫道:
> On Mon, Apr 2, 2018 at 5:32 AM,   wrote:
> > I am new to the asyncio subject, just trying to figure out how to use it. 
> > Below is the script I use for testing:
> > -
> > # asyncio_cancel_task2.py
> >
> > import asyncio
> >
> > @asyncio.coroutine
> > def task_func():
> > print('in task_func, sleeping')
> > try:
> > yield from asyncio.sleep(1)
> > except asyncio.CancelledError:
> > print('task_func was canceled')
> > raise
> > print('return result')
> > return 'the result'
> >
> > def task_canceller(task):
> > task.cancel()
> > print('canceled the task')
> >
> > @asyncio.coroutine
> > def main(loop):
> > print('first, scheduling a task')
> > task = loop.create_task(task_func())
> > print('second, scheduling its cancellation')
> > loop.call_later(0.5, task_canceller, task)
> > try:
> > print('waiting task to complete')
> > yield from task
> > except asyncio.CancelledError:
> > print('main() also sees task as canceled')
> >
> >
> > event_loop = asyncio.get_event_loop()
> > try:
> > event_loop.run_until_complete(main(event_loop))
> > finally:
> > print('wait 3 seconds before closing event_loop')
> > asyncio.sleep(3)
> 
> This won't actually wait 3 seconds. It just instantiates a sleep
> coroutine and then discards it. Inside the event loop you would need
> to await or yield from it. Outside the event loop, in order to sleep
> you have to block the thread, e.g. using time.sleep. That said, there
> is no reason to wait before closing the event loop.
> 
Thank you for reminding my mistake. I shouldn't use asyncio.sleep there.

> > print('event_loop was closed')
> > event_loop.close()
> > ---
> >
> > It schedules two tasks, the task_func and the task_canceller, in main. 
> > Before the task_func completed, the task_canceller was fired to cancel it. 
> > Hence its output below seems reasonable.
> >
> > D:\Works\Python>py
> > Python 3.4.4 (v3.4.4:737efcadf5a6, Dec 20 2015, 19:28:18) [MSC v.1600 32 
> > bit (Intel)] on win32
> > Type "help", "copyright", "credits" or "license" for more information.
>  import asyncio_cancel_task2
> > first, scheduling a task
> > second, scheduling its cancellation
> > waiting task to complete
> > in task_func, sleeping
> > canceled the task
> > task_func was canceled
> > main() also sees task as canceled
> > wait 3 seconds before closing event_loop
> > event_loop was closed
> 
> >
> > Then, I changed the call_later delay from 0.5 to 1.5, expect it to be 
> > called after the task_func completed and before the event loop closed. The 
> > output seems not quite right. Why the task_canceller hasn't been called?
> >
>  import asyncio_cancel_task2
> > first, scheduling a task
> > second, scheduling its cancellation
> > waiting task to complete
> > in task_func, sleeping
> > return result
> > wait 3 seconds before closing event_loop
> > event_loop was closed
> 
> 
> Because, as your thread title suggests, after run_until_complete
> returns, the event loop is not running. How could it? It needs a
> thread to run on, but it doesn't create one, so whenever it returns
> from running it is relinquishing the thread and can't do anything
> unless it gets it back, since that thread is now running outer code.
> If you want to, you can restart the event loop by calling one of the
> run methods again; everything that was previously scheduled and
> everything that was scheduled after it stopped will remain scheduled.
> 
I also do a quick check, with call_later delay keeps at 1.5, to see what the 
event loop status is after run_until_complete returns. Strangely, both 
is_closed and is_running return a False.

try:
event_loop.run_until_complete(main(event_loop))
finally:
print(event_loop.is_closed())  # print(event_loop.is_running())


It's not closed(OK, the event_loop.close hasn't be executed yet) and neither 
it's running(quote your words, "it is relinquishing the thread and can't do 
anything")!

Event loop, coroutine, task, yield from, ...etc, all these words' interaction 
makes asyncio has more mystery than I think:-(

> So, you can't have the event loop running in the background while also
> doing things within the code that started the loop in the same thread.
> If you really want this you can create a second thread to run the
> event loop on. However it is usually better to do that sort of thing
> within a coroutine running in the event loop, since single-threaded
> concurrency is the whole point of asyncio. The code that started the
> event loop will then only be used for cleanup after it terminates.

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


Re: In asyncio, does the event_loop still running after run_until_complete returned?

2018-04-03 Thread jfong
Ian於 2018年4月3日星期二 UTC+8下午1時38分57秒寫道:
> On Mon, Apr 2, 2018 at 9:01 PM,   wrote:
> 
> def run_forever(self):
> """Run until stop() is called."""
>try:
> events._set_running_loop(self)
> while True:
> self._run_once()
> if self._stopping:
> break
> finally:
> self._stopping = False
> events._set_running_loop(None)
>
What's the purpose of resetting self._stopping back to False in finally clause?

--Jach

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


Is pdb suitable for debugging asyncio module?

2018-04-04 Thread jfong
I have a module below and run it under pdb, the result seems not easy to xplain.
(Note: the sleep periods are in reverse order)
---
# asyncio_as_completed.py

import asyncio

@asyncio.coroutine
def phase(i):
print('in phase {}'.format(i))
yield from asyncio.sleep(0.5 - (0.1 * i))
print('done with phase {}'.format(i))
return 'phase {} result'.format(i)

@asyncio.coroutine
def main(num_phases):
print('starting main')
phases = [
phase(i)
for i in range(num_phases)
]
print('waiting for phases to complete')
results = []
for next_to_complete in asyncio.as_completed(phases):
answer = yield from next_to_complete  # <--set breakpoint here
print('received answer {!r}'.format(answer))
results.append(answer)
print('results: {!r}'.format(results))
return results

event_loop = asyncio.get_event_loop()
try:
event_loop.run_until_complete(main(3))
finally:
event_loop.close()
---

D:\Works\Python>py -m pdb asyncio_as_completed.py
> d:\works\python\asyncio_as_completed.py(3)()
-> import asyncio
(Pdb) n
> d:\works\python\asyncio_as_completed.py(5)()
-> @asyncio.coroutine
(Pdb) b 22
Breakpoint 1 at d:\works\python\asyncio_as_completed.py:22
(Pdb) c
starting main
waiting for phases to complete
> d:\works\python\asyncio_as_completed.py(22)main()
-> answer = yield from next_to_complete

(Pdb) n
in phase 1
in phase 0
in phase 2
Internal StopIteration# <---
> d:\works\python\asyncio_as_completed.py(8)phase()
-> yield from asyncio.sleep(0.5 - (0.1 * i))
(Pdb) n
> d:\works\python\asyncio_as_completed.py(9)phase()
-> print('done with phase {}'.format(i))
(Pdb) n
done with phase 2
> d:\works\python\asyncio_as_completed.py(10)phase()
-> return 'phase {} result'.format(i)

(Pdb) n
Internal StopIteration: phase 2 result
> d:\works\python\asyncio_as_completed.py(22)main()
-> answer = yield from next_to_complete
(Pdb) n
> d:\works\python\asyncio_as_completed.py(23)main()
-> print('received answer {!r}'.format(answer))
(Pdb) n
received answer 'phase 2 result'# <---
> d:\works\python\asyncio_as_completed.py(24)main()
-> results.append(answer)
(Pdb) n
> d:\works\python\asyncio_as_completed.py(21)main()
-> for next_to_complete in asyncio.as_completed(phases):
(Pdb) n
> d:\works\python\asyncio_as_completed.py(22)main()
-> answer = yield from next_to_complete

(Pdb) n
Internal StopIteration# <---
> d:\works\python\asyncio_as_completed.py(8)phase()
-> yield from asyncio.sleep(0.5 - (0.1 * i))
(Pdb) n
> d:\works\python\asyncio_as_completed.py(9)phase()
-> print('done with phase {}'.format(i))
(Pdb) n
done with phase 1
> d:\works\python\asyncio_as_completed.py(10)phase()
-> return 'phase {} result'.format(i)

(Pdb) n
Internal StopIteration# <---
> d:\works\python\asyncio_as_completed.py(8)phase()
-> yield from asyncio.sleep(0.5 - (0.1 * i))
(Pdb) n
> d:\works\python\asyncio_as_completed.py(9)phase()
-> print('done with phase {}'.format(i))
(Pdb) n
done with phase 0
> d:\works\python\asyncio_as_completed.py(10)phase()
-> return 'phase {} result'.format(i)

(Pdb) n
Internal StopIteration: phase 1 result# <---
> d:\works\python\asyncio_as_completed.py(22)main()
-> answer = yield from next_to_complete
(Pdb) n
> d:\works\python\asyncio_as_completed.py(23)main()
-> print('received answer {!r}'.format(answer))
(Pdb) n
received answer 'phase 1 result'
> d:\works\python\asyncio_as_completed.py(24)main()
-> results.append(answer)
(Pdb) n
> d:\works\python\asyncio_as_completed.py(21)main()
-> for next_to_complete in asyncio.as_completed(phases):
(Pdb) n
> d:\works\python\asyncio_as_completed.py(22)main()
-> answer = yield from next_to_complete

(Pdb) n
> d:\works\python\asyncio_as_completed.py(23)main()
-> print('received answer {!r}'.format(answer))
(Pdb) n
received answer 'phase 0 result'
> d:\works\python\asyncio_as_completed.py(24)main()
-> results.append(answer)
(Pdb) n
> d:\works\python\asyncio_as_completed.py(21)main()
-> for next_to_complete in asyncio.as_completed(phases):

(Pdb) n
> d:\works\python\asyncio_as_completed.py(25)main()
-> print('results: {!r}'.format(results))
(Pdb) n
results: ['phase 2 result', 'phase 1 result', 'phase 0 result']
> d:\works\python\asyncio_as_completed.py(26)main()
-> return results
(Pdb) n
The program finished and will be restarted
> d:\works\python\asyncio_as_completed.py(3)()
-> import asyncio
(Pdb)


I saw three "Internal StopIteration" lines which match the three "phase" tasks, 
it's OK. But there are only two "Internal StopIteration: phase x result" lines, 
the "phase 0" was missed. Why is that?

Best Regards,
Jach Fong
-- 
https://mail.python.org/mailman/listinfo/python-list


How to write partial of a buffer which was returned from a C function to a file?

2018-04-11 Thread jfong
This C function returns a buffer which I declared it as a ctypes.c_char_p. The 
buffer has size 0x1 bytes long and the valid data may vary from a few bytes 
to the whole size.

In every call I know how much the valid data size is, but I suppose I can't use 
slice to get it because there may be zero byte in it. What to do?


Best Regards,
Jach Fong
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: How to write partial of a buffer which was returned from a C function to a file?

2018-04-12 Thread jfong
Chris Angelico於 2018年4月12日星期四 UTC+8下午1時31分35秒寫道:
> On Thu, Apr 12, 2018 at 2:16 PM,   wrote:
> > This C function returns a buffer which I declared it as a ctypes.c_char_p. 
> > The buffer has size 0x1 bytes long and the valid data may vary from a 
> > few bytes to the whole size.
> >
> > In every call I know how much the valid data size is, but I suppose I can't 
> > use slice to get it because there may be zero byte in it. What to do?
> >
> 
> You suppose? Or have you tested it?
> 
> ChrisA

Yes, I had test it once before. Now, I re-do it again to make sure. After a 
call which returns 3 bytes of data, I use len(buf) to check the length and get 
the number 24. I can see the first 24 bytes of data by using buf[:30] but 
buf[24] will cause an "index out of range" error. I don't know how to see what 
the buf[24] exactly is but I suppose it might be a zero byte.

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


Re: How to write partial of a buffer which was returned from a C function to a file?

2018-04-12 Thread jfong
Chris Angelico於 2018年4月12日星期四 UTC+8下午4時05分29秒寫道:
> On Thu, Apr 12, 2018 at 4:20 PM,   wrote:
> > Chris Angelico於 2018年4月12日星期四 UTC+8下午1時31分35秒寫道:
> >> On Thu, Apr 12, 2018 at 2:16 PM,   wrote:
> >> > This C function returns a buffer which I declared it as a 
> >> > ctypes.c_char_p. The buffer has size 0x1 bytes long and the valid 
> >> > data may vary from a few bytes to the whole size.
> >> >
> >> > In every call I know how much the valid data size is, but I suppose I 
> >> > can't use slice to get it because there may be zero byte in it. What to 
> >> > do?
> >> >
> >>
> >> You suppose? Or have you tested it?
> >>
> >> ChrisA
> >
> > Yes, I had test it once before. Now, I re-do it again to make sure. After a 
> > call which returns 3 bytes of data, I use len(buf) to check the length and 
> > get the number 24. I can see the first 24 bytes of data by using buf[:30] 
> > but buf[24] will cause an "index out of range" error. I don't know how to 
> > see what the buf[24] exactly is but I suppose it might be a zero byte.
> >
> 
> If you have 24 bytes, they're numbered 0 through 23. So there is no byte at 
> 24.
> 
> ChrisA

Using a technique you mentioned in subject "how to memory dump an object?" at 
16/5/21, I confirm the length of buf was decided by a \x00 byte:

>>> len(buf)
24
>>> id(buf)
13553888
>>> ptr = ctypes.cast(id(buf), ctypes.POINTER(ctypes.c_ubyte))
>>> buf[:24]
b'\x05ALLOTNPUT_BUFFER_SIZE\x02+'
>>> bytes([ptr[i] for i in range(50)])
b'\x02\x00\x00\x00X\xa1%\x1e\x18\x00\x00\x00\xff\xff\xff\xff\x05ALLOTNPUT_BUFFER_SIZE\x02+\x00\n\x00\x00\x00\x00\x00\x00\xb0\x9b'
>>>

but it won't help on solving my problem. Still need someone's help:-)

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


Re: Observations on the List - "Be More Kind"

2018-10-09 Thread jfong
I am wondering the role of the moderator.

Does he own the server or pay the bill? Where he get the power to suspending 
people? Is he a police or judge? Can he shoot someone just because he has any 
reason?

What will happen if his power was limited? Will the forum be end in disorder? 
No, I don't think so. We are mature enough to keep it running.

--Jach


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


Re: Observations on the List - "Be More Kind"

2018-10-09 Thread jfong
Richard Damon at 2018.10.9 UTC+8 PM 8:40:29 wrote:
> Moderators are generally appointed by those who do 'pay the bill' for
> the mailing list they are moderators for, and serve at their pleasure.
> Mailing List are generally 'private property', though often made open to
> the public for general use. The owners of that property, generally have
> rights to establish rules for the public to use that property (perhaps
> somewhat constrained by whatever laws are applicable at the physical
> location that the mailing list server, owner or moderator resides at).
> 
> Shoot, as in physically, generally no such right; metaphorically, as in
> sever discipline in list operations, generally yes, though perhaps
> limited from some grounds based on applicable Laws.

Then, I respect their right of doing this if it's a 'private property'.

I switched from comp.lang.python to mailing list a few months ago for those 
spam threads there. Now it seems a bad decision because 1) replied mail can be 
lost  or duplicated or even banned. 2) look at each separately mail is not as 
comfortable as at a single thread. 3) Google group is a more free land to live.

So, have to switch back to comp.lang.python to get ride of all these problems.

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


Re: Observations on the List - "Be More Kind"

2018-10-09 Thread jfong
Chris Angelico at 2018.10.10 UTC+8 AM 10:31:33 wrote:
> On Wed, Oct 10, 2018 at 1:21 PM  wrote:
> > I switched from comp.lang.python to mailing list a few months ago for those 
> > spam threads there. Now it seems a bad decision because 1) replied mail can 
> > be lost  or duplicated or even banned. 2) look at each separately mail is 
> > not as comfortable as at a single thread. 3) Google group is a more free 
> > land to live.
> >
> > So, have to switch back to comp.lang.python to get ride of all these 
> > problems.
> >
> 
> Well, just be aware that a lot of people block ALL posts that come
> from Google Groups. The signal-to-noise ratio there is sufficiently
> low that it's often just not worth carrying that traffic. So you're
> welcome to switch over to there to get freedom, but you're basically
> getting the Wild West, where spammers run free and the lawless rule...
> and the genteel avoid the place.
> 
> ChrisA

Wild West? haha.. nice metaphor, thanks for reminding. But, in cyberspace, I 
prefer more freedom than more safety:-)

--Jach

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


How to run/debug a script file its name has characters such as space, (, etc.

2018-10-12 Thread jfong
I saw a directory where all its filenames are something like this:
...
1a PSG (Entry and PopUp).py
1b PSG (Format).py
1c PSG (persistent form and bind key).py
...

Just wondering how these file can run and debugged under Windows?

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


Re: How to run/debug a script file its name has characters such as space, (, etc.

2018-10-12 Thread jfong
Chris Angelico於 2018年10月12日星期五 UTC+8下午4時39分37秒寫道:
> On Fri, Oct 12, 2018 at 6:26 PM  wrote:
> >
> > I saw a directory where all its filenames are something like this:
> > ...
> > 1a PSG (Entry and PopUp).py
> > 1b PSG (Format).py
> > 1c PSG (persistent form and bind key).py
> > ...
> >
> > Just wondering how these file can run and debugged under Windows?
> >
> 
> Put the file name inside double quotes. You can probably do this by
> tab-completing the name - type 1c and then hit the tab key - your
> shell should fill out the rest of the name with whatever quoting is
> necessary.
> 
> ChrisA

After using Windows so many years, I don't know this trick the double quotes 
and tab can do in the shell. It really embarrass me:-(  Thanks you, Chris.

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


Is it dangeous when using custom metaclass?

2018-10-15 Thread jfong
class StructureMeta(type):
def __init__(self, clsname, bases, clsdict):
offset = 0
...
...
setattr(self, 'struct_size', offset)

class Structure(metaclass=StructureMeta):
...
...

class PolyHeader(Structure):
...
...

As my understanding, the metaclass's __init__ was called when a class was 
created. In the above example, both the Structure and PolyHeader called it. My 
question is: because the PolyHeader inherited Structure, is it reasonable for 
PolyHeader to call this __init__ again? Will it cause any possible trouble?

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


Re: Is it dangeous when using custom metaclass?

2018-10-16 Thread jfong
Gregory Ewing at 2018/10/16 UTC+8 PM 2:01:01 wrote
> jf...@ms4.hinet.net wrote:
> > class Structure(metaclass=StructureMeta): ...
> > 
> > class PolyHeader(Structure): ...
> > 
> > As my understanding, the metaclass's __init__ was called when a class was
> > created. In the above example, both the Structure and PolyHeader called it.
> > My question is: because the PolyHeader inherited Structure, is it reasonable
> > for PolyHeader to call this __init__ again? Will it cause any possible
> > trouble?
> 
> It's reasonable for both to call it, because they're distinct
> instances of StructureMeta, each of which need to be initialised.

The PolyHeader is already initialized by inheritance. Is there any way to 
bypass this __init__?

> Whether it will cause a problem depends on what StructureMeta's
> __init__ is supposed to do. Presumably you want a given structure
> class to start allocating its offsets where its base class left
> off, in which case you may need to do something like this:
> 
> class StructureMeta(type):
>  def __init__(self, clsname, bases, clsdict):
>  if bases:
> offset = bases[0].offset # assuming there isn't more than one base
>  else:
> offset = 0
>  ...
> 
> (BTW, why do you use setattr() to set the offset attribute
> instead of just doing self.offset = offset?)

No particular reason, just follows the same code pattern ahead of it where the 
attribute names are from a list:-)

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


Re: Is it dangeous when using custom metaclass?

2018-10-17 Thread jfong
dieter at 2018/10/17 UTC+8 PM 1:15:01 wrote:
> jf...@ms4.hinet.net writes:
> > Gregory Ewing at 2018/10/16 UTC+8 PM 2:01:01 wrote
> >> jf...@ms4.hinet.net wrote:
> >> > class Structure(metaclass=StructureMeta): ...
> >> > 
> >> > class PolyHeader(Structure): ...
> >> > 
> >> > As my understanding, the metaclass's __init__ was called when a class was
> >> > created. In the above example, both the Structure and PolyHeader called 
> >> > it.
> >> > My question is: because the PolyHeader inherited Structure, is it 
> >> > reasonable
> >> > for PolyHeader to call this __init__ again? Will it cause any possible
> >> > trouble?
> >> 
> >> It's reasonable for both to call it, because they're distinct
> >> instances of StructureMeta, each of which need to be initialised.
> >
> > The PolyHeader is already initialized by inheritance. Is there any way to 
> > bypass this __init__?
> 
> If there were any, you should find it described in metaclass related 
> documentation.
> 
> Likely, you can ensure that followup calls of "__init__" effectively
> behave as "no-op"s: let the first call place a marker in the initialized
> object and check in later calls whether it is already there.

Hard to find the document of type.__init__. I can only guess it does nothing, 
at least no thing serious, to avoid trouble the metaclass's __init__ may cause 
in a class hierarchy:-)
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: how to create a dictionary from csv file?

2016-04-26 Thread jfong
Just curious:-) why everyone here open the csv file without using newline='' as 
suggested in Python 3.4.4 document section 14.1?
-- 
https://mail.python.org/mailman/listinfo/python-list


Dictionary is really not easy to handle

2016-04-28 Thread jfong
I have a dictionary like this:

>>> dct ={1: 'D', 5: 'A', 2: 'B', 3: 'B', 4: 'E'}

The following code works:

>>> for k in dct: print(k, dct[k])
...
1 D
2 B
3 B
4 E
5 A

and this one too:

>>> for k,v in dct.items(): print(k,v)
...
1 D
2 B
3 B
4 E
5 A

But...this one?

>>> for k,v in dct: print(k,v)
...
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'int' object is not iterable

No idea what the error message means:-( Can anyone explain it? Thanks ahead.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Dictionary is really not easy to handle

2016-04-28 Thread jfong
I was overwhelmed that three gurus inspire me in three different ways in their 
own flavour:-) That's really appreciated! Now I understand why it's so, thanks 
to all of you.

To Peter:
> With that information, can you predict what

> for k, v in {(1, 2): "three"}: print(k, v)

> will print? 

It's 1 2.

(Although Rustom had given the answer in his reply, I didn't figure out until 
after reading you and Steven's answers:-)
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: You gotta love a 2-line python solution

2016-05-02 Thread jfong
DFS at 2016/5/2 UTC+8 11:39:33AM wrote:
> To save a webpage to a file:
> -
> 1. import urllib
> 2. urllib.urlretrieve("http://econpy.pythonanywhere.com
>  /ex/001.html","D:\file.html")
> -
> 
> That's it!

Why my system can't do it?

Python 3.4.4 (v3.4.4:737efcadf5a6, Dec 20 2015, 19:28:18) [MSC v.1600 32 bit (In
tel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from urllib import urlretrieve
Traceback (most recent call last):
  File "", line 1, in 
ImportError: cannot import name 'urlretrieve'

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


Re: You gotta love a 2-line python solution

2016-05-02 Thread jfong
DFS at 2016/5/3 9:12:24AM wrote:
> try
> 
> from urllib.request import urlretrieve
> 
> http://stackoverflow.com/questions/21171718/urllib-urlretrieve-file-python-3-3
> 
> 
> I'm running python 2.7.11 (32-bit)

Alright, it works...someway.

I try to get a zip file. It works, the file can be unzipped correctly.

>>> from urllib.request import urlretrieve
>>> urlretrieve("http://www.caprilion.com.tw/fed.zip";, "d:\\temp\\temp.zip")
('d:\\temp\\temp.zip', )
>>>

But when I try to get this forum page, it does get a html file but can't be 
viewed normally.

>>> urlretrieve("https://groups.google.com/forum/#!topic/comp.lang.python/jFl3GJ
bmR7A", "d:\\temp\\temp.html")
('d:\\temp\\temp.html', )
>>>

I suppose the html is a much complex situation where more processes need to be 
done before it can be opened by a web browser:-)

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


Re: You gotta love a 2-line python solution

2016-05-02 Thread jfong
Stephen Hansen at 2016/5/3 11:49:22AM wrote:
> On Mon, May 2, 2016, at 08:27 PM, jf...@ms4.hinet.net wrote:
> > But when I try to get this forum page, it does get a html file but can't
> > be viewed normally.
> 
> What does that mean?
> 
> -- 
> Stephen Hansen
>   m e @ i x o k a i . i o

The page we are looking at:-)
https://groups.google.com/forum/#!topic/comp.lang.python/jFl3GJbmR7A

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


How to memory dump an object?

2016-05-20 Thread jfong
Is there any tools which can do the memory dump of an object so I can view 
their content or implementation? For example,

>>> s1 = '\x80abc'
>>> b1 = b'\x80abc'

What are exactly stored in memory for each of them? Is their content really the 
same? This kind of tool should be helpful "for me" to learn the inner detail of 
Python. 


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


Re: How to memory dump an object?

2016-05-20 Thread jfong
Sorry, forget to mention that I am working on version 3.4

Following the steps given in Chris's reply, I get the result from bytes string:

>>> b1 = b'\x80abc'
>>> ctypes.cast(id(b1), ctypes.c_voidp)
c_void_p(35495992)
>>> sys.getsizeof(b1)
21
>>> b1ptr = ctypes.cast(id(b1), ctypes.POINTER(ctypes.c_uint8))
>>> bytes([b1ptr[i] for i in range(21)])
b'\x01\x00\x00\x00X\xa1e^\x04\x00\x00\x00\x04\xff\x04&\x80abc\x00'
>>>

It obviously has the same "content" as the s1 string has and the object's 
structure are much different as expected (77 vs 21 bytes:-)

If I do this as Ned suggested:

>>> b2 = b1

I get:

>>> bytes([b1ptr[i] for i in range(21)])
b'\x02\x00\x00\x00X\xa1e^\x04\x00\x00\x00\x04\xff\x04&\x80abc\x00'
>>>

So, at least, we know where the reference count was stored:-)

It's amazing the "tool" is so simple. Actually I feel a little embarrassed that 
I do know every statements in it but just no idea of combining them together. 
Thanks a lot, Chris.

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


Re: How to memory dump an object?

2016-05-21 Thread jfong
Make a quick experiment under version 3.4.4 through this simple "tool" Chris 
had provided, now I know how the unicode string was stored in memory:-)

>>> s1 = '\x80abc'
>>> s1
'\x80abc'
>>> len(s1)
4
>>> sys.getsizeof(s1)
41
>>> s1ptr = ctypes.cast(id(s1), ctypes.POINTER(ctypes.c_uint8))
>>> bytes([s1ptr[i] for i in range(41)])
b'\x01\x00\x00\x00\xe8\xa5g^\x04\x00\x00\x00\x04\xff\x04&\xa4\x00\x00d\x00\x00\x
00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80abc\x00'
>>>
# a simple unicode string, each code point can be stored in one byte

>>> s2 = '\u0080abc'
>>> s2
'\x80abc'
>>> len(s2)
4
>>> sys.getsizeof(s2)
41
>>> s2ptr = ctypes.cast(id(s2), ctypes.POINTER(ctypes.c_uint8))
>>> bytes([s2ptr[i] for i in range(41)])
b'\x01\x00\x00\x00\xe8\xa5g^\x04\x00\x00\x00\x04\xff\x04&\xa4\x00\x00|\x00\x00\x
00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80abc\x00'
>>>
# Python change it automatically to store each code point into one byte

>>> s3 = '\u07b4abc'
>>> s3
'\u07b4abc'
>>> len(s3)
4
>>> sys.getsizeof(s3)
46
>>> s3ptr = ctypes.cast(id(s3), ctypes.POINTER(ctypes.c_uint8))
>>> bytes([s3ptr[i] for i in range(46)])
b'\x01\x00\x00\x00\xe8\xa5g^\x04\x00\x00\x00\x19n\x93]\xa8\x00\x00dd\r\x1d\x02\x
00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\xb4\x07a\x00b\x00c\x00\x00\x00'
>>>
# use two bytes to store each code point, even the end-of-string mark

>>> s4 = '\U00025049abc'
>>> s4
'\U00025049abc'
>>> len(s4)
4
>>> sys.getsizeof(s4)
56
>>> s4ptr = ctypes.cast(id(s4), ctypes.POINTER(ctypes.c_uint8))
>>> bytes([s4ptr[i] for i in range(56)])
b'\x01\x00\x00\x00\xe8\xa5g^\x04\x00\x00\x003\xdd\xa7"\xb0\x00\x00\x00\x00\x00\x
00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00IP\x02\x00a\x00\x00\x00b\x
00\x00\x00c\x00\x00\x00\x00\x00\x00\x00'
>>>
# use four bytes to store each code point

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


Re: Guys, can you please share me some sites where we can practice python programs for beginners and Intermediate.

2016-06-21 Thread jfong
Pushpanth Gundepalli at 2016/6/21 7:03:28PM wrote:
> Guys, can you please share me some sites where we can practice python 
> programs for beginners and Intermediate.

Is this you want? http://pythontutor.com/

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


"for/while ... break(by any means) ... else" make sense?

2016-06-28 Thread jfong
Anyone who wrote the code below must be insane:-)

for x in range(3):
print(x)
else:
print('I am done')

But here it seems perfectly OK:

for x in range(3):
print(x)
if x == 1:  break
else:
print('I am done')

To me, the "else" was bonded with "break" (or return, or raise, or...),
not "for". It make sense:-)

--Jach

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


Re: "for/while ... break(by any means) ... else" make sense?

2016-06-29 Thread jfong
Steven D'Aprano at 2016/6/29 UTC+8 10:43:52AM wrote:
> The "else" in for...else has nothing to do with any "if" inside the for
> block.

Yes, the "else" has nothing to do with "break" syntactically in Python 
language, but semantically in English it cause confusion. When I said "insane", 
I just want to emphasis this situation. 

"else" should appear only when there is a "break" in the "for" block, then "for 
...break... else ..." become perfectly alright semantically. Never think of it 
in "for ...else ..." or the confusion bond to come up:-)

--Jach


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


Re: Iteration, while loop, and for loop

2016-06-30 Thread jfong
Steven D'Aprano at 2016/6/30 7:59:40AM wrote:
> py> mi = list('bananas')
> py> for char in mi:
> ... if char == 'a':
> ... mi.extend(' yum')
> ... print(char, end='')
> ... else:  # oh no, the feared for...else!
> ... # needed to prevent the prompt overwriting the output
> ... print()
> ...
> bananas yum yum yum
> py> 
> 
> 
> This example shows two things:
... 
> (2) Anyone who says that for...else without break is useless is wrong.

Haha...you win.

By the way, I never said "else" without "break" is illegal or useless, I said 
it will cause confusion semantically, just like this(it reminds me the IOCCC:-):

import math
pass
import os
pass
import sys 

Think of the "try ...except ...else ..." where the situation is similar but 
luckily it was mandatory.

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


Why Python don't accept 03 as a number?

2018-12-07 Thread jfong
>>> 00
0
>>> 03
  File "", line 1
03
 ^
SyntaxError: invalid token
>>>

Any particular reason?
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Why Python don't accept 03 as a number?

2018-12-07 Thread jfong
MRAB at 2018/12/8 UTC+8 AM10:04:51 wrote:
> Before Python 3, a leading 0 in an integer literal would indicate an 
> octal (base 8) number.

So, the reason is historical.

> The old form is now invalid in order to reduce the chance of bugs.

I encounter this problem on trying to do something like this:
eval('03 + 00 + 15')
It takes me some efforts to get rid of those leading zeros:-(

Hope someday 03 can be accepted as a valid decimal number in Python 3.

Thank you for explaining.

--Jach


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


Re: Why Python don't accept 03 as a number?

2018-12-07 Thread jfong
Ian at 2018/12/8 UTC+8 AM11:28:34 wrote:
> What is it exactly that you're trying to accomplish with this? Perhaps
> there's a better way than using eval.

This problem comes from solving a word puzzle,
ab + aa + cd == ce
Each character will be translate to a digit and evaluate the correctness,
03 + 00 + 15 == 18

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


Re: Why Python don't accept 03 as a number?

2018-12-07 Thread jfong
I can understand the difficulty of throwing old thing away and accept new one 
in human. There seems have a huge inertia there. This phenomenon appears on 
every aspects, not only on the transition from Python2 to Python3. But, as a 
new comer of Python like me, I have no difficulty to accept it because of 03 is 
a valid number in my daily life and never had the experience of treating 010 as 
8:-)

MBAB wrote:
> We could just wait until all the old C programmers have died. :-)

Yes, it's the nature way.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Why Python don't accept 03 as a number?

2018-12-08 Thread jfong
Avi Gross at 2018/12/8 UTC+8 PM2:09:20 wrote:
> [[READERS DIGEST CONDENSED ANSWER: use int("string") ]]
> 
> Since we all agree python will not make notations like "05" work
> indefinitely, and the need expressed is how to solve a symbolic puzzle (see
> message below) then it makes sense to look at alternate representations.
> 
> I have a question first. How are you solving your puzzles? 
> 
> ab + aa + cd == ce

Try all the combinations:-)

The only way I can think of is try-error. It takes no more 10 lines to go from 
"ab + aa + cd == ce" to yield one correct answer, such as "03 + 00 + 15 == 18", 
using itertools' permutations(), string's translate() and re.

> Why does 05 ever even appear in your solution?

I don't know. There is total 192 answers for this puzzle anyway.

> Are you generating all possible answers by setting each variable to one of 0
> to 9 then the second to any of the remaining nine choices then the third to
> the remaining 8 and so on? For any method like that, you can presumably make
> each component like
> 
> ab = 10*a + b
> 
> in the loop.
> 
> Similarly for aa and cd and ce. If the equality above is true, you found the
> solution and break out. If there can be multiple solutions, note the
> solution and keep going. But note for the 5 variables above, you are testing
> 10*9*8*7*6 combinations.
> 
> Another idea is to use strings like "05" as bizarrely, the function int()
> seems to be an ex eption that does NOT care about leading whitespace or
> zeroes:
> 
> >>> int("05")
> 5
> >>> int("  0005")
> 5
> 
> And even handles all zeroes:
> 
> >>> int("00")
> 0
> 
> You can also use lstrip() with an argument to remove zeros:
> 
> >>> a = eval("05".lstrip("0"))
>
> >>> a
>
> 5
> 
> If you are in a situation where you only want to remove leading zeroes if
> the following character is a digit and not "o" or "b" or "x", use regular
> expressions or other techniques.

As far as the leading zero problem was concerned, the simplest way is using 
re.sub()

> I will just toss in the possible use of the SymPy module to do actual
> symbolic computations to solve some of these. Perhaps a tad advanced.

I don't know SymPy and if it can shorten the execution time. But I am very 
curious about if there is other algorithm which can apply to this problem:-)

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


Re: Why Python don't accept 03 as a number?

2018-12-08 Thread jfong
Grant Edwards於 2018年12月9日星期日 UTC+8上午12時52分04秒寫道:
> On 2018-12-08, Cameron Simpson  wrote:
> > On 07Dec2018 20:24, Jach Fong  wrote:
> >>Ian at 2018/12/8 UTC+8 AM11:28:34 wrote:
> >>> What is it exactly that you're trying to accomplish with this? Perhaps
> >>> there's a better way than using eval.
> >>
> >>This problem comes from solving a word puzzle,
> >>ab + aa + cd == ce
> >>Each character will be translate to a digit and evaluate the correctness,
> >>03 + 00 + 15 == 18
> >
> > Then you should be evaluating the digits and assembling values from 
> > them. Not trying to shoehorn a string through something that _might_ 
> > accept this string and do what you want. In Python 2 it will accept your 
> > string and not do what you want; at least in Python 3 it doesn't accept 
> > your string.
> 
> Just to be clear: you do _not_ want to use eval on the string.
> 
> If you're not the one who created the string, it might wipe your hard
> drive or empty your bank account.  If you _are_ the one who created
> the string, then generate the desired result instead.
> 
> -- 
> Grant

I didn't evaluate the input string directly. It's the translated "digit" string 
been evaluated, so shouldn't have any danger on using eval().

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


Re: Why Python don't accept 03 as a number?

2018-12-08 Thread jfong
Avi Gross於 2018年12月9日星期日 UTC+8上午1時40分26秒寫道:
> Jach,
> 
> Just for fun, I looked at the  puzzle you asked about and solved it several
> ways without running into your 03 problem at all. There are more efficient
> solutions than total brute force.
> 
> Anyone not interested, stop here, please. After my explanations, I show a
> python program then the output it produces.
> 
> The comments in the python program (below) explain the solution classes but
> let me suggest a little algebra simplifies the problem so fewer brute force
> iterations are needed.
> 
> The simplistic algorithm can be written as a single list comprehension with
> (in this case) 5 "for" clauses and one "if" clause.
> 
> You are solving for: ab + aa + cd == ce
> 
> So 
> for all digits possible for a
> for all remaining digits possible for b each iteration
> for all remaining digits possible for c each iteration
> for all remaining digits possible for d each iteration
> for all remaining digits possible for e each iteration
> if the condition applies.
> 
> Clearly the above is deeply nested with 10!/5! Iterations or 30,240.
> 
> But a little algebra simplifies the solution so c drops out of the equation
> as shown below in the comments.
> The test becomes:  21*a + b + d - e == 0
> 
> You can apply that as the condition using four loops. You get 32 solutions
> and for each you can let c be any of 10 possibilities for 320 total
> solutions, if I did it right. The number of iterations is now only 5,040 and
> you are evaluating fewer terms with c gone. The full test would have been
> (10*a +b )+ (10*a + a) + (10*c + d) == (10*c + e)
> 
> BUT a tad more analysis shows that all solutions require "a" to be zero. If
> a >=1 then 21*a must be >= 21.
> But b and c cannot be more than 9+8 which is 17 and subtracting e makes it
> no larger. So "a" MUST be zero.
> 
> So the solution can be done with only three loops for b, d, and e. 720
> iterations.
> 
> The commented code is below. It can be done in as little as two lines of
> code if the list comprehension is done in one line but why make it hard to
> read.
> 
> If there is a flaw in my reasoning or the program below, please point it
> out. You said there were 192 solutions. I found 320.
> And, there are more efficient solutions possible but overkill for this
> application.
> 
> Avi
> 
> ### START CODE ##
> # GOAL: find all solutions of a puzzle
> # ab + aa + cd == ce
> # Where each of the letters a through e
> # are UNIQUE values ranging from 0 to 9
> 
> # Make the equation simpler
> # expand ab to 10*a + b
> # expand aa to 10*a + a
> # expand cd to 10*c + d
> # add to get 21*a + b + 10*c + d
> # expand ce to 10*c + e
> # simplify 21*a + b + 10*c + d = 10*c + e
> # the 10*c on both sides cancel.
> # RESULT: 21*a + b + d - e = 0
> # the value of c is not relevant and
> # you can solve without e and then add back
> # all ten possibilities later.
> 
> # Method:
> # Use a set of digits.
> # Use a list comprehension with four loops.
> # Each loop chooses all available values
> # for a,b,d,e by subtracting the set
> # of digits already in use at the time from all digits.
> 
> digits = set(range(10))
> 
> matches = [ (a, b, d, e)
> for a in digits
> for b in (digits - {a})
> for d in (digits -{a,b})
> for e in (digits -{a,b,d})
> if ( 21*a + b + d - e == 0)
> ]
> 
> print("SOLVING FOR: 21*a + b + d - e == 0")
> print(f"matches found in batches of 10: {len(matches)}")
> 
> for (a,b,d,e) in matches:
> solution =  {'a' : a,
> 'b' : b,
> 'c' : 'any digit',
> 'd' : d,
> 'e' : e
>  }
> print(solution)
> 
> # Note the result shows all solutions have 'a' being zero.
> # That was obvious from the equation as there were 21 of them
> # and if a was 1 in 21*a + b + d - e = 0
> # then clearly band d cannot be more than 9+8 so no solution
> # unless a == 0.
> # So you can solve this easier using the above techique by just
> # solving b + d - e = 0
> 
> matches = [ (b, d, e)
> for b in digits
> for d in (digits -{b})
> for e in (digits -{b,d})
> if ( b + d == e)
> ]
> 
> print("\nSOLVING FOR: b + d == e")
> print(f"matches found in batches of 10: {len(matches)}")
> 
> for (b,d,e) in matches:
> solution =  {'a' : '0',
> 'b' : b,
> 'c' : 'any digit',
> 'd' : d,
> 'e' : e
>  }
> print(solution)
> 
> ### END CODE ##
> ### BEGIN OUTPUT ##
> SOLVING FOR: 21*a + b + d - e == 0
> matches found in batches of 10: 32
> {'a': 0, 'b': 1, 'c': 'any digit', 'd': 2, 'e': 3}
> {'a': 0, 'b': 1, 'c': 'any digit', 'd': 3, 'e': 4}
> {'a': 0, 'b': 1, 'c': 'any digit', 'd': 4, 'e': 5}
> {'a': 0, 'b': 1, 'c': 'any digit', 'd': 5,

Re: Why Python don't accept 03 as a number?

2018-12-10 Thread jfong
Chris Angelico於 2018年12月10日星期一 UTC+8下午6時17分14秒寫道:
> On Mon, Dec 10, 2018 at 9:11 PM Antoon Pardon  wrote:
> >
> > On 10/12/18 11:03, Chris Angelico wrote:
> > > Considering that, in a problem of that description, neither S nor M
> > > may represent zero, I don't think there's a problem here.
> >
> > Not all such problems have that condition.
> 
> They should. Every published set of problems that I've ever solved by
> hand has. I went searching online for some, and found this page:
> 
> http://puzzlepicnic.com/genre?alphametic
> 
> which clearly states that exact restriction. The implication is that
> you're solving a puzzle in arithmetic (usually addition or long
> multiplication), and it is *exactly* as you would have written it with
> digits, save that the digits have been replaced with letters (and
> carries have been omitted, since that'd make it too easy). You
> wouldn't write a leading zero on a number in standard grade-school
> arithmetic, so you also won't use a leading zero in anything here.
> 
> ChrisA

All I know is that when I write a number 03, there is no any human being will 
say it's an illegal number.

I prefer to buy the reason that this restriction was bring in is because of the 
puzzle's author know it will cause trouble without this, not because of our 
written habit.

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


Re: Why Python don't accept 03 as a number?

2018-12-10 Thread jfong
Chris Angelico於 2018年12月10日星期一 UTC+8下午7時09分01秒寫道:
> On Mon, Dec 10, 2018 at 9:46 PM  wrote:
> >
> > Chris Angelico於 2018年12月10日星期一 UTC+8下午6時17分14秒寫道:
> > > On Mon, Dec 10, 2018 at 9:11 PM Antoon Pardon  
> > > wrote:
> > > >
> > > > On 10/12/18 11:03, Chris Angelico wrote:
> > > > > Considering that, in a problem of that description, neither S nor M
> > > > > may represent zero, I don't think there's a problem here.
> > > >
> > > > Not all such problems have that condition.
> > >
> > > They should. Every published set of problems that I've ever solved by
> > > hand has. I went searching online for some, and found this page:
> > >
> > > http://puzzlepicnic.com/genre?alphametic
> > >
> > > which clearly states that exact restriction. The implication is that
> > > you're solving a puzzle in arithmetic (usually addition or long
> > > multiplication), and it is *exactly* as you would have written it with
> > > digits, save that the digits have been replaced with letters (and
> > > carries have been omitted, since that'd make it too easy). You
> > > wouldn't write a leading zero on a number in standard grade-school
> > > arithmetic, so you also won't use a leading zero in anything here.
> > >
> > > ChrisA
> >
> > All I know is that when I write a number 03, there is no any human being 
> > will say it's an illegal number.
> >
> 
> Yet most human beings will agree that you don't write out an
> arithmetic problem as:
> 
>0 1 9 8
>  +   7 1 3
>  =

Python3 gives me the error message is because of the number 0198, not because 
of 0198 + 713.

> > I prefer to buy the reason that this restriction was bring in is because of 
> > the puzzle's author know it will cause trouble without this, not because of 
> > our written habit.
> >
> 
> No, it's a restriction because it is unsatisfactory without it. The
> point of a puzzle is to be fun, and fun means having restrictions that
> fit what people expect.

The fun is from solving the puzzle, not from its restriction, unless the puzzle 
has no fun without this restriction.

--Jach

> ChrisA

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


Re: 03 digression by brute force

2018-12-13 Thread jfong
Just for fun:-) On my ooold PC, it takes 0.047 seconds to run the following 
algorithm on the problem 'SNED + MORE == MONEY".

-
import time
import itertools

#S, E, N, D, M, O, R, Y
n = 0
digits = {x for x in range(10)}

def tenThousand(u, Cin):  # Cin == M
global n
if Cin == M:
print(S, E, N, D, '+', M, O, R, E, '==', M, O, N, E, Y)
n += 1

def thousand(u, Cin):  # Cin + S + M == 10 * Cout + O
global S, M, n
rest = digits - set(u)
for g in itertools.permutations(rest, 2):
for Cout in range(2):
if Cin + g[0] + g[1] == 10 * Cout + O:
S = g[0];  M = g[1]
tenThousand(u + g, Cout)

def hundred(u, Cin):  # Cin + E + O == 10 * Cout + N
global O, n
rest = digits - set(u)
for g in itertools.permutations(rest, 1):
for Cout in range(2):
if Cin + E + g[0] == 10 * Cout + N:
O = g[0]
thousand(u + g, Cout)

def ten(u, Cin):  # Cin + N + R == 10 * Cout + E
global N, R, n
rest = digits - set(u)
for g in itertools.permutations(rest, 2):
for Cout in range(2):
if Cin + g[0] + g[1] == 10 * Cout + E:
N = g[0];  R = g[1]
hundred(u + g, Cout)

def unit():  # D + E == 10 * Cout + Y
global D, E, Y, n
n = 0
for g in itertools.permutations(range(10), 3):  # g is a tuple
for Cout in range(2):  # add two items so Cout is 0 or 1
if g[0] + g[1] == 10 * Cout + g[2]:
D = g[0];  E = g[1];  Y = g[2]
ten(g, Cout)
print(n)

if __name__ == '__main__':
start = time.time()
unit()
print(time.time() - start)
-

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


Re: Smarter algo, was Re: 03 digression by brute force

2018-12-15 Thread jfong
Appreciate your thoughtfully analysis on this code. Before generalize it with 
arbitrary additions, as Peter suggested:-), a recursive version is needed. I 
may give it a try on this Sunday.


Avi Gross at 2018/12/15 UTC+8 AM8:13:37 wrote:
> REAL SUBJECT: Analysis of alternate algorithms.
> 
> Peter & Jach and anyone interested,
> 
> As Peter said in his altered subject line, Jack changed directions from 
> tweaking an algorithm to trying something quite different.
> 
> Reminder of the problem. 
> 
> Horizontal View:
> SEND + MORE = MONEY
> 
> Vertical View:
>   SEND
> +MORE
> ...
> MONEY
> 
> Hard to be precise as I am sticking to plain text in my message. The three 
> words above are meant to be right adjusted.
> 
> When solving it horizontally, Jach and I used variants of a brute force 
> approach. Substitute all possible combinations. He did it in-line and used 
> eval. I did it by making lists of items on both sides and summing the int() 
> of each component and comparing. We tried both our algorithms and his was 
> slower and he profiled that the cause was that eval() was much more expensive 
> as were his use of regular expression functions. For comparison, mine used 
> int() and string manipulation functions and sets and dictionaries.
> 
> But the real puzzle is meant to be solved in a more vertical way by humans 
> using logic. I won't do that here but note we have 4 equations going down but 
> 8 unknowns. And the equations are not unique.
> 
> The rightmost column (I will call it the first as our arithmetic proceeds 
> from right to left) is meant to represent ONES and provides the equation:
> 
> (D+E== Y) or (D+E == Y + 10)
> 
> Worse, for the next column, you either get a "1" carried from the previous 
> addition or not and either pass a "1" along to the next column or not. 4 
> Possibilities.
> 
> (N+R==E) or (N+R+1==E) or (N+R==E+10) or (N+R+1==E+10)
> 
> Getting a headache yet?
> 
> For a human, they need a way to come up with additional info in terms of 
> constraints.
> 
> There is a guiding inequality that looks like this:
> 
> S is not the same as any of the others. Anytime you solve for another, the 
> list of possible values for S shrinks.
> Ditto for each other variable.
> Or, since anything plus 0 is itself, then D and E adding up to Y (with no 
> possible carry) cannot be 0.
> 
> But getting a computer to do this might be a bit harder than blunt-force 
> searches. So let's see why Jach's new algorithm was faster.
> 
> The code I am analyzing can be viewed in the archives and will not be entered 
> again:
> 
> https://mail.python.org/pipermail/python-list/2018-December/738454.html
> 
> So what did Jach try in his newer version? It is what I call a vertical 
> approach but one a computer can do easier than a human can or would. I see it 
> is a very specific algorithm that hard codes in these variables as global 
> entities that are altered by a set of nested functions. S, E, N, D, M, O, R, 
> Y. There are approaches that might be better such as passing a dictionary 
> partially filled out from one function to the next as the only one that 
> prints the solution is the final function call.
> 
> So his is not a general solution.
> 
> What interests me as a probable reason this is faster is the number of 
> situations it tries. The earlier versions asked itertools.permutations() to 
> provide all unique combinations of ten tokens in eight positions. So there 
> were 10 choices for the first and 9 for the second and so on adding up to 
> 10!/2! or 1,814,400  different combinations tried. That approaches 2 million.
> 
> Jack broke the problem down into evaluating the units column with a loop like 
> this:
> 
> itertools.permutations(range(10), 3)
> 
> That is 720 possibilities. He then doubled that to 1,440 to consider a carry. 
> Only if the selected values for the three variables in contention (plus a 
> carry) does he go on to call to evaluate the tens column.
> 
> It then shrinks a bit more as he no longer gets the permutations of all 10 
> digits. He subtracts the three values that might work for the units, so he is 
> asking for permutations of 7 digits, two at a time. That is 42, doubled again 
> to 84 for carry purposes. And this function is not called 1,440 times, but 
> quite a bit fewer. 
> 
> So, similarly, of those 84 loops for tens, he only sometimes calls to 
> evaluate hundreds. As mentioned, the set of 10 digits shrinks some more and 
> this continues upward to functions that evaluate hundreds and thousands  and 
> finally the one evaluating ten thousands pretty much prints out an answer it 
> finds. 
> 
> So overall iterations can be shown to drop. We could add code to measure how 
> many times each function is called and come up with an exact value for this 
> built-in problem. I did and the functions were called this many times:
> 
> >>> counting
> {'unit': 1, 'ten': 72, 'hundred': 290, 'thou': 183, '10thou': 196}
> >>> sum(counting.values())
> 742
> 
> But I a

Re: Smarter algo, was Re: 03 digression by brute force

2018-12-16 Thread jfong
BlindAnagram at 2018/12/15 UTC+8 PM 8:41:21 wrote:
> On 15/12/2018 09:56, jf...@ms4.hinet.net wrote:
> > Appreciate your thoughtfully analysis on this code. Before generalize it 
> > with arbitrary additions, as Peter suggested:-), a recursive version is 
> > needed. I may give it a try on this Sunday.
> > 
> > 
> > Avi Gross at 2018/12/15 UTC+8 AM8:13:37 wrote:
> >> REAL SUBJECT: Analysis of alternate algorithms.
> >>
> >> Peter & Jach and anyone interested,
> >>
> >> As Peter said in his altered subject line, Jack changed directions from 
> >> tweaking an algorithm to trying something quite different.
> >>
> >> Reminder of the problem. 
> >>
> >> Horizontal View:
> >> SEND + MORE = MONEY
> >>
> >> Vertical View:
> >>   SEND
> >> +MORE
> >> ...
> >> MONEY
> >>
> >> Hard to be precise as I am sticking to plain text in my message. The three 
> >> words above are meant to be right adjusted.
> >>
> >> When solving it horizontally, Jach and I used variants of a brute force 
> >> approach. Substitute all possible combinations. He did it in-line and used 
> >> eval. I did it by making lists of items on both sides and summing the 
> >> int() of each component and comparing. We tried both our algorithms and 
> >> his was slower and he profiled that the cause was that eval() was much 
> >> more expensive as were his use of regular expression functions. For 
> >> comparison, mine used int() and string manipulation functions and sets and 
> >> dictionaries.
> >>
> >> But the real puzzle is meant to be solved in a more vertical way by humans 
> >> using logic. I won't do that here but note we have 4 equations going down 
> >> but 8 unknowns. And the equations are not unique.
> >>
> >> The rightmost column (I will call it the first as our arithmetic proceeds 
> >> from right to left) is meant to represent ONES and provides the equation:
> >>
> >> (D+E== Y) or (D+E == Y + 10)
> >>
> >> Worse, for the next column, you either get a "1" carried from the previous 
> >> addition or not and either pass a "1" along to the next column or not. 4 
> >> Possibilities.
> >>
> >> (N+R==E) or (N+R+1==E) or (N+R==E+10) or (N+R+1==E+10)
> >>
> >> Getting a headache yet?
> >>
> >> For a human, they need a way to come up with additional info in terms of 
> >> constraints.
> >>
> >> There is a guiding inequality that looks like this:
> >>
> >> S is not the same as any of the others. Anytime you solve for another, the 
> >> list of possible values for S shrinks.
> >> Ditto for each other variable.
> >> Or, since anything plus 0 is itself, then D and E adding up to Y (with no 
> >> possible carry) cannot be 0.
> >>
> >> But getting a computer to do this might be a bit harder than blunt-force 
> >> searches. So let's see why Jach's new algorithm was faster.
> >>
> >> The code I am analyzing can be viewed in the archives and will not be 
> >> entered again:
> >>
> >> https://mail.python.org/pipermail/python-list/2018-December/738454.html
> >>
> >> So what did Jach try in his newer version? It is what I call a vertical 
> >> approach but one a computer can do easier than a human can or would. I see 
> >> it is a very specific algorithm that hard codes in these variables as 
> >> global entities that are altered by a set of nested functions. S, E, N, D, 
> >> M, O, R, Y. There are approaches that might be better such as passing a 
> >> dictionary partially filled out from one function to the next as the only 
> >> one that prints the solution is the final function call.
> >>
> >> So his is not a general solution.
> >>
> >> What interests me as a probable reason this is faster is the number of 
> >> situations it tries. The earlier versions asked itertools.permutations() 
> >> to provide all unique combinations of ten tokens in eight positions. So 
> >> there were 10 choices for the first and 9 for the second and so on adding 
> >> up to 10!/2! or 1,814,400  different combinations tried. That approaches 2 
> >> million.
> >>
> >> Jack broke the problem down into evaluating the units column with a loop 
> >> like this:
> >>
> >> itertools.permutations(range(10), 3)
> >>
> >> That is 720 possibilities. He then doubled that to 1,440 to consider a 
> >> carry. Only if the selected values for the three variables in contention 
> >> (plus a carry) does he go on to call to evaluate the tens column.
> >>
> >> It then shrinks a bit more as he no longer gets the permutations of all 10 
> >> digits. He subtracts the three values that might work for the units, so he 
> >> is asking for permutations of 7 digits, two at a time. That is 42, doubled 
> >> again to 84 for carry purposes. And this function is not called 1,440 
> >> times, but quite a bit fewer. 
> >>
> >> So, similarly, of those 84 loops for tens, he only sometimes calls to 
> >> evaluate hundreds. As mentioned, the set of 10 digits shrinks some more 
> >> and this continues upward to functions that evaluate hundreds and 
> >> thousands  and finally the one evaluating ten thousands pretty

Ask for help about class variable scope (Re: Why doesn't a dictionary work in classes?)

2018-12-26 Thread jfong
I saw the code below at stackoverflow. I have a little idea about the scope of 
a class, and list comprehension and generator expressions, but still can't 
figure out why Z4 works and Z5 not. Can someone explain it? (in a 
not-too-complicated way:-)

class Foo():
XS = [15, 15, 15, 15]
Z4 = sum(val for val in XS)
try:
Z5 = sum(XS[i] for i in range(len(XS)))
except NameError:
Z5 = None

print(Foo.Z4, Foo.Z5)
>>> 60 None


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


Re: Ask for help about class variable scope (Re: Why doesn't a dictionary work in classes?)

2018-12-27 Thread jfong
eryk sun於 2018年12月27日星期四 UTC+8下午2時31分58秒寫道:
> On 12/26/18, jf...@ms4.hinet.net  wrote:
> > I saw the code below at stackoverflow. I have a little idea about the scope
> > of a class, and list comprehension and generator expressions, but still
> > can't figure out why Z4 works and Z5 not. Can someone explain it? (in a
> > not-too-complicated way:-)
> >
> > class Foo():
> > XS = [15, 15, 15, 15]
> > Z4 = sum(val for val in XS)
> > try:
> > Z5 = sum(XS[i] for i in range(len(XS)))
> > except NameError:
> > Z5 = None
> >
> > print(Foo.Z4, Foo.Z5)
>  60 None
> 
> Maybe rewriting it with approximately equivalent inline code and
> generator functions will clarify the difference:
> 
> class Foo:
> def genexpr1(iterable):
> for val in iterable:
> yield val
> 
> def genexpr2(iterable):
> for i in iterable:
> yield XS[i]
> 
> XS = [15, 15, 15, 15]
> Z4 = sum(genexpr1(XS))
> try:
> Z5 = sum(genexpr2(range(len(XS
> except NameError:
> Z5 = None
> 
> del genexpr1, genexpr2
> 
> >>> print(Foo.Z4, Foo.Z5)
> 60 None
> 
> In both cases, an iterable is passed to the generator function. This
> argument is evaluated in the calling scope (e.g. range(len(XS))). A
> generator expression has a similar implementation, except it also
> evaluates the iterator for the iterable to ensure an exception is
> raised immediately in the defining scope if it's not iterable. For
> example:
> 
> >>> (x for x in 1)
> Traceback (most recent call last):
>   File "", line 1, in 
> TypeError: 'int' object is not iterable
> 
> genexpr1 is working with local variables only, but genexpr2 has a
> non-local reference to variable XS, which we call late binding. In
> this case, when the generator code executes the first pass of the loop
> (whenever that is), it looks for XS in the global (module) scope and
> builtins scope. It's not there, so a NameError is raised.
> 
> With late-binding, the variable can get deleted or modified in the
> source scope while the generator gets evaluated. For example:
> 
> >>> x = 'spam'
> >>> g = (x[i] for i in range(len(x)))
> >>> next(g)
> 's'
> >>> del x
> >>> next(g)
> Traceback (most recent call last):
>   File "", line 1, in 
>   File "", line 1, in 
> NameError: name 'x' is not defined
> 
> >>> x = 'spam'
> >>> g = (x[i] for i in range(len(x)))
> >>> next(g)
> 's'
> >>> x = 'eggs'
> >>> list(g)
> ['g', 'g', 's']

I still don't get it. When I change it to using list comprehension, the problem 
is still there. (it now has no late-binding variable, right? :-)

>>> class Too:
... XS = [15, 15, 15, 15]
... Z4 = [val for val in XS]
... Z5 = [XS[0] for val in XS]
...
Traceback (most recent call last):
  File "", line 1, in 
  File "", line 4, in Too
  File "", line 4, in 
NameError: name 'XS' is not defined
>>>

The problem confuse me is that is XS a local variable of the list comprehension?
If it's then Z5 should work, if it's not then Z4 shouldn't work when it's 
written in generator expression.

Or, things is much more complex than I thought:-(


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


Re: Ask for help about class variable scope (Re: Why doesn't a dictionary work in classes?)

2018-12-28 Thread jfong
eryk sun at 2018/12/27 UTC+8 PM 6:58:33 wrote:
> On 12/27/18, jf...@ms4.hinet.net  wrote:
> >
> > I still don't get it. When I change it to using list comprehension, the
> > problem is still there. (it now has no late-binding variable, right? :-)
> >
>  class Too:
> > ... XS = [15, 15, 15, 15]
> > ... Z4 = [val for val in XS]
> > ... Z5 = [XS[0] for val in XS]
> > ...
> > Traceback (most recent call last):
> >   File "", line 1, in 
> >   File "", line 4, in Too
> >   File "", line 4, in 
> > NameError: name 'XS' is not defined
> >
> > The problem confuse me is that is XS a local variable of the list
> > comprehension?
> 
> XS is not a local variable in the scope of either comprehension. XS is
> local to the class statement's scope. For each comprehension, an
> iterator for the current object referenced by XS gets instantiated
> (early binding) and passed as an argument to the comprehension scope.
> If we disassemble the comprehension code, we find that this iterator
> argument has the creatively illegal name ".0". (The bytecode
> references it by its fast-locals-array index, not its weird name.)
> 
> In the Z5 case, XS is a non-local variable (late binding) in the
> loop-body expression (left-hand side) of the comprehension. That's
> common for Python code. In every iteration of the loop, the
> interpreter looks up the object referenced by the name "XS", which can
> change at any time (e.g. by another thread).

In Python document 4.2.2. Resolution of names, the last paragraph:

"...A class definition is an executable statement that may use and define 
names. These references follow the normal rules for name resolution with an 
exception that unbound local variables are looked up in the global namespace. 
...The scope of names defined in a class block is limited to the class block; 
it does not extend to the code blocks of methods – this includes comprehensions 
and generator expressions since they are implemented using a function scope". 

These statements reflect the following difference:

>>> xy = [1,2]
>>> [dir() for i in xy]
[['.0', 'i'], ['.0', 'i']]
>>> [xy[0] for i in xy]
[1, 1]

>>> class foo():
... xs = [1,2]
... z4 = [dir() for i in xs]
...
>>> foo().z4
[['.0', 'i'], ['.0', 'i']]
>>> class foo():
... xs = [1,2]
... z4 = [xs[0] for i in xs]
...
Traceback (most recent call last):
  File "", line 1, in 
  File "", line 3, in foo
  File "", line 3, in 
NameError: name 'xs' is not defined
>>>

and it goes further:

>>> [dir() for i in xy for j in xy]
[['.0', 'i', 'j'], ['.0', 'i', 'j'], ['.0', 'i', 'j'], ['.0', 'i', 'j']]
>>> class foo():
... xs = [1,2]
... z5 = [dir() for i in xs for j in xs]
...
Traceback (most recent call last):
  File "", line 1, in 
  File "", line 3, in foo
  File "", line 3, in 
NameError: name 'xs' is not defined
>>>

That's all I had learn so far, although not understand the design decision 
behind it yet:-(

--Jach

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


Re: Ask for help about class variable scope (Re: Why doesn't a dictionary work in classes?)

2018-12-28 Thread jfong
jf...@ms4.hinet.net於 2018年12月28日星期五 UTC+8下午4時04分07秒寫道:
> eryk sun at 2018/12/27 UTC+8 PM 6:58:33 wrote:
> > On 12/27/18, jf...@ms4.hinet.net  wrote:
> > >
> > > I still don't get it. When I change it to using list comprehension, the
> > > problem is still there. (it now has no late-binding variable, right? :-)
> > >
> >  class Too:
> > > ... XS = [15, 15, 15, 15]
> > > ... Z4 = [val for val in XS]
> > > ... Z5 = [XS[0] for val in XS]
> > > ...
> > > Traceback (most recent call last):
> > >   File "", line 1, in 
> > >   File "", line 4, in Too
> > >   File "", line 4, in 
> > > NameError: name 'XS' is not defined
> > >
> > > The problem confuse me is that is XS a local variable of the list
> > > comprehension?
> > 
> > XS is not a local variable in the scope of either comprehension. XS is
> > local to the class statement's scope. For each comprehension, an
> > iterator for the current object referenced by XS gets instantiated
> > (early binding) and passed as an argument to the comprehension scope.
> > If we disassemble the comprehension code, we find that this iterator
> > argument has the creatively illegal name ".0". (The bytecode
> > references it by its fast-locals-array index, not its weird name.)
> > 
> > In the Z5 case, XS is a non-local variable (late binding) in the
> > loop-body expression (left-hand side) of the comprehension. That's
> > common for Python code. In every iteration of the loop, the
> > interpreter looks up the object referenced by the name "XS", which can
> > change at any time (e.g. by another thread).
> 
> In Python document 4.2.2. Resolution of names, the last paragraph:
> 
> "...A class definition is an executable statement that may use and define 
> names. These references follow the normal rules for name resolution with an 
> exception that unbound local variables are looked up in the global namespace. 
> ...The scope of names defined in a class block is limited to the class block; 
> it does not extend to the code blocks of methods – this includes 
> comprehensions and generator expressions since they are implemented using a 
> function scope". 
> 
> These statements reflect the following difference:
> 
> >>> xy = [1,2]
> >>> [dir() for i in xy]
> [['.0', 'i'], ['.0', 'i']]
> >>> [xy[0] for i in xy]
> [1, 1]
> 
> >>> class foo():
> ... xs = [1,2]
> ... z4 = [dir() for i in xs]
> ...
> >>> foo().z4
> [['.0', 'i'], ['.0', 'i']]
> >>> class foo():
> ... xs = [1,2]
> ... z4 = [xs[0] for i in xs]
> ...
> Traceback (most recent call last):
>   File "", line 1, in 
>   File "", line 3, in foo
>   File "", line 3, in 
> NameError: name 'xs' is not defined
> >>>
> 
> and it goes further:
> 
> >>> [dir() for i in xy for j in xy]
> [['.0', 'i', 'j'], ['.0', 'i', 'j'], ['.0', 'i', 'j'], ['.0', 'i', 'j']]
> >>> class foo():
> ... xs = [1,2]
> ... z5 = [dir() for i in xs for j in xs]
> ...
> Traceback (most recent call last):
>   File "", line 1, in 
>   File "", line 3, in foo
>   File "", line 3, in 
> NameError: name 'xs' is not defined
> >>>
> 
> That's all I had learn so far, although not understand the design decision 
> behind it yet:-(
> 
> --Jach

Anyway, it "looks" weird. Isn't it?

>>> xs = [5,6,7,8]
>>> class foo():
... xs = [1,2,3]
... z4 = [xs[i] for i in xs]
...
>>> foo.z4
[6,7,8]

xs in the "for" statement referenced to class variable xs and xs[i] in the body 
referenced to the global xs with i from locals.

PS. Don't bother to reply. This is just for my own documentary:-)
-- 
https://mail.python.org/mailman/listinfo/python-list


How to run a module before install?

2019-01-13 Thread jfong
I had download a module which has the following directory structure:

[XL-Sudoku-Solver_master]
  |__[tests]
  |__[xl_sudoku_solver]
  |__setup.py   |__ __init__.py
  |__problem1.txt   |__ __main__.py
  |__README.md  |__ ...
  |__ ...

The setup.py file has something like this:
-
...
setup(
name="xl-sudoku-solver",
version="0.0.1.post3",
packages=['xl_sudoku_solver'],
entry_points={
"console_scripts": [
"xl-sudoku-solver = xl_sudoku_solver.__main__:main"
]
},
...


and the __main__.py has:

...
from . import Solver, load_from_file, load_from_input, load_from_string

def main():
...

if __name__ == '__main__':
main()


The README.md suggest the way of running it:

pip install xl-sudoku-solver
$ xl-sudoku-solver --time -f problem1.txt 

But I like to run it before install. Is it possible? and how? I had try two 
ways below but niether works:

1) h:\Temp\XL-Sudoku-Solver-master>py xl_sudoku_solver --time -f problem1.txt
Traceback (most recent call last):
  File "C:\Python34\lib\runpy.py", line 170, in _run_module_as_main
"__main__", mod_spec)
  File "C:\Python34\lib\runpy.py", line 85, in _run_code
exec(code, run_globals)
  File "xl_sudoku_solver\__main__.py", line 5, in 
from . import Solver, load_from_file, load_from_input, load_from_string
SystemError: Parent module '' not loaded, cannot perform relative import

2) h:\Temp\XL-Sudoku-Solver-master>py
Python 3.4.4 (v3.4.4:737efcadf5a6, Dec 20 2015, 19:28:18) [MSC v.1600 32 bit 
(Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import xl_sudoku_solver
>>>

Can't find the name "main", What to do?


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


Re: How to run a module before install?

2019-01-14 Thread jfong
Peter Otten於 2019年1月14日星期一 UTC+8下午4時04分33秒寫道:
> jf...@ms4.hinet.net wrote:
> 
> > I had download a module which has the following directory structure:
> > 
> > [XL-Sudoku-Solver_master]
> >   |__[tests]
> >   |__[xl_sudoku_solver]
> >   |__setup.py   |__ __init__.py
> >   |__problem1.txt   |__ __main__.py
> >   |__README.md  |__ ...
> >   |__ ...
> > 
> > The setup.py file has something like this:
> > -
> > ...
> > setup(
> > name="xl-sudoku-solver",
> > version="0.0.1.post3",
> > packages=['xl_sudoku_solver'],
> > entry_points={
> > "console_scripts": [
> > "xl-sudoku-solver = xl_sudoku_solver.__main__:main"
> > ]
> > },
> > ...
> > 
> > 
> > and the __main__.py has:
> > 
> > ...
> > from . import Solver, load_from_file, load_from_input, load_from_string
> > 
> > def main():
> > ...
> > 
> > if __name__ == '__main__':
> > main()
> > 
> > 
> > The README.md suggest the way of running it:
> > 
> > pip install xl-sudoku-solver
> > $ xl-sudoku-solver --time -f problem1.txt
> > 
> > But I like to run it before install. Is it possible? and how? I had try
> > two ways below but niether works:
> > 
> > 1) h:\Temp\XL-Sudoku-Solver-master>py xl_sudoku_solver --time -f
> > problem1.txt Traceback (most recent call last):
> >   File "C:\Python34\lib\runpy.py", line 170, in _run_module_as_main
> > "__main__", mod_spec)
> >   File "C:\Python34\lib\runpy.py", line 85, in _run_code
> > exec(code, run_globals)
> >   File "xl_sudoku_solver\__main__.py", line 5, in 
> > from . import Solver, load_from_file, load_from_input,
> > load_from_string
> > SystemError: Parent module '' not loaded, cannot perform relative import
> > 
> > 2) h:\Temp\XL-Sudoku-Solver-master>py
> > Python 3.4.4 (v3.4.4:737efcadf5a6, Dec 20 2015, 19:28:18) [MSC v.1600 32
> > bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for
> > more information.
>  import xl_sudoku_solver
> 
> > 
> > Can't find the name "main", What to do?
> 
> With h:\Temp\XL-Sudoku-Solver-master as the current working directory try
> 
> h:\Temp\XL-Sudoku-Solver-master>py -m xl_sudoku_solver

Great! it works. Thank you, peter.

By the way, can you explain what these two command difference means? with or 
without a "-m". Or pointing where the document is. Thanks ahead:-)

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


Re: Problem : Generator

2019-02-15 Thread jfong
Prahallad Achar於 2019年2月15日星期五 UTC+8下午5時27分36秒寫道:
> I get list object instead gen  obj
> 
> On Fri, 15 Feb 2019, 13:57 Chris Angelico  
> > On Fri, Feb 15, 2019 at 6:57 PM Prahallad Achar 
> > wrote:
> > >
> > > How about this
> > > List1=[ 1,2,3,4]
> > > Rever_gen = ( x*x for x in list1, reversed = True)
> > >
> > > Rever_gen gets generator object and iterating it now gets reverse order..
> > >
> > > Am I correct here? Suggest me
> > >
> >
> > How about reversed(list1) ?
> >
> > ChrisA
> > --
> > https://mail.python.org/mailman/listinfo/python-list
> >
Rever_gen = ( x*x for x in reversed(list1))


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


Ask for help on using asynctk package

2019-02-20 Thread jfong
The file below is a simple script to test this package.
-
# test_asynctk.py

import asynctk as atk

root = atk.AsyncTk()
def delay5S():
btn0.after(5000)
def inc1():
msgs = btn1.cget('text').split()
n = int(msgs[1])
msg = msgs[0] + ' ' + str(n+1) 
btn1.config(text=msg)

btn0 = atk.AsyncButton(root, text='delay 5s', command=delay5S)
btn0.pack()
btn1 = atk.AsyncButton(root, text='increment 0', command=inc1)
btn1.pack()

if __name__ == "__main__":
root.mainloop()
-

After import this script and press the increment button, the following error 
appears. No idea how to use it correctly. Any help?

Python 3.7.1 (v3.7.1:260ec2c36a, Oct 20 2018, 14:05:16) [MSC v.1915 32 bit 
(Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import test_asynctk
# press the button
>>> Exception in Tkinter callback
Traceback (most recent call last):
  File "H:\WPy-3710Zero\python-3.7.1\lib\tkinter\__init__.py", line 1705, in 
__call__
return self.func(*args)
  File "H:\Works\Python34\asynctk-master\asynctk\_lib.py", line 1615, in 

kw["command"] = lambda *i: asyncio.ensure_future(kw["command"](*i))
  File "H:\Works\Python34\asynctk-master\asynctk\_lib.py", line 1615, in 

kw["command"] = lambda *i: asyncio.ensure_future(kw["command"](*i))
  File "H:\Works\Python34\asynctk-master\asynctk\_lib.py", line 1615, in 

kw["command"] = lambda *i: asyncio.ensure_future(kw["command"](*i))
  [Previous line repeated 995 more times]
RecursionError: maximum recursion depth exceeded

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


Re: Quirk difference between classes and functions

2019-02-26 Thread jfong
ast於 2019年2月26日星期二 UTC+8上午12時25分40秒寫道:
> Hello
> 
> I noticed a quirk difference between classes and functions
> 
>  >>> x=0
>  >>>
>  >>> class Test:
>  x = x+1
>  print(x)
>  x = x+1
>  print(x)
> 
> 1
> 2
>  >>> print(x)
> 0
> 
> Previous code doesn't generate any errors.
> x at the right of = in first "x = x+1" line is
> the global one (x=0), then x becomes local
> 
> within a function, this is not allowed
> 
>  >>> x = 0
>  >>>
>  >>> def f():
>  x = x+1
> 
>  >>> f()
> UnboundLocalError: local variable 'x' referenced before assignment
> 
> Since x is written inside the function, it is considered as a local
> variable and x in x+1 is undefined so this throw an exception
> 
> Any comment ?

May I say that the LEGB rule apply to run time, not compile time?

>>> x = 1
>>> def f():
... print(x)
... print(locals())
...
>>> f()
1
{}
>>> def g():
... print(x)
... x = 2
... print(locals())
...
>>> g()
Traceback (most recent call last):
  File "", line 1, in 
  File "", line 2, in g
UnboundLocalError: local variable 'x' referenced before assignment
>>> class X:
... print(x)
... x = 2
...
1
>>>
The print(x) difference between class and function was caused by that one was 
executed and the other was compiled. The LEGB rule must apply to run time to 
make the language dynamic.

Any comment:-)?

--Jach

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


Re: Quirk difference between classes and functions

2019-02-26 Thread jfong
Gregory Ewing at 2019/2/27 AM 5:26:49 wrote:
> Thomas Jollans wrote:
> > I imagine there's a justification for the difference in behaviour to do
> > with the fact that the body of a class is only ever executed once, while
> > the body of a function is executed multiple times.
> 
> I suspect there isn't any deep reason for it, rather it's just
> something that fell out of the implementation, in particular
> the decision to optimise local variable access in functions
> but not other scopes.
> 
> When compiling a function, the compiler needs to know which
> variables are local so that it can allocate slots for them in
> the stack frame. But when executing a class body, the locals
> are kept in a dict and are looked up dynamically.

If the compiler can do any decision on the variable's name, when it goes to 
line of print, how it handle it?

x = 0
def f():
print(x)

def g():
print(x)
x = 1
print(y)

--Jach

> The compiler *could* be made to treat class bodies the same
> way as functions in this regard, but it would be extra work
> for little or no benefit. Most code in class bodies just
> defines new names without referring to anything else in the
> same scope.
> 
> -- 
> Greg

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


Re: Quirk difference between classes and functions

2019-02-26 Thread jfong
Chris Angelico於 2019年2月27日星期三 UTC+8上午9時25分11秒寫道:
> On Wed, Feb 27, 2019 at 12:21 PM  wrote:
> >
> > Gregory Ewing at 2019/2/27 AM 5:26:49 wrote:
> > > Thomas Jollans wrote:
> > > > I imagine there's a justification for the difference in behaviour to do
> > > > with the fact that the body of a class is only ever executed once, while
> > > > the body of a function is executed multiple times.
> > >
> > > I suspect there isn't any deep reason for it, rather it's just
> > > something that fell out of the implementation, in particular
> > > the decision to optimise local variable access in functions
> > > but not other scopes.
> > >
> > > When compiling a function, the compiler needs to know which
> > > variables are local so that it can allocate slots for them in
> > > the stack frame. But when executing a class body, the locals
> > > are kept in a dict and are looked up dynamically.
> >
> > If the compiler can do any decision on the variable's name, when it goes to 
> > line of print, how it handle it?
> >
> > x = 0
> > def f():
> > print(x)
> >
> > def g():
> > print(x)
> > x = 1
> > print(y)
> >
> 
> Not sure what you mean by "decision", but the definition is that since
> x is assigned to in g(), it is local to g(). It's not local to f(), so
> the global is visible.

So, may I say that the Python compiler is a multi-pass one?

--Jach
> 
> (Incidentally, "print" is handled exactly the same way. Since neither
> function assigns to print, it's not local, so the built-in is found.)
> 
> ChrisA

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


Re: Quirk difference between classes and functions

2019-02-26 Thread jfong
Chris Angelico於 2019年2月27日星期三 UTC+8上午11時29分04秒寫道:
> On Wed, Feb 27, 2019 at 2:21 PM  wrote:
> >
> > Chris Angelico於 2019年2月27日星期三 UTC+8上午9時25分11秒寫道:
> > > On Wed, Feb 27, 2019 at 12:21 PM  wrote:
> > > >
> > > > Gregory Ewing at 2019/2/27 AM 5:26:49 wrote:
> > > > > Thomas Jollans wrote:
> > > > > > I imagine there's a justification for the difference in behaviour 
> > > > > > to do
> > > > > > with the fact that the body of a class is only ever executed once, 
> > > > > > while
> > > > > > the body of a function is executed multiple times.
> > > > >
> > > > > I suspect there isn't any deep reason for it, rather it's just
> > > > > something that fell out of the implementation, in particular
> > > > > the decision to optimise local variable access in functions
> > > > > but not other scopes.
> > > > >
> > > > > When compiling a function, the compiler needs to know which
> > > > > variables are local so that it can allocate slots for them in
> > > > > the stack frame. But when executing a class body, the locals
> > > > > are kept in a dict and are looked up dynamically.
> > > >
> > > > If the compiler can do any decision on the variable's name, when it 
> > > > goes to line of print, how it handle it?
> > > >
> > > > x = 0
> > > > def f():
> > > > print(x)
> > > >
> > > > def g():
> > > > print(x)
> > > > x = 1
> > > > print(y)
> > > >
> > >
> > > Not sure what you mean by "decision", but the definition is that since
> > > x is assigned to in g(), it is local to g(). It's not local to f(), so
> > > the global is visible.
> >
> > So, may I say that the Python compiler is a multi-pass one?
> >
> 
> At this point, you're veering away from "Python-the-language" and
> towards "CPython-the-implementation" (or whichever other
> implementation you want to explore). 

Yes, it's a little away:-) I was curious about how the compiled print(x) can be 
influenced by x = 1 after it. Anyway, thank you for your confirmation.

--Jach

> But I would say that, yes, most
> or all Python implementations will use multi-pass compilation. It's
> the easiest way to guarantee correct behaviour. For instance, when you
> reach a "try" statement, you don't know whether there'll be an
> "except" block after it (there might just be a "finally"); the
> bytecode that CPython produces is different for setting up a
> finally-only block than for setting up a try/except. Easiest to find
> out that sort of thing by running multiple passes.
> 
> Plus, depending on how you define "pass", there are additional steps
> such as constant folding and peephole optimization that can be done
> after everything else. So, yeah, it's highly unlikely that there are
> any performant implementations of Python that run a single compilation
> pass.
> 
> ChrisA

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


Re: Quirk difference between classes and functions

2019-02-27 Thread jfong
jf...@ms4.hinet.net於 2019年2月26日星期二 UTC+8下午4時46分04秒寫道:
> ast於 2019年2月26日星期二 UTC+8上午12時25分40秒寫道:
> > Hello
> > 
> > I noticed a quirk difference between classes and functions
> > 
> >  >>> x=0
> >  >>>
> >  >>> class Test:
> >  x = x+1
> >  print(x)
> >  x = x+1
> >  print(x)
> > 
> > 1
> > 2
> >  >>> print(x)
> > 0
> > 
> > Previous code doesn't generate any errors.
> > x at the right of = in first "x = x+1" line is
> > the global one (x=0), then x becomes local
> > 
> > within a function, this is not allowed
> > 
> >  >>> x = 0
> >  >>>
> >  >>> def f():
> >  x = x+1
> > 
> >  >>> f()
> > UnboundLocalError: local variable 'x' referenced before assignment
> > 
> > Since x is written inside the function, it is considered as a local
> > variable and x in x+1 is undefined so this throw an exception
> > 
> > Any comment ?
> 
> May I say that the LEGB rule apply to run time, not compile time?

No. The LEGB apply to compile time where only name and scope are involved.

> 
> >>> x = 1
> >>> def f():
> ... print(x)
> ... print(locals())
> ...
> >>> f()
> 1
> {}
> >>> def g():
> ... print(x)
> ... x = 2
> ... print(locals())
> ...
> >>> g()
> Traceback (most recent call last):
>   File "", line 1, in 
>   File "", line 2, in g
> UnboundLocalError: local variable 'x' referenced before assignment
> >>> class X:
> ... print(x)
> ... x = 2
> ...
> 1
> >>>
> The print(x) difference between class and function was caused by that one was 
> executed and the other was compiled. The LEGB rule must apply to run time to 
> make the language dynamic.

At run time, the binding between name and object can be changed. It's the word 
"dynamic" comes from. 

What happens in class X when print(x) was encountered? I have no idea how the 
LEGB involves there yet:-(

--Jach

> 
> Any comment:-)?
> 
> --Jach

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


Re: Implement C's Switch in Python 3

2019-03-15 Thread jfong
Sayth Renshaw at 2019/2/3 UTC+8 AM9:52:50 wrote:
> Or perhaps use a 3rd party library like 
> https://github.com/mikeckennedy/python-switch

Thank you for this link. It's a good general implementation.

--Jach

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


How to debug a function under the (pdb) prompt?

2019-05-10 Thread jfong
For example, there is a file test0.py:
-
1  def foo():
2  for i in range(3):
3  print(i)
4
5  x = 0
-
I start the debug session as below. My question is why the break point at line 
3 didn't work. How to debug the function foo() at this time?

D:\Works\Python>py -m pdb test0.py
> d:\works\python\test0.py(1)()
-> def foo():
(Pdb) tbreak 5
Breakpoint 1 at d:\works\python\test0.py:5
(Pdb) cont
Deleted breakpoint 1 at d:\works\python\test0.py:5
> d:\works\python\test0.py(5)()
-> x = 0
(Pdb) tbreak 3
Breakpoint 2 at d:\works\python\test0.py:3
(Pdb) foo()
0
1
2
(Pdb)
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Instance vs Class variable oddity

2019-05-17 Thread jfong
Correct me if I am wrong, please.

I always think that the LEGB rule (e.g. the namespace to look up for) was 
applied at compile-time, only the binding was resolved "dynamically" at 
run-time. For example:

def foo():
print(x)

foo() will cause a NameError. But after

x = 5

foo() will run correctly.

I also don't think the term "variable" and "attribute" can be used 
exchangeable. Variable apply to an unbound name, and attribute applies to 
bounded name. For example:

foo.x = 3 will create an attribute x of function foo. It's either not a local 
variable, or a global variable. It's more likely a class instance attribute, 
and it's resolved by applying MRO rule dynamically.

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


Re: Instance vs Class variable oddity

2019-05-18 Thread jfong
Chris Angelico於 2019年5月18日星期六 UTC+8下午3時09分37秒寫道:
> On Sat, May 18, 2019 at 1:51 PM  wrote:
> >
> > Correct me if I am wrong, please.
> >
> > I always think that the LEGB rule (e.g. the namespace to look up for) was 
> > applied at compile-time, only the binding was resolved "dynamically" at 
> > run-time. For example:
> >
> > def foo():
> > print(x)
> >
> > foo() will cause a NameError. But after
> >
> > x = 5
> >
> > foo() will run correctly.
> 
> This is correct; however, this function will fail with UnboundLocalError:
> 
> x = 1
> def foo():
> print(x)
> x = 2
> 
> Function locals ARE locked in at compile time.
> 
> ChrisA

Thank you. This example proves that the LEGB rule was applied at compile-time, 
and it fails to resolve the binding at run-time.

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


tkinter.tix "Control" widget don't work with StringVar?

2019-06-01 Thread jfong
Below is a simplified version of the sample script downloaded from its package.
When run it, the entry field display '0' instead of 'P&W'.
PS. I am using Python 3.4.4, Windows 32bit

test0.py
 1 from tkinter import tix as Tix
 2 
 3 root = Tix.Tk()
 4 
 5 demo_maker = Tix.StringVar()
 6 demo_maker.set('P&W')
 7 
 8 c = Tix.Control(root, label='Engine Maker: ',
 9variable=demo_maker,
10options='entry.width 10 label.width 20 label.anchor e')
11 c.pack(side=Tix.TOP, anchor=Tix.W)
12 
13 root.mainloop()


I run it under pdb, try to figure out where the problem is:

D:\Works\Python>py -m pdb test0.py
> d:\works\python\test0.py(1)()
-> from tkinter import tix as Tix
(Pdb) tbreak 13
Breakpoint 1 at d:\works\python\test0.py:13
(Pdb) cont
Deleted breakpoint 1 at d:\works\python\test0.py:13
> d:\works\python\test0.py(13)()
-> root.mainloop()
(Pdb) !c['value']
'0'
(Pdb) !demo_maker.get()
'P&W'
(Pdb) quit

If I change line 8 to "c = Tix.Control(root, label='Engine Maker: ', 
value='P&W',", the result is very interest:

D:\Works\Python>py -m pdb test0.py
> d:\works\python\test0.py(1)()
-> from tkinter import tix as Tix
(Pdb) tbreak 13
Breakpoint 1 at d:\works\python\test0.py:13
(Pdb) cont
Deleted breakpoint 1 at d:\works\python\test0.py:13
> d:\works\python\test0.py(13)()
-> root.mainloop()
(Pdb) !c['value']
'0'
(Pdb) !demo_maker.get()
'0'
(Pdb) quit

Anyone can help?

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


Re: tkinter.tix "Control" widget don't work with StringVar?

2019-06-01 Thread jfong
MRAB於 2019年6月2日星期日 UTC+8上午10時18分36秒寫道:
> On 2019-06-02 02:28, jf...@ms4.hinet.net wrote:
> > Below is a simplified version of the sample script downloaded from its 
> > package.
> > When run it, the entry field display '0' instead of 'P&W'.
> > PS. I am using Python 3.4.4, Windows 32bit
> > 
> > test0.py
> >   1 from tkinter import tix as Tix
> >   2
> >   3 root = Tix.Tk()
> >   4
> >   5 demo_maker = Tix.StringVar()
> >   6 demo_maker.set('P&W')
> >   7
> >   8 c = Tix.Control(root, label='Engine Maker: ',
> >   9variable=demo_maker,
> > 10options='entry.width 10 label.width 20 label.anchor e')
> > 11 c.pack(side=Tix.TOP, anchor=Tix.W)
> > 12
> > 13 root.mainloop()
> > 
> > 
> > I run it under pdb, try to figure out where the problem is:
> > 
> > D:\Works\Python>py -m pdb test0.py
> >> d:\works\python\test0.py(1)()
> > -> from tkinter import tix as Tix
> > (Pdb) tbreak 13
> > Breakpoint 1 at d:\works\python\test0.py:13
> > (Pdb) cont
> > Deleted breakpoint 1 at d:\works\python\test0.py:13
> >> d:\works\python\test0.py(13)()
> > -> root.mainloop()
> > (Pdb) !c['value']
> > '0'
> > (Pdb) !demo_maker.get()
> > 'P&W'
> > (Pdb) quit
> > 
> > If I change line 8 to "c = Tix.Control(root, label='Engine Maker: ', 
> > value='P&W',", the result is very interest:
> > 
> > D:\Works\Python>py -m pdb test0.py
> >> d:\works\python\test0.py(1)()
> > -> from tkinter import tix as Tix
> > (Pdb) tbreak 13
> > Breakpoint 1 at d:\works\python\test0.py:13
> > (Pdb) cont
> > Deleted breakpoint 1 at d:\works\python\test0.py:13
> >> d:\works\python\test0.py(13)()
> > -> root.mainloop()
> > (Pdb) !c['value']
> > '0'
> > (Pdb) !demo_maker.get()
> > '0'
> > (Pdb) quit
> > 
> > Anyone can help?
> > 
>  From the documentation:
> 
> """class tkinter.tix.Control
> The Control widget is also known as the SpinBox widget. The user can 
> adjust the value by pressing the two arrow buttons or by entering the 
> value directly into the entry. The new value will be checked against the 
> user-defined upper and lower limits."""
> 
> In other words, the widget that you're using is for entering a _number_; 
> you can click the up and down buttons to change its value. You usually 
> use it with tix.IntVar.
> 
> You're using it with tix.StringVar, which is for strings, and because 
> it's unable to interpret the value as a number, it's pretending that 
> it's 0 instead. You can, however, set it to, say, '1', or '01', and the 
> widget will then show the number 1.

From the documents, it sounds that this widget was designed for number only. 
But the original example Control.py from 
https://svn.python.org/projects/stackless/trunk/Demo/tix/samples/ works on 
string either by changing its button command. The only thing bothers me is that 
why it fails at the start-up? and I can't figure out the reason:-(
-- 
https://mail.python.org/mailman/listinfo/python-list


  1   2   3   >