Re: Code improvement question

2023-11-16 Thread Mike Dewhirst via Python-list

On 16/11/2023 9:34 am, Rimu Atkinson via Python-list wrote:





Why don't you use re.findall?

re.findall(r'\b[0-9]{2,7}-[0-9]{2}-[0-9]{2}\b', txt)


I think I can see what you did there but it won't make sense to me - 
or whoever looks at the code - in future.


That answers your specific question. However, I am in awe of people 
who can just "do" regular expressions and I thank you very much for 
what would have been a monumental effort had I tried it.


I feel the same way about regex. If I can find a way to write 
something without regex I very much prefer to as regex usually adds 
complexity and hurts readability.


You might find https://regex101.com/ to be useful for testing your 
regex. You can enter in sample data and see if it matches.


If I understood what your regex was trying to do I might be able to 
suggest some python to do the same thing. Is it just removing numbers 
from text?


The for loop, "for bit in bits" etc, could be written as a list 
comprehension.


pieces = [bit if len(bit) > 6 else "" for bit in bits]

For devs familiar with other languages but new to Python this will 
look like gibberish so arguably the original for loop is clearer, 
depending on your team.


It's worth making the effort to get into list comprehensions though 
because they're awesome.


I agree qualitatively 100% but quantitively perhaps I agree 80% where 
readability is easy.


I think that's what you are saying anyway.








That little re.sub() came from ChatGPT and I can understand it 
without too much effort because it came documented


I suppose ChatGPT is the answer to this thread. Or everything. Or 
will be.


I am doubtful. We'll see!

R





--
Signed email is an absolute defence against phishing. This email has
been signed with my private key. If you import my public key you can
automatically decrypt my signature and be sure it came from me. Your
email software can handle signing.



OpenPGP_signature.asc
Description: OpenPGP digital signature
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Code improvement question

2023-11-16 Thread Rimu Atkinson via Python-list






Why don't you use re.findall?

re.findall(r'\b[0-9]{2,7}-[0-9]{2}-[0-9]{2}\b', txt)


I think I can see what you did there but it won't make sense to me - or 
whoever looks at the code - in future.


That answers your specific question. However, I am in awe of people who 
can just "do" regular expressions and I thank you very much for what 
would have been a monumental effort had I tried it.


I feel the same way about regex. If I can find a way to write something 
without regex I very much prefer to as regex usually adds complexity and 
hurts readability.


You might find https://regex101.com/ to be useful for testing your 
regex. You can enter in sample data and see if it matches.


If I understood what your regex was trying to do I might be able to 
suggest some python to do the same thing. Is it just removing numbers 
from text?


The for loop, "for bit in bits" etc, could be written as a list 
comprehension.


pieces = [bit if len(bit) > 6 else "" for bit in bits]

For devs familiar with other languages but new to Python this will look 
like gibberish so arguably the original for loop is clearer, depending 
on your team.


It's worth making the effort to get into list comprehensions though 
because they're awesome.






That little re.sub() came from ChatGPT and I can understand it without 
too much effort because it came documented


I suppose ChatGPT is the answer to this thread. Or everything. Or will be.


I am doubtful. We'll see!

R


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


Re: Code improvement question

2023-11-16 Thread MRAB via Python-list

On 2023-11-17 01:15, Mike Dewhirst via Python-list wrote:

On 15/11/2023 3:08 pm, MRAB via Python-list wrote:

On 2023-11-15 03:41, Mike Dewhirst via Python-list wrote:

On 15/11/2023 10:25 am, MRAB via Python-list wrote:

On 2023-11-14 23:14, Mike Dewhirst via Python-list wrote:
I'd like to improve the code below, which works. It feels clunky to 
me.


I need to clean up user-uploaded files the size of which I don't 
know in

advance.

After cleaning they might be as big as 1Mb but that would be super 
rare.

Perhaps only for testing.

I'm extracting CAS numbers and here is the pattern xx-xx-x up to
xxx-xx-x eg., 1012300-77-4

def remove_alpha(txt):

      """  r'[^0-9\- ]':

      [^...]: Match any character that is not in the specified set.

      0-9: Match any digit.

      \: Escape character.

      -: Match a hyphen.

      Space: Match a space.

      """

  cleaned_txt = re.sub(r'[^0-9\- ]', '', txt)

      bits = cleaned_txt.split()

      pieces = []

      for bit in bits:

      # minimum size of a CAS number is 7 so drop smaller 
clumps of digits


      pieces.append(bit if len(bit) > 6 else "")

      return " ".join(pieces)


Many thanks for any hints


Why don't you use re.findall?

re.findall(r'\b[0-9]{2,7}-[0-9]{2}-[0-9]{2}\b', txt)


I think I can see what you did there but it won't make sense to me - or
whoever looks at the code - in future.

That answers your specific question. However, I am in awe of people who
can just "do" regular expressions and I thank you very much for what
would have been a monumental effort had I tried it.

That little re.sub() came from ChatGPT and I can understand it without
too much effort because it came documented

I suppose ChatGPT is the answer to this thread. Or everything. Or 
will be.



\b  Word boundary
[0-9]{2,7}  2..7 digits
-   "-"
[0-9]{2}    2 digits
-   "-"
[0-9]{2}    2 digits
\b  Word boundary

The "word boundary" thing is to stop it matching where there are 
letters or digits right next to the digits.


For example, if the text contained, say, "123456789-12-1234", you 
wouldn't want it to match because there are more than 7 digits at the 
start and more than 2 digits at the end.



Thanks

I know I should invest some brainspace in re. Many years ago at a Perl
conferenceI did buy a coffee mug completely covered with a regex cheat
sheet. It currently holds pens and pencils on my desk. And spiders now I
look closely!

Then I took up Python and re is different.

Maybe I'll have another look ...

The patterns themselves aren't that different; Perl's just has more 
features than the re module's.

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


Re: Code improvement question

2023-11-16 Thread Mike Dewhirst via Python-list

On 15/11/2023 3:08 pm, MRAB via Python-list wrote:

On 2023-11-15 03:41, Mike Dewhirst via Python-list wrote:

On 15/11/2023 10:25 am, MRAB via Python-list wrote:

On 2023-11-14 23:14, Mike Dewhirst via Python-list wrote:
I'd like to improve the code below, which works. It feels clunky to 
me.


I need to clean up user-uploaded files the size of which I don't 
know in

advance.

After cleaning they might be as big as 1Mb but that would be super 
rare.

Perhaps only for testing.

I'm extracting CAS numbers and here is the pattern xx-xx-x up to
xxx-xx-x eg., 1012300-77-4

def remove_alpha(txt):

      """  r'[^0-9\- ]':

      [^...]: Match any character that is not in the specified set.

      0-9: Match any digit.

      \: Escape character.

      -: Match a hyphen.

      Space: Match a space.

      """

  cleaned_txt = re.sub(r'[^0-9\- ]', '', txt)

      bits = cleaned_txt.split()

      pieces = []

      for bit in bits:

      # minimum size of a CAS number is 7 so drop smaller 
clumps of digits


      pieces.append(bit if len(bit) > 6 else "")

      return " ".join(pieces)


Many thanks for any hints


Why don't you use re.findall?

re.findall(r'\b[0-9]{2,7}-[0-9]{2}-[0-9]{2}\b', txt)


I think I can see what you did there but it won't make sense to me - or
whoever looks at the code - in future.

That answers your specific question. However, I am in awe of people who
can just "do" regular expressions and I thank you very much for what
would have been a monumental effort had I tried it.

That little re.sub() came from ChatGPT and I can understand it without
too much effort because it came documented

I suppose ChatGPT is the answer to this thread. Or everything. Or 
will be.



\b  Word boundary
[0-9]{2,7}  2..7 digits
-   "-"
[0-9]{2}    2 digits
-   "-"
[0-9]{2}    2 digits
\b  Word boundary

The "word boundary" thing is to stop it matching where there are 
letters or digits right next to the digits.


For example, if the text contained, say, "123456789-12-1234", you 
wouldn't want it to match because there are more than 7 digits at the 
start and more than 2 digits at the end.



Thanks

I know I should invest some brainspace in re. Many years ago at a Perl 
conferenceI did buy a coffee mug completely covered with a regex cheat 
sheet. It currently holds pens and pencils on my desk. And spiders now I 
look closely!


Then I took up Python and re is different.

Maybe I'll have another look ...

Cheers

Mike

--
Signed email is an absolute defence against phishing. This email has
been signed with my private key. If you import my public key you can
automatically decrypt my signature and be sure it came from me. Your
email software can handle signing.



OpenPGP_signature.asc
Description: OpenPGP digital signature
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: __set_name__ equivalent for instance

2023-11-16 Thread Dom Grigonis via Python-list
Thank you.

> On 16 Nov 2023, at 21:30, Dieter Maurer  wrote:
> 
> Dom Grigonis wrote at 2023-11-16 21:11 +0200:
>> ...
>>> On 16 Nov 2023, at 21:00, Dieter Maurer  wrote:
>>> ...
>>> Methods are not bound during instance creation, they are bound during
>>> access.
>> 
>> Good to know. What is the criteria for binding then? Does it check if its 
>> type is `vanilla` function? If yes, is there any way to simulate it for 
>> arbitrary object?
> 
> Attribute access (including method binding) is documented in the
> language reference.
> 
> Functions and descriptors accessed via an instance but found in a class (i.e.
> not directly in the instance) are handled specially;
> functions are bound. Other objects are returned as is.
> 
> `__getattribute__` can be used to take over control over the attribute
> access.

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


Re: __set_name__ equivalent for instance

2023-11-16 Thread Dieter Maurer via Python-list
Dom Grigonis wrote at 2023-11-16 21:11 +0200:
> ...
>> On 16 Nov 2023, at 21:00, Dieter Maurer  wrote:
>> ...
>> Methods are not bound during instance creation, they are bound during
>> access.
>
>Good to know. What is the criteria for binding then? Does it check if its type 
>is `vanilla` function? If yes, is there any way to simulate it for arbitrary 
>object?

Attribute access (including method binding) is documented in the
language reference.

Functions and descriptors accessed via an instance but found in a class (i.e.
not directly in the instance) are handled specially;
functions are bound. Other objects are returned as is.

`__getattribute__` can be used to take over control over the attribute
access.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: __set_name__ equivalent for instance

2023-11-16 Thread Dom Grigonis via Python-list



> On 16 Nov 2023, at 21:00, Dieter Maurer  wrote:
> 
> Dom Grigonis wrote at 2023-11-16 20:12 +0200:
>> What I am interested in is a callback.
>> Preferably just after methods get bound. So in `object.__new__`.
> 
>> I have done it via metaclass, but it is not ideal as there would be too much 
>> overhead.
>> 
>> I think what I am looking for is custom method binding.
> 
> Methods are not bound during instance creation, they are bound during
> access.

Good to know. What is the criteria for binding then? Does it check if its type 
is `vanilla` function? If yes, is there any way to simulate it for arbitrary 
object?

I have tried inheriting from function type, but not allowed.

> You can use descriptors to implement "custom method binding".
> 
> Descriptors are defined on the class (and do not behave as
> descriptors when defined on instances).
> Thus, you would need a metaclass or `__inist_subclass__` is you
> want your "custom method binding" globally.

Yes, I have tried that. This works well. But maybe will be useful for another 
case.

Currently, the focus is decorators that can be used on arbitrary methods. 
Needing to inherit and add metaclasses whenever I want to decorate is not an 
option.

I think I will continue with descriptor approach and am slowly finding route to 
get where I need to, but still exploring options.

Regards,
DG
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: __set_name__ equivalent for instance

2023-11-16 Thread Dieter Maurer via Python-list
Dom Grigonis wrote at 2023-11-16 20:12 +0200:
>What I am interested in is a callback.
>Preferably just after methods get bound. So in `object.__new__`.

>I have done it via metaclass, but it is not ideal as there would be too much 
>overhead.
>
>I think what I am looking for is custom method binding.

Methods are not bound during instance creation, they are bound during
access.

You can use descriptors to implement "custom method binding".

Descriptors are defined on the class (and do not behave as
descriptors when defined on instances).
Thus, you would need a metaclass or `__inist_subclass__` is you
want your "custom method binding" globally.


For many methods (but usually not the `__...__` methods),
you can take over the binding in `__new__` or `__init__`
and populate the instance with prebound methods.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: __set_name__ equivalent for instance

2023-11-16 Thread Dieter Maurer via Python-list
Dom Grigonis wrote at 2023-11-15 18:44 +0200:
>So there is a method __set_name__ which is called on class creation.
>
>The functionality that I am interested in is not retrieving name, but the fact 
>that it also receives `owner` argument.
>
>Thus, allowing simulation of bound class method.
>
>I was wandering if there is an equivalent functionality of attribute to 
>receive `instance` argument on instance creation.

As PEP 487 describes, `__set_name__` essentially targets descriptors.
It is there to inform a descriptor about the name it is used for
in a class (and the class itself). There is no other (easy) way to allow
a descriptor to learn about this name.

If a descriptor is accessed via an instance, the descriptor (protocol)
methods get the instance as parameter.
Note that descriptors are stored in the class: they must not store
instance specific information in their attributes.
Therefore, a method informing an descriptor about instance creation
would not help: it cannot do anything with it.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: __set_name__ equivalent for instance

2023-11-16 Thread Dom Grigonis via Python-list
What I am interested in is a callback.
Preferably just after methods get bound. So in `object.__new__`.

I have done it via metaclass, but it is not ideal as there would be too much 
overhead.

I think what I am looking for is custom method binding.

Regards,
DG

> On 16 Nov 2023, at 20:02, Dieter Maurer  wrote:
> 
> Dom Grigonis wrote at 2023-11-15 18:44 +0200:
>> So there is a method __set_name__ which is called on class creation.
>> 
>> The functionality that I am interested in is not retrieving name, but the 
>> fact that it also receives `owner` argument.
>> 
>> Thus, allowing simulation of bound class method.
>> 
>> I was wandering if there is an equivalent functionality of attribute to 
>> receive `instance` argument on instance creation.
> 
> As PEP 487 describes, `__set_name__` essentially targets descriptors.
> It is there to inform a descriptor about the name it is used for
> in a class (and the class itself). There is no other (easy) way to allow
> a descriptor to learn about this name.
> 
> If a descriptor is accessed via an instance, the descriptor (protocol)
> methods get the instance as parameter.
> Note that descriptors are stored in the class: they must not store
> instance specific information in their attributes.
> Therefore, a method informing an descriptor about instance creation
> would not help: it cannot do anything with it.

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


Re: Newline (NuBe Question)

2023-11-16 Thread Grizzy Adams via Python-list
Thursday, November 16, 2023  at 7:47, Thomas Passin via Python-list wrote:
Re: Newline (NuBe Question) (at least in part)

>I wrote that you don't need the "students" list, which is correct.  But 
>there could be a use for a list.  It would let you change the order in 
>which students appear in the printed output.  Knowing how to do that is 
>a useful skill.  But that should be left for a later lesson, not mixed 
>in here.

I have a vague memory of seeing sorted list somewhere ;->)
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Newline (NuBe Question)

2023-11-16 Thread Thomas Passin via Python-list

On 11/16/2023 1:19 AM, Grizzy Adams via Python-list wrote:

Wednesday, November 15, 2023  at 15:54, Thomas Passin via Python-list wrote:
Re: Newline (NuBe Question) (at least in part)


On 11/15/2023 2:04 PM, Grizzy Adams via Python-list wrote:

Wednesday, November 15, 2023  at 12:19, Pierre Fortin wrote:
Re: Newline (NuBe Question) (at least in part)
  

On Wed, 15 Nov 2023 16:51:09 - Grizzy Adams via Python-list wrote:



I don't give solutions; just a nudge...  you appear not to fully grok
"list"; your list is ONE list with no delineation between students. You
want a "list of lists"...
  

['Example High', 'Mary', 89.6, 'Pass', 'Example High', 'Matthew', 76.5, 'Fail', 
'Example High', 'Marie', 80.4, 'Fail', 'Example High', 'Manuel', 79.6, 'Fail', 
'Example High', 'Malala', 98.9, 'Pass']



Like this:
  

students = [
 ['Example High', 'Mary', 89.6, 'Pass'],
 ['Example High','Matthew', 76.5, 'Fail'],
 ['Example High', 'Marie', 80.4, 'Fail'],
 ['Example High', 'Manuel', 79.6, 'Fail'],
 ['Example High', 'Malala', 98.9, 'Pass']
]
  

for now I made a copt of code and altered to

students = []
grades = []



# In this design there is no point in the extra loop.
# also, the indentation is wrong.  Perhaps you inserted
# tabs?  Use only spaces in these posts.


I copy-pasted the code direct from IDLE, (to avoid any other typo's)


# Also you don't need the students list

for student in geographyClass:
# students.append(geographyStudent(s))

 s = geographyStudent(student)



  # for s in students:

   if s.finalGrade()>82: Result=("Pass")
   else: Result=("Fail")
   print(s.school, s.name, s.finalGrade(),Result)


I'll hive this a try (as a learning point)


I wrote that you don't need the "students" list, which is correct.  But 
there could be a use for a list.  It would let you change the order in 
which students appear in the printed output.  Knowing how to do that is 
a useful skill.  But that should be left for a later lesson, not mixed 
in here.


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


Amy known issues with tkinter /ttk on latest MacOS?

2023-11-16 Thread Alan Gauld via Python-list
I have a little app that I wrote ages ago (2015) using tkinter/ttk
and it just works. Or it did, up until the latest MacOS version upgrade
and now it has become very sporadic in response to mouse clicks.

For example I have a drop-down list and I can drop the list but
then it won't let me select an item. Or sometimes, the selected
item is highlighted but the corresponding action doesn't get fired.
It is intermittent which makes debugging it difficult. And it's
not just lists it also affects regular buttons as well.
Right clicks seem to work ok, it's only the left mouse button.
Also, I've just noticed that if I move the mouse slightly while
clicking that seems to work. There are no error/warning
messages in the Console.

I'm just wondered if this is a known issue, or just my setup?
Any suggestions welcomed.

Python version - 3.10.4
OS version - Sonoma 14.1
M1 Mac Mini, 16GB Ram

I could upgrade my Python version but I was planning on waiting
for the 3.13 release to finalize first. And I doubt if that's
the cause anyway.

-- 
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos

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