Re: Changing 'Scripts/*.exe'

2022-10-03 Thread Meredith Montgomery
r...@zedat.fu-berlin.de (Stefan Ram) writes:

> Meredith Montgomery  writes:
>>Wouldn't it be great if it were portable by default?
>
>   I think under Windows there is a division of software
>   suggested by Microsoft, a division of software into
>   executable code and data (data may change in time).
>
>   The executable code is supposed to rest under
>   "C:\Program Files" the contents of which cannot be
>   modified by user processes easily. Program configuration
>   can be stored below "AppData" in the user directory.
>   It is supposed to be more secure when executable code
>   cannot be modified easily by user processes.
>
>   So far, Python has decided to ignore this and install
>   everything under AppData as I understand it. So one 
>   gets neither the security of "Program Files" nor the
>   possibility to move it to another directory easily.

Interesting.  I like portable things.  You copy from one place to
another and it just runs.  As it should.  Things should be simple.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: on GNU EMACS's python-mode, loading entire buffer

2022-10-03 Thread Meredith Montgomery
Stephen Berman  writes:

> On Sun, 04 Sep 2022 16:47:07 -0300 Meredith Montgomery
>  wrote:
>
>> Meredith Montgomery  writes:
>>
>>> Meredith Montgomery  writes:
>>>
>>> [...]
>>>
>>>> I would also be interested in a command that restarts the REPL afresh
>>>> and reloads my buffer --- sort of like keyboard's [F5] of the IDLE.
>>>
>>> A partial solution for this is the following procedure.
>>>
>>> (defun python-revert-and-send-buffer-to-repl ()
>>>   "Revert current buffer and sends it to the Python REPL."
>>>   (interactive)
>>>   (revert-buffer "ignore-auto-no" "no-confirm")
>>>   (python-shell-send-buffer))
>>>
>>> We can map this to the F5-key and that improves things.  But a restart
>>> of the REPL would be the ideal.  (Sometimes we really want to start
>>> afresh.  Sometimes.  Most often we don't want that.)
>>
>> It's not easy to restart the REPL.  You can send "quit()" to it and
>> invoke run-python again interactively by typing out one command after
>> another, but if you write a procedure such as this one below, it doesn't
>> work: it gives me the impression that there's a timing issue, that is,
>> perhaps the procedure is too fast and something happens before it
>> should.
>>
>> (defun python-save-send-buffer-to-repl ()
>>   (interactive)
>>   (save-buffer)
>>   (python-shell-send-string "quit()")
>>   (run-python)
>>   (python-shell-send-buffer)
>>   (python-shell-switch-to-shell))
>
> It does seem like a timing issue.  This works for me:
>
> (defun python-save-send-buffer-to-repl ()
>   (interactive)
>   (save-buffer)
>   (python-shell-send-string "quit()")
>   (sit-for 0.1)
>   (run-python)
>   (python-shell-send-buffer)
>   (python-shell-switch-to-shell))
>
> But if I decrease the wait to 0.05 it doesn't work.

Interesting.  I can't reproduce this at all.  No matter how long I sit,
I always get a similar ``crash''.  Here's what happens for me with your
procedure, sitting for even 5 seconds.  I'm adding a 5-second delay
after quitting and after running the REPL.

--8<---cut here---start->8---
(defun python-save-send-buffer-to-repl ()
  "Save current buffer and sends it to the Python REPL."
  (interactive)
  (save-buffer)
  (python-shell-send-string "quit()")
  (sit-for 5)
  (run-python)
  (sit-for 5)
  (python-shell-send-buffer)
  (python-shell-switch-to-shell))
--8<---cut here---end--->8---

When the REPL comes up, it looks fine.  When I try to see if a
hello-procedure was defined, I get the following:

--8<---cut here---start->8---
>>> 
Process Python finished
Python 3.10.6 (tags/v3.10.6:9c7b4bd, Aug  1 2022, 21:53:49) [MSC v.1932 64 bit 
(AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> 
Traceback (most recent call last):
  File "", line 1, in 
  File "c:/Users/mer/AppData/Local/Temp/pyoUKuUx", line 1
Python 3.10.6 (tags/v3.10.6:9c7b4bd, Aug  1 2022, 21:53:49) [MSC v.1932 64 
bit (AMD64)] on win32
^
SyntaxError: invalid decimal literal
>>> >>> hello
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'hello' is not defined. Did you mean: 'help'?
>>> 
--8<---cut here---end--->8---

You see?  It seems that the Python's banner is sent to the REPL,
somehow.  I actually see it being sent sometimes --- I see in the
minibuffer that the string ``Python 3.10.6 (tags/v3.10.6:9c7b4bd[...]''
was sent to the REPL.

Somehow my GNU EMACS is reading the banner and sending it back to the
REPL as if it were code in my file.  My file contained just this:

--8<---cut here---start->8---
# -*- mode: python; python-indent-offset: 2 -*-
def hello():
  return 1
--8<---cut here---end--->8---
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Changing 'Scripts/*.exe'

2022-10-03 Thread Meredith Montgomery
Gisle Vanem  writes:

> Hello list.
>
> I'm moved my old Python27 installation from
>   f:\ProgramFiler\Python27  ( == 'ProgramFiles')
> to
>   f:\gv\Python27
>
> and now many 'scripts/*.exe' program fails
> to start since the old path to 'Python.exe'
> is wrong.
>
> E.g. 'Scripts/pip2.exe' has the path
> "f:\programfiler\python27\python.exe" hard-coded
> inside it.
>
> Is there a easy way to fix this w/o re-installing this
> old Python?

Wouldn't it be great if it were portable by default?
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: on implementing a toy oop-system

2022-09-29 Thread Meredith Montgomery
r...@zedat.fu-berlin.de (Stefan Ram) writes:

[...]

>>>However, to evaluate a method call such as "o.m( a, a1, ... )",
>>>currying does not necessarily have to be used. One can as well 
>>>determine the function to be used for "m" from the type of "o" 
>>>and then call that function with arguments "o", "a", "a1", ... 
>>Was that your last approach? 
>
>   Yes, I think so. 
>
>   (There are also languages with "multi-methods", where upon
>   a function call "m( o, o1, ... )" the decision which function
>   to call depends on all the types of all the arguments.)

I think Clojure is one such.  I've read Part 1 of ``Clojure in Action''
by Amit Rathore, 2012, Manning, ISBN 9781935182597.  I liked it.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: on implementing a toy oop-system

2022-09-29 Thread Meredith Montgomery
r...@zedat.fu-berlin.de (Stefan Ram) writes:

> Meredith Montgomery  writes:
>>The code below works, but you can see it's kinda ugly.  I wish I could
>>uncurry a procedure, but I don't think this is possible.  (Is it?)
>
> from functools import partial
> from operator import add
> add5 = partial( add, 5 )
> print( add5( 2 ))
> # might be dependent on implementation details of "functools":
> uncurried = add5.func
> print( uncurried( 14, 7 ))

It works on my system here.  Thank you so much for your help.  (I've
been learning a lot with you!)

>   However, to evaluate a method call such as "o.m( a, a1, ... )",
>   currying does not necessarily have to be used. One can as well 
>   determine the function to be used for "m" from the type of "o" 
>   and then call that function with arguments "o", "a", "a1", ... 

Was that your last approach?  I only glanced at it so far.  But I
remember seeing you describing an object and listing out which methods
were defined for it and then there was one procedure that would take the
role of invoking the methods (with the proper arguments).
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: on implementing a toy oop-system

2022-09-28 Thread Meredith Montgomery
Meredith Montgomery  writes:

> r...@zedat.fu-berlin.de (Stefan Ram) writes:
>
>> Meredith Montgomery  writes:
>>>Is that at all possible somehow?  Alternatively, how would you do your
>>>toy oop-system?
>>
>>   Maybe something along those lines:
>>
>> from functools import partial
>>
>> def counter_create( object ):
>> object[ "n" ]= 0
>> def counter_increment( object ):
>> object[ "n" ]+= 1
>> def counter_value( object ):
>> return object[ "n" ]
>>
>> counter_class =( counter_create, counter_increment, counter_value )
>>
>> def inherit_from( class_, target ):
>> class_[ 0 ]( target )
>> for method in class_[ 1: ]:
>> target[ method.__name__ ]= partial( method, target )
>>
>> car = dict()
>>
>> inherit_from( counter_class, car )
>>
>> print( car[ "counter_value" ]() )
>> car[ "counter_increment" ]()
>> print( car[ "counter_value" ]() )
>>
>>   . The "create" part is simplified. I just wanted to show how
>>   to make methods like "counter_increment" act on the object
>>   that inherited them using "partial".
>
> I really liked this idea.  I organized it my way.  Have a look.  (Thank
> you for the lecture!)

But it lacks consistency.

> from functools import partial
>
> def Counter(name = None):
>   o = {"name": name if name else "untitled", "n": 0}
>   def inc(o):
> o["n"] += 1
> return o
>   o["inc"] = inc
>   def get(o):
> return o["n"]
>   o["get"] = get
>   return o

This parent class is not defined in the same way as the child class
below.  The class below uses partial to fix the object in the method,
but the parent one does not.  We need consistency.  

But if we curry the parent class's methods (that is, if we apply partial
on it to fix the object in its first argument), we will curry them a
second time in inherit_from.  That won't work.  I can't see an elegant
solution there, so what I'm going to do is to keep a copy of the
uncurried original method.

The code below works, but you can see it's kinda ugly.  I wish I could
uncurry a procedure, but I don't think this is possible.  (Is it?)

# -*- mode: python; python-indent-offset: 2 -*-
def Counter(name = None):
  self = {"name": name if name else "untitled", "n": 0}
  def inc(self):
self["n"] += 1
return self
  self["inc_uncurried"] = inc
  self["inc"] = curry(inc, self)
  def get(self):
return self["n"]
  self["get_uncurried"] = get
  self["get"] = curry(get, self)
  return self

def Car(maker):
  self = {"maker": maker, "state": "off"}
  inherit_from(Counter, self)
  def on(self):
if self["is_on"]():
  raise ValueError("oh, no: car is already on")
self["inc"]()
print(f"{self['maker']}: bruum!")
self["state"] = "on"
return self
  self["on_uncurried"] = on
  self["on"] = curry(on, self)
  def off(self):
if self["is_off"]():
  raise ValueError("oh, no: car is already off")
print(f"{self['maker']}: spat!")
self["state"] = "off"
return self
  self["off_uncurried"] = off
  self["off"] = curry(off, self)
  def is_on(self):
return self["state"] == "on"
  self["is_on_uncurried"] = is_on
  self["is_on"] = curry(is_on, self)
  def is_off(self):
return self["state"] == "off"
  self["is_off_uncurried"] = is_off
  self["is_off"] = curry(is_off, self)
  return self

def main():
  car1 = Car("Ford")
  car2 = Car("VW")
  for i in range(5):
car1["on"](); car1["off"]()
  for i in range(3):
car2["on"](); car2["off"]()
  print(f"car turned on = {car1['get']()} ({car1['maker']})")
  print(f"car turned on = {car2['get']()} ({car2['maker']})")

>>> main()
Ford: bruum!
Ford: spat!
Ford: bruum!
Ford: spat!
Ford: bruum!
Ford: spat!
Ford: bruum!
Ford: spat!
Ford: bruum!
Ford: spat!
VW: bruum!
VW: spat!
VW: bruum!
VW: spat!
VW: bruum!
VW: spat!
car turned on = 5 (Ford)
car turned on = 3 (VW)
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: on implementing a toy oop-system

2022-09-23 Thread Meredith Montgomery
Chris Angelico  writes:

> On Sat, 24 Sept 2022 at 07:52, Meredith Montgomery
>  wrote:
>>
>> def Counter(name = None):
>>   o = {"name": name if name else "untitled", "n": 0}
>>   def inc(o):
>> o["n"] += 1
>> return o
>>   o["inc"] = inc
>>   def get(o):
>> return o["n"]
>>   o["get"] = get
>>   return o
>>
>
> Want a neat demo of how classes and closures are practically the same thing?
>
> def Counter(name=None):
> if not name: name = "untitled"
> n = 0
> def inc():
> nonlocal n; n += 1
> def get():
> return n
> return locals()
>
> Aside from using a nonlocal declaration rather than "self.n", this is
> extremely similar to classes, yet there are no classes involved.
>
> A class statement creates a namespace. The locals() function returns
> the function's namespace.
>
> Each call to Counter() creates a new closure context, just like each
> call to a constructor creates a new object.
>
> There's very little difference, at a fundamental level :)

I started out this way, but I had to change direction to implement
inheritance: the difficulty with closures seems to be lexical scoping,
which makes it hard (or impossible) for me to move these closures to
another ``object''.  For instance, the nonlocal /n/ in /inc/ above is
forever bound to that closure; there seems to be no way to make /inc/
update some /n/ in another ``object'', which is needed in my conception
of inheritance.  I think Python would have to let me duplicate closures.
(Thanks for showing me /locals()/.)
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: on implementing a toy oop-system

2022-09-23 Thread Meredith Montgomery
r...@zedat.fu-berlin.de (Stefan Ram) writes:

> Meredith Montgomery  writes:
>>Is that at all possible somehow?  Alternatively, how would you do your
>>toy oop-system?
>
>   Maybe something along those lines:
>
> from functools import partial
>
> def counter_create( object ):
> object[ "n" ]= 0
> def counter_increment( object ):
> object[ "n" ]+= 1
> def counter_value( object ):
> return object[ "n" ]
>
> counter_class =( counter_create, counter_increment, counter_value )
>
> def inherit_from( class_, target ):
> class_[ 0 ]( target )
> for method in class_[ 1: ]:
> target[ method.__name__ ]= partial( method, target )
>
> car = dict()
>
> inherit_from( counter_class, car )
>
> print( car[ "counter_value" ]() )
> car[ "counter_increment" ]()
> print( car[ "counter_value" ]() )
>
>   . The "create" part is simplified. I just wanted to show how
>   to make methods like "counter_increment" act on the object
>   that inherited them using "partial".

I really liked this idea.  I organized it my way.  Have a look.  (Thank
you for the lecture!)

--8<---cut here---start->8---
from functools import partial

def Counter(name = None):
  o = {"name": name if name else "untitled", "n": 0}
  def inc(o):
o["n"] += 1
return o
  o["inc"] = inc
  def get(o):
return o["n"]
  o["get"] = get
  return o

def Car(maker):
  o = {"maker": maker, "state": "off"}
  inherit_from(Counter, o)
  def on(o):
if o["is_on"]():
  raise ValueError("oh, no: car is already on")
o["inc"]()
print(f"{o['maker']}: bruum!")
o["state"] = "on"
return o
  o["on"] = partial(on, o)
  def off(o):
if o["is_off"]():
  raise ValueError("oh, no: car is already off")
print(f"{o['maker']}: spat!")
o["state"] = "off"
return o
  o["off"] = partial(off, o)
  def is_on(o):
return o["state"] == "on"
  o["is_on"] = partial(is_on, o)
  def is_off(o):
return o["state"] == "off"
  o["is_off"] = partial(is_off, o)
  return o

def main():
  car1 = Car("Ford")
  car2 = Car("VW")
  for i in range(5):
car1["on"](); car1["off"]()
  for i in range(3):
car2["on"](); car2["off"]()
  print(f"car turned on = {car1['get']()} ({car1['maker']})")
  print(f"car turned on = {car2['get']()} ({car2['maker']})")

## (*) How to inherit the methods from a class
## 
def inherit_from(C, target):
  o = C()
  for k, v in o.items():
if callable(v):
  target[k] = partial(v, target)
else:
  target[k] = v
--8<---cut here---end--->8---
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Question about learning Python

2022-09-09 Thread Meredith Montgomery
 writes:

> Maybe we should ask WHY the person asking the question about how to learn a
> computer language called Python is pairing it with the idea of whether to
> also learn C.

Excellent point!
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Question about learning Python

2022-09-07 Thread Meredith Montgomery
Maruful Islam  writes:

> I want to start learning python. I have a question about learning python. 
>
> Is learning C essential or not for learning python?

Surely not necessary.  There's a generous recent thread about books on
Python.  Have a look at it.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: any author you find very good has written a book on Python?

2022-09-07 Thread Meredith Montgomery
jkn  writes:

> On Tuesday, September 6, 2022 at 4:36:38 PM UTC+1, Meredith Montgomery wrote:
>> Paul Rubin  writes: 
>> 
>> > Meredith Montgomery  writes: 
>> >> So that's my request --- any author you find very good has written a 
>> >> book on Python? 
>> > 
>> > The ones by David Beazley are great. Same with his non-book writings 
>> > about Python. See: http://dabeaz.com/
>> Distilled Python is looking really nice, actually. It seems so concise, 
>> so it looks like a really nice first read. Thank you for the 
>> recommendation.
>
> I concur with Paul's general recommendation of David Beazley's work.
> I bought a copy of Python Distilled recently, having 'grown up' with
> editions of his earlier 'Python Essential Reference', going back to
> the first edition (Python 1.5?)
>
> I confess to being slightly disappointed with 'Python Distilled', but
> I was probably expecting something that I shouldn't have. It is
> basically a relatively fast-paced introduction to 'modern' python,
> stripping down some of the fine detail that the 'Essential Reference'
> books leave in.
>
> I am not 100% sure how useful it would be for relative beginners; it
> depends what you are looking for. As a reference to functions and
> library usage etc., the essential reference books are (still) great,
> and cheap via eBay. As a stepping stone from 'fluent beginner', it
> might well be perfect. As a hand-holding learning guide, maybe not so
> great.
>
> I'm by no means trying to diss Beazley's work, I think it is great;
> just trying to indicate what you get for your money, and maybe the
> target audience.

You got a point.  It's so concise that maybe it's too concise for a
beginner.  But I will take my chances.  I liked it.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: on str.format and f-strings

2022-09-06 Thread Meredith Montgomery
Chris Angelico  writes:

> On Wed, 7 Sept 2022 at 03:52, Meredith Montgomery  
> wrote:
>>
>> It seems to me that str.format is not completely made obsolete by the
>> f-strings that appeared in Python 3.6.  But I'm not thinking that this
>> was the objective of the introduction of f-strings: the PEP at
>>
>>   https://peps.python.org/pep-0498/#id11
>>
>> says so explicitly.
>
> Precisely. It was never meant to obsolete str.format, and it does not.
>
>> My question is whether f-strings can do the
>> following nice thing with dictionaries that str.format can do:
>>
>> --8<---cut here---start->8---
>> def f():
>>   d = { "name": "Meredith", "email": "mmontgom...@levado.to" }
>>   return "The name is {name} and the email is {email}".format(**d)
>> --8<---cut here---end--->8---
>>
>> Is there a way to do this with f-strings?
>
> No. That's not their job. That's str.format's job.

Chris!  So good to see you around here again.  Thank you so much for
your input on this. 
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: any author you find very good has written a book on Python?

2022-09-06 Thread Meredith Montgomery
Paul Rubin  writes:

> Meredith Montgomery  writes:
>> So that's my request --- any author you find very good has written a
>> book on Python?
>
> The ones by David Beazley are great.  Same with his non-book writings
> about Python.  See: http://dabeaz.com/

Distilled Python is looking really nice, actually.  It seems so concise,
so it looks like a really nice first read.  Thank you for the
recommendation.
-- 
https://mail.python.org/mailman/listinfo/python-list


any author you find very good has written a book on Python?

2022-09-06 Thread Meredith Montgomery
I never read a book on Python.  I'm looking for a good one now.  I just
searched the web for names such as Charles Petzold, but it looks like he
never wrote a book on Python.  I also searched for Peter Seibel, but he
also never did.  I also tried to search for Richard Heathfield.  (I took
a look at his ``C Unleashed'' once and I liked what I saw.)  This is how
I search for books --- I go through the authors first.  Charles Petzold,
for instance, anything he writes is worth reading it.  (Have you given
his Annotated Turing a shot?  It's a very nice read.)

So that's my request --- any author you find very good has written a
book on Python?

It could be for in a certain specific context.  For instance, I also
searched for Hadley Wickham in the hope that he could have written a
data-science-type of book using Python.  I like his writing a lot, but
he also only seems to have written only for the R language.

Thank you!
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: on the importance of exceptions

2022-09-06 Thread Meredith Montgomery
Meredith Montgomery  writes:

> I'm trying to show people that exceptions are a very nice thing to have
> when it comes to detecting when something went awry somewhere.  I'd like
> a real-world case, though.  

Here's my contribution.  I want to handle all errors in main() and the
real job is done in does_a_job(), which, in turns, needs to delegate
tasks to those other procedures that fail sometimes.  

It's does_a_job() that /must/ distinguish the error codes because errors
come in as False from both opens_file() and reads_file().  So the checks
must be done both in does_a_job() and in main().  (We also notice that
does_a_job() has a return-type that's a union (sometimes an integer,
sometimes a string), which makes distinguishing error code and success a
bit harder.)

--8<---cut here---start->8---
from random import randint

def main():
  r, data = does_a_job()
  if r < 0:
if r == -1:
  print("Fatal. Could not open file.")
  return None
if r == -2:
  print("Fatal. Could not read file")
  return None
  print(f"Great! We got the data: ``{r}''.")

def does_a_job():
  okay = opens_file()
  if not okay:
return -1
  okay, data = reads_file()
  if not okay:
return -2
  closes_file()
  return data

def open_file(): # Opens okay with probability 80%
  return randint(1,10) <= 8

def read_file(): # Reads okay with probability 50%
  return randint(1,10) <= 5, "data I am"

def closes_file():  # Works with probability 1
  return True
--8<---cut here---end--->8---

If we could give the program a final destination at does_a_job(), the
job would be easier.  But all we want to do in does_a_job() is to
propagate the error conditions upwards to main() to really decide what
to do.  Exceptions lets us do that with a cleaner version.

--8<---cut here---start->8---
from random import randint

def main():
  try:
data = does_a_job()
  except FileNotFoundError:
print("Fatal. Could not open file.")
  except MemoryError:
print("Fatal. Could not read file")
  else:
print(f"Great! We got the data: ``{data}''.")

def does_a_job():
  open_file()
  data = reads_file()
  close_file()
  return data

def open_file(): # Opens okay with probability 80%
  if randint(1,10) <= 8:
return True
  raise FileNotFoundError("Sorry: the file system is /so/ busy right now.")

def reads_file(): # Reads okay with probability 50%
  if randint(1,10) <= 5:
return "data I am"
  raise MemoryError("Sorry: not enough memory for /all/ this data.")

def close_file():  # Works with probability 1
  return True
--8<---cut here---end--->8---
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: on str.format and f-strings

2022-09-06 Thread Meredith Montgomery
Julio Di Egidio  writes:

> On Tuesday, 6 September 2022 at 01:03:02 UTC+2, Meredith Montgomery wrote:
>> Julio Di Egidio  writes: 
>> > On Monday, 5 September 2022 at 22:18:58 UTC+2, Meredith Montgomery wrote: 
>> >> r...@zedat.fu-berlin.de (Stefan Ram) writes: 
>> > 
>> >> > , but with the spaces removed, it's even one character 
>> >> > shorter than the format expression: 
>> >> > 
>> >> > eval('f"The name is {name} and the email is {email}"',d) 
>> >> > "The name is {name} and the email is {email}".format(**d) 
>> >> 
>> >> Lol. That's brilliant! Thanks very much! 
>> > 
>> > Calling eval for that is like shooting a fly with a cannon.
>> 
>> Indeed! But we're not looking for production-quality code. Just an 
>> extreme way to satisfy a silly requirement.
>
> Indeed, as far as programming goes, even the premise is
> totally nonsensical.  Maybe you too better go to the pub?

It surely isn't precise, but Stefan Ram caught my meaning.  It's hard to
be precise.  I wanted to avoid having to write things like d['key'].
Stefam Ram provided a solution.  I did not care whether it was something
sensible to do in Python from a serious-programming perspective.  Thank
you for thoughts anyhow.  I appreciate it.
-- 
https://mail.python.org/mailman/listinfo/python-list


on the importance of exceptions

2022-09-06 Thread Meredith Montgomery
I'm trying to show people that exceptions are a very nice thing to have
when it comes to detecting when something went awry somewhere.  I'd like
a real-world case, though.  

Here's what I'm sort of coming up with --- given my limited experience
and imagination.  Below, you have f calling g caling h calling j which
returns True or False based on a random thing.  (This simulates a task
that sometimes succeeds and sometimes fails.)  If while at f() I want to
know what happened at j(), I'm going to have to propagate that
information upwards through the execution stack.  I can't do that right
now: I'd have to change f, g and h.

--8<---cut here---start->8---
from random import randint
  
def f():
  g()

def g():
  h()

def h():
  if j():
print("I got a 2.")
  else:
print("I got a 1.")

def j():
  return randint(1,2) == 2
--8<---cut here---end--->8---

If instead of that, j() would be raising an exception when it fails,
then all I only need to change f() to know what happens.

I could replace j's test with opening a file, say.  That would improve
it a little.  I'm sure you guys know excellent cases to show.  Would you
be so kind to share anything you might have in mind?
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: on str.format and f-strings

2022-09-06 Thread Meredith Montgomery
Julio Di Egidio  writes:

> On Monday, 5 September 2022 at 22:18:58 UTC+2, Meredith Montgomery wrote:
>> r...@zedat.fu-berlin.de (Stefan Ram) writes: 
>
>> > , but with the spaces removed, it's even one character 
>> > shorter than the format expression: 
>> > 
>> > eval('f"The name is {name} and the email is {email}"',d)
>> > "The name is {name} and the email is {email}".format(**d) 
>> 
>> Lol. That's brilliant! Thanks very much!
>
> Calling eval for that is like shooting a fly with a cannon.

Indeed!  But we're not looking for production-quality code.  Just an
extreme way to satisfy a silly requirement.

> Besides, this one is even shorter:
>
> f"The name is {d['name']} and the email is {d['email']}"

This doesn't quite satisfy the requeriments.  We're trying to specify
only the keys, not the dictionary.  (But maybe the requirements did not
say that explicitly.  I'd have to look it up again --- it's been
snipped.  It's not important.  Thanks much for your thoughts!)
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: on str.format and f-strings

2022-09-06 Thread Meredith Montgomery
r...@zedat.fu-berlin.de (Stefan Ram) writes:

> Meredith Montgomery  writes:
> ...
>>  d = { "name": "Meredith", "email": "mmontgom...@levado.to" }
>>  return "The name is {name} and the email is {email}".format(**d)
>>--8<---cut here---end--->8---
>>Is there a way to do this with f-strings?
>
>   I cannot think of anything shorter now than:
>
> eval( 'f"The name is {name} and the email is {email}"', d )
>
>   , but with the spaces removed, it's even one character
>   shorter than the format expression:
>
> eval('f"The name is {name} and the email is {email}"',d)
> "The name is {name} and the email is {email}".format(**d)
>
>   . 

Lol.  That's brilliant!  Thanks very much!
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: on implementing a toy oop-system

2022-09-06 Thread Meredith Montgomery
r...@zedat.fu-berlin.de (Stefan Ram) writes:

> Meredith Montgomery  writes:
>>Is that at all possible somehow?  Alternatively, how would you do your
>>toy oop-system?
>
>   Maybe something along those lines:
>
> from functools import partial
>
> def counter_create( object ):
> object[ "n" ]= 0
> def counter_increment( object ):
> object[ "n" ]+= 1
> def counter_value( object ):
> return object[ "n" ]
>
> counter_class =( counter_create, counter_increment, counter_value )
>
> def inherit_from( class_, target ):
> class_[ 0 ]( target )
> for method in class_[ 1: ]:
> target[ method.__name__ ]= partial( method, target )
>
> car = dict()
>
> inherit_from( counter_class, car )
>
> print( car[ "counter_value" ]() )
> car[ "counter_increment" ]()
> print( car[ "counter_value" ]() )
>
>   . The "create" part is simplified. I just wanted to show how
>   to make methods like "counter_increment" act on the object
>   that inherited them using "partial".

That's simple and interesting.  I'll study your more elaborate approach
next, but I like what I see already.  Thank you so much.
-- 
https://mail.python.org/mailman/listinfo/python-list


on str.format and f-strings

2022-09-06 Thread Meredith Montgomery
It seems to me that str.format is not completely made obsolete by the
f-strings that appeared in Python 3.6.  But I'm not thinking that this
was the objective of the introduction of f-strings: the PEP at 

  https://peps.python.org/pep-0498/#id11

says so explicitly.  My question is whether f-strings can do the
following nice thing with dictionaries that str.format can do:

--8<---cut here---start->8---
def f():
  d = { "name": "Meredith", "email": "mmontgom...@levado.to" }
  return "The name is {name} and the email is {email}".format(**d)
--8<---cut here---end--->8---

Is there a way to do this with f-strings?
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: on GNU EMACS's python-mode, loading entire buffer

2022-09-06 Thread Meredith Montgomery
Meredith Montgomery  writes:

> Meredith Montgomery  writes:
>
> [...]
>
>> I would also be interested in a command that restarts the REPL afresh
>> and reloads my buffer --- sort of like keyboard's [F5] of the IDLE.
>
> A partial solution for this is the following procedure.
>
> (defun python-revert-and-send-buffer-to-repl ()
>   "Revert current buffer and sends it to the Python REPL."
>   (interactive)
>   (revert-buffer "ignore-auto-no" "no-confirm")
>   (python-shell-send-buffer))
>
> We can map this to the F5-key and that improves things.  But a restart
> of the REPL would be the ideal.  (Sometimes we really want to start
> afresh.  Sometimes.  Most often we don't want that.)

It's not easy to restart the REPL.  You can send "quit()" to it and
invoke run-python again interactively by typing out one command after
another, but if you write a procedure such as this one below, it doesn't
work: it gives me the impression that there's a timing issue, that is,
perhaps the procedure is too fast and something happens before it
should.

(defun python-save-send-buffer-to-repl ()
  (interactive)
  (save-buffer)
  (python-shell-send-string "quit()")
  (run-python)
  (python-shell-send-buffer)
  (python-shell-switch-to-shell))
-- 
https://mail.python.org/mailman/listinfo/python-list


on implementing a toy oop-system

2022-09-06 Thread Meredith Montgomery
Just for investigation sake, I'm trying to simulate OO-inheritance.  

(*) What did I do?  

I decided that objects would be dictionaries and methods would be
procedures stored in the object.  A class is just a procedure that
creates such object-dictionary.  So far so good.  Trouble arrived when I
decided to have inheritance.  The problem might related to the
lexical-nature of closures, but I'm not sure.

(*) A problem 

Say I have a Counter-creating object procedure and a Car-creating object
procedure.  Cars want to track how many times they park, so they inherit
a counter.  

--8<---cut here---start->8---
def Car(maker = None, color = None):
  o = inherit(Object(), Counter())
  o["maker"] = maker
  o["color"] = color
  o["speed"] = 0
--8<---cut here---end--->8---

What Object() does is just to return a dictionary.  What inherit() does
is just to merge the two dictionaries into a single one (to be used by
the Car procedure).

This didn't come out as I expected, though.  Let me show you
step-by-step where the problem is.  First, here's a counter in action.

>>> c1 = Counter()
>>> c1["inc"]()["inc"]()
{'id': .id at 0x016547C648B0>, 'n': 2, [...]}
>>> c1["n"]
2

That's good and expected: I incremented it twice.  But look what happens
with a Car's counter.

>>> c = Car()
>>> c = Car()
>>> c
{'id': .id at 0x016547C64B80>, 'n': 0,
  'inc': .inc at 0x016547C64C10>, 'dec':
  .dec at 0x016547C64CA0>, 'maker': None,
  'color': None, 'speed': 0, 'accelerate': .accelerate at 0x016547C64AF0>, 'park': .park at 0x016547C64D30>}

>>> c["inc"]()
{'id': .id at 0x016547C64B80>, 'n': 1,
  'inc': .inc at 0x016547C64C10>, 'dec':
  .dec at 0x016547C64CA0>}

We can see something got incremented!  But... 

>>> c["n"]
0

Indeed, what got incremented is the dictionary attached to the /inc/
procedure of the Counter closure, so it's that dictionary that's being
mutated.  My /inherit/ procedure is not able to bring that procedure
into the Car dictionary.  

Is that at all possible somehow?  Alternatively, how would you do your
toy oop-system?

(*) Full code below

from random import random

def Object():
  myid = random()
  def id():
return myid
  return {
"id": id
  }

def inherit(o, parentObject):
  o.update(parentObject)
  return o

def Counter(begin_at = 0):
  o = Object()
  o["n"] = begin_at
  def inc():
nonlocal o
o["n"] += 1
return o
  o["inc"] = inc
  def dec():
nonlocal o
o["n"] -= 1
return o
  o["dec"] = dec
  return o

def Car(maker = None, color = None):
  o = inherit(Object(), Counter())
  o["maker"] = maker
  o["color"] = color
  o["speed"] = 0
  def accelerate(speed):
nonlocal o
print(f"Car-{o['id']()}: accelerating to {speed}...")
o["speed"] = speed
return o
  o["accelerate"] = accelerate
  def park():
nonlocal o
o["speed"] = 0
o["parked"] = True
o["inc"]()
print(f"Car-{o['id']()}: parked! ({o['n']} times)")
return o
  o["park"] = park
  return o

def tests():
  c1 = Counter()
  c2 = Counter(100)
  c1["inc"]()["inc"]()
  c2["dec"]()["dec"]()["dec"]()
  print("c1 is 2:", c1["n"])
  print("c2 is 97:", c2["n"])
  car1 = Car("VW", "Red")
  car1["accelerate"](100)
  print("speed is 100:", car1["speed"])
  car2 = Car("Ford", "Black")
  car2["accelerate"](120)["park"]()
  car2["accelerate"](50)["park"]()
  print("has parked 2 times:", car2["n"])
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: on GNU EMACS's python-mode, loading entire buffer

2022-08-31 Thread Meredith Montgomery
Meredith Montgomery  writes:

[...]

> I would also be interested in a command that restarts the REPL afresh
> and reloads my buffer --- sort of like keyboard's [F5] of the IDLE.

A partial solution for this is the following procedure.

--8<---cut here---start->8---
(defun python-revert-and-send-buffer-to-repl ()
  "Revert current buffer and sends it to the Python REPL."
  (interactive)
  (revert-buffer "ignore-auto-no" "no-confirm")
  (python-shell-send-buffer))
--8<---cut here---end--->8---

We can map this to the F5-key and that improves things.  But a restart
of the REPL would be the ideal.  (Sometimes we really want to start
afresh.  Sometimes.  Most often we don't want that.)
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Coffee

2022-08-31 Thread Meredith Montgomery
"Michael F. Stemper"  writes:

> On 29/08/2022 07.16, Stefan Ram wrote:
>> |Python's obviously a great tool for all kinds of programming things,
>> |and I would say if you're only gonna use one programming
>> |language in your live, Python will probably the right one.
>> Brian Kernighan
>>I transcribed this from the recent video
>>"Coffee with Brian Kernighan".
>
> For those who'd like to see the whole chat:
> 

So kind of you!  Thank you!
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: on GNU EMACS's python-mode, loading entire buffer

2022-08-29 Thread Meredith Montgomery
Paul Rubin  writes:

> Meredith Montgomery  writes:
>> Now in 27.1, things are different.  I say C-c C-c and it tells me to
>> start the process with C-c C-p.  I mean --- is that the most polite
>> thing to do?  I feel like it's telling me --- go send this buffer
>> yourself!
>
> Hmm, I noticed that too, but I thought it was a change in python-mode
> itself.  I just got used to it.  I didn't bother trying to chase it down.

These little conveniences are so important. :-)

> To start a new process, try C-u C-c C-p .

Oh, thank you!
-- 
https://mail.python.org/mailman/listinfo/python-list


on GNU EMACS's python-mode, loading entire buffer

2022-08-29 Thread Meredith Montgomery
Perhaps this isn't the right newsgroup, but I kinda feel I will find
more GNU EMACS users running the native python-mode here than in GNU
EMACS newsgroups.  Not every GNU EMACS user cares about Python.
(Right?)

A sort of a complaint is that when I used to run GNU EMACS 24.3.1, I'd
open a file.py and simply say C-c C-c and it would ask me if I wanted a
dedicated process, load a REPL load my entire buffer.

Now in 27.1, things are different.  I say C-c C-c and it tells me to
start the process with C-c C-p.  I mean --- is that the most polite
thing to do?  I feel like it's telling me --- go send this buffer
yourself!

I also don't know how to start a dedicated process.  (Sometimes I want
two REPLs.  You know, you can get never get enough.)

I would bet all of this and more is available, but I don't even know
which book to read.  Would you point me in the right direction?

I would also be interested in a command that restarts the REPL afresh
and reloads my buffer --- sort of like keyboard's [F5] of the IDLE.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Coffee

2022-08-29 Thread Meredith Montgomery
r...@zedat.fu-berlin.de (Stefan Ram) writes:

> |Python's obviously a great tool for all kinds of programming things,
> |and I would say if you're only gonna use one programming
> |language in your live, Python will probably the right one.
> Brian Kernighan
>
>   I transcribed this from the recent video 
>   "Coffee with Brian Kernighan".

Sounds reasonable.  I have been learning Python bit by bit simply
because there seems to be no other way to talk to university people.
But somehow I am so in love with Lisp that it makes me sort of blind
because sometimes I feel more productive in Python simply because I'm
always using it.  When I can write Lisp, I do it, but often I feel like
I'm a role-playing TCP Slow Start or something like that.
-- 
https://mail.python.org/mailman/listinfo/python-list


on a statement followed by an expression

2022-06-04 Thread Meredith Montgomery
(*) Question

How can I, in a single line, write a statement followed by an
expression?  For example, if /d/ is a dicionary, how can I write

   d["key"] = value # and somehow making this line end up with d

(*) Where does the question come from?

>From the following experiment-exercise.

(*) Introduction

Here's a gentle way to consome records /rs/, each of which represents a
robbery, say, and produce a dictionary containing a count of each zip
code.

--8<---cut here---start->8---
def zip(r):
  return r[0]

def roberry_per_zip(rs):
  d = {}
  for r in rs:
d[zip(r)] = dict.get(d, zip(r), 0) + 1
  return d
--8<---cut here---end--->8---

Now I'd like to compare the code with a version that uses reduce.  Let
me please write my own reduce function for completeness and clarity ---
I suppose.  The code is still pretty clear.

--8<---cut here---start->8---
def my_reduce(it, f, init):
  r = init
  for e in it:
r = f(r, e)
  return r

def count_in(d, r):
  d[zip(r)] = dict.get(d, zip(r), 0) + 1
  return d

def roberry_via_reduce(rs):
  return my_reduce(rs, count_in, {})
--8<---cut here---end--->8---

It's not clear, though, how to write such a procedure using a lambda
expression in place of count_in.  That's because we must return a
dicionary and statements are not expressions.

How can I execute a statement followed by a value in a single line?

def roberry_via_reduce(rs):
  return my_reduce(rs, lambda d, r: ``increment and return d'', {})

I don't know how to write

  ``increment and return d''

I'm just curious.  Thank you.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: how to distinguish return from print()

2022-05-25 Thread Meredith Montgomery
r...@zedat.fu-berlin.de (Stefan Ram) writes:

> Meredith Montgomery  writes:
> ...
>>def f(x):
>>return x + 1
> ...
>>>>> print("hello")
>
>   To me, what would make more sense would be:
>
>   Teacher:
>
> |>>> def r():
> |... return 7
> |...
> |>>> def p():
> |... print( 7 )
> |...
> |>>> r()
> |7
> |>>> p()
> |7
>
>   Pupil:
>
>   That was a very instructive example, teacher. Thank you!
>   But could you also show us some context where the calls 
>   to p and r show some difference?
>
>   Teacher:
>   
> |>>> print( r() )
> |7
> |>>> print( p() )
> |7
> |None
>
> |>>> x = r()
> |>>> x = p()
> |7
>
>   Pupil:
>
>   Now I'm confused. What's "None"?
>
>   Teacher:
>
>   ...

I did do this too.  I think that was helpful.  I told them --- a print
doesn't let you easily ``capture'' a value calculated in a procedure.
Thank you!
-- 
https://mail.python.org/mailman/listinfo/python-list


how to distinguish return from print()

2022-05-22 Thread Meredith Montgomery
Students seeing a programming language for the first time and using
Python's REPL for the first time have asked me what is the difference
between a return statement and a print() call.  They got a point.

--8<---cut here---start->8---
def f(x):
return x + 1

>>> f(1)
2

>>> print("hello")
hello
--8<---cut here---end--->8---

There's no visual difference.

(*) My answer

The way I know how to answer the difference there is to explain how a
typical computer system works, which is a more or less long answer.  A
return statement is usually just another CPU instruction, while /print/
is a procedure that must eventually run a CPU instruction that
interrupts the CPU, passes control to the operating system which, in
turn, talks to the i/o devices in question (the video, for example) to
get the job finally done.  (We may expect a print() call, therefore, to
be usually much slower than a return statement.)

I also explain that if, say, math.sin(x) is going to print a message to
the screen...

>>> sin(pi/2)
calculating your sine... hang on...
1.0

... I might as well not use it because this will get mixed with my own
print() statements and I'll be surprised about who added that
calculating-your-sine message.  So adding print() statements to
procedures is, in practice, rare.  (To them it's the most typical
operation because they never do any serious programming and they learn
their first steps out on the Internet.  In my course, print() is only
allowed after at 10th homework, after 10 weeks.)

I also explain that if f(x) prints its answer to the screen instead of
returning it, it will be harder to capture the answer in a variable.
For example,

>>> def f(x):
...   print(x + 1)
... 
>>> f(1)
2
>>> y = f(1)
2
>>> y
>>> 
>>> y == None
True

I take this opportunity to remark that Python seems to always returns
something, even if it's the ``special'' value None.

(*) The REPL

I also explain that the REPL is just another program.  Its purpose
happens to be to [r]ead, [e]val, [p]rint and [l]oop, which is why we get
to see return values printed to the screen.

(*) My insatisfaction

I wish I had simpler answers.  Explaining about operating systems, the
CPU, system calls...  I wish there was an easier way to clarify such
things.  You guys might have ideas.

I'm thinking about showing them the code for the simplest toy-REPL so
that we can perhaps demystify the REPL.  I think they see the REPL as
part of the programming language, so I think it might help to figure out
that nothing happens unless code is written to make it happen.  If
something gets displayed on the screen, there is definitely some i/o
going on and print() is the one initiating that i/o, while return is
just another ``arithmetic'' operation such as addition.

Thank you so much.
-- 
https://mail.python.org/mailman/listinfo/python-list