Re: A missing iterator on itertools module?

2024-03-28 Thread ast via Python-list

Le 28/03/2024 à 18:07, Stefan Ram a écrit :

ast  wrote or quoted:

s1 = "AZERTY"
s2 = "QSDFGH"
s3 = "WXCVBN"
and I need an itertor who delivers
A Q W Z S C E D C ...
I didn't found anything in itertools to do the job.
So I came up with this solution:
list(chain.from_iterable(zip("AZERTY", "QSDFGH", "WXCVBN")))


   Maybe you meant "zip(s1,s2,s3)" as the definition of s1, s2,
   and s3 otherwise would not be required. Also the "list" is not
   necessary because "chain.from_iterable" already is an iterable.
   You could also use "*" instead of "list" to print it. So,

import itertools as _itertools
s =[ "AZERTY", "QSDFGH", "WXCVBN" ]
print( *_itertools.chain.from_iterable( zip( *s )))

   . But these are only minor nitpicks; you have found a nice solution!


Why did you renamed itertools as _itertools ?
--
https://mail.python.org/mailman/listinfo/python-list


Re: A missing iterator on itertools module?

2024-03-28 Thread ast via Python-list

Le 28/03/2024 à 17:45, ast a écrit :


A Q W Z S C E D C ...


sorry
A Q W Z S X E D C


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


A missing iterator on itertools module?

2024-03-28 Thread ast via Python-list

Hello

Suppose I have these 3 strings:

s1 = "AZERTY"
s2 = "QSDFGH"
s3 = "WXCVBN"

and I need an itertor who delivers

A Q W Z S C E D C ...

I didn't found anything in itertools to do the job.

So I came up with this solution:


list(chain.from_iterable(zip("AZERTY", "QSDFGH", "WXCVBN")))

['A', 'Q', 'W', 'Z', 'S', 'X', 'E', 'D', 'C', 'R', 'F', 'V', 'T', 'G', 
'B', 'Y', 'H', 'N']


Do you havbe a neat solution ?
--
https://mail.python.org/mailman/listinfo/python-list


A problem with itertools.groupby

2021-12-17 Thread ast

Python 3.9.9

Hello

I have some troubles with groupby from itertools

from itertools import groupby

for k, grp in groupby("aahfffddnnb"):
print(k, list(grp))
print(k, list(grp))

a ['a', 'a']
a []
h ['h']
h []
f ['f', 'f', 'f']
f []
d ['d', 'd']
d []
s ['s', 's', 's', 's']
s []
n ['n', 'n']
n []
b ['b']
b []

It works as expected.
itertools._grouper objects are probably iterators
so they provide their datas only once. OK

but:

li = [grp for k, grp in groupby("aahfffddnnb")]
list(li[0])

[]

list(li[1])

[]

It seems empty ... I don't understand why, this is
the first read of an iterator, it should provide its
data.

This one works:

["".join(grp) for k, grp in groupby("aahfffddnnb")]

['aa', 'h', 'fff', 'dd', '', 'nn', 'b']

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


Re: Unexpected behaviour of math.floor, round and int functions (rounding)

2021-11-23 Thread ast

Le 19/11/2021 à 21:17, Chris Angelico a écrit :

On Sat, Nov 20, 2021 at 5:08 AM ast  wrote:


Le 19/11/2021 à 03:51, MRAB a écrit :

On 2021-11-19 02:40, 2qdxy4rzwzuui...@potatochowder.com wrote:

On 2021-11-18 at 23:16:32 -0300,
René Silva Valdés  wrote:





  >>> 0.3 + 0.3 + 0.3 == 0.9
False


That's because 0.3 is not 3/10. It's not because floats are
"unreliable" or "inaccurate". It's because the ones you're entering
are not what you think they are.

When will people understand this?

(Probably never. Sigh.)

ChrisA



I posted that to make people aware of danger of float comparison,
not because I was not understanding what happened.

We can see there is a difference on the lsb, due to rounding.

>>> (0.3+0.3+0.3).hex()
'0x1.cp-1'
>>> 0.9.hex()
'0x1.dp-1'
>>>

An isclose() function is provided in module math to do float
comparison safely.

>>> math.isclose(0.3+0.3+0.3, 0.9)
True
--
https://mail.python.org/mailman/listinfo/python-list


Re: copy.copy

2021-11-22 Thread ast

Le 22/11/2021 à 16:02, Jon Ribbens a écrit :

On 2021-11-22, ast  wrote:




For immutable types, copy(foo) just returns foo.



ok, thx
--
https://mail.python.org/mailman/listinfo/python-list


copy.copy

2021-11-22 Thread ast

Hi,

>>> a = 6
>>> b = 6
>>> a is b
True

ok, we all know that Python creates a sole instance
with small integers, but:

>>> import copy
>>> b = copy.copy(a)
>>> a is b
True

I was expecting False
--
https://mail.python.org/mailman/listinfo/python-list


Re: Unexpected behaviour of math.floor, round and int functions (rounding)

2021-11-19 Thread ast

Le 19/11/2021 à 12:43, ast a écrit :

Le 19/11/2021 à 03:51, MRAB a écrit :

On 2021-11-19 02:40, 2qdxy4rzwzuui...@potatochowder.com wrote:

On 2021-11-18 at 23:16:32 -0300,
René Silva Valdés  wrote:


Hello, I would like to report the following issue:

Working with floats i noticed that:

int(23.99/12) returns 1, and
int(23.999/12) returns 2

This implies that int() function is rounding ...


It's not int() that's doing the rounding; that second numerator is being
rounded before being divided by 12:

 Python 3.9.7 (default, Oct 10 2021, 15:13:22)
 [GCC 11.1.0] on linux
 Type "help", "copyright", "credits" or "license" for more 
information.

 >>> 23.999
 24.0
 >>> (23.999).hex()
 '0x1.8p+4'

I think this is a bit clearer because it shows that it's not just 
being rounded for display:


Python 3.10.0 (tags/v3.10.0:b494f59, Oct  4 2021, 19:00:18) [MSC 
v.1929 64 bit (AMD64)] on win32

Type "help", "copyright", "credits" or "license" for more information.
 >>> 23.99 == 24
False
 >>> 23.999 == 24
True


 >>> 0.3 + 0.3 + 0.3 == 0.9
False


Better use math.isclose to test equality between 2 floats

>>> import math
>>> math.isclose(0.3 + 0.3 + 0.3, 0.9)
True
--
https://mail.python.org/mailman/listinfo/python-list


Re: Unexpected behaviour of math.floor, round and int functions (rounding)

2021-11-19 Thread ast

Le 19/11/2021 à 03:51, MRAB a écrit :

On 2021-11-19 02:40, 2qdxy4rzwzuui...@potatochowder.com wrote:

On 2021-11-18 at 23:16:32 -0300,
René Silva Valdés  wrote:


Hello, I would like to report the following issue:

Working with floats i noticed that:

int(23.99/12) returns 1, and
int(23.999/12) returns 2

This implies that int() function is rounding ...


It's not int() that's doing the rounding; that second numerator is being
rounded before being divided by 12:

 Python 3.9.7 (default, Oct 10 2021, 15:13:22)
 [GCC 11.1.0] on linux
 Type "help", "copyright", "credits" or "license" for more 
information.

 >>> 23.999
 24.0
 >>> (23.999).hex()
 '0x1.8p+4'

I think this is a bit clearer because it shows that it's not just being 
rounded for display:


Python 3.10.0 (tags/v3.10.0:b494f59, Oct  4 2021, 19:00:18) [MSC v.1929 
64 bit (AMD64)] on win32

Type "help", "copyright", "credits" or "license" for more information.
 >>> 23.99 == 24
False
 >>> 23.999 == 24
True


>>> 0.3 + 0.3 + 0.3 == 0.9
False
--
https://mail.python.org/mailman/listinfo/python-list


Re: Symbolic links on Windows

2021-11-17 Thread ast

Le 17/11/2021 à 13:10, Python a écrit :

ast wrote:

Hello,

It seems that symbolic links on Windows are not
well reconized by modules os or pathlib.

I have a file named json.txt on my destop. With a
drag and drop right click on it I create a link
automatically named: json.txt - Raccourci.lnk


This is not a symbolic link.

Symbolic links were introduced in Windows Vista/Windows
Server 2008. A .lnk file is just a regular file containing
the path of the target (you can open it and read it if you
wish) that is interpreted in a specific way by the graphical
Shell and some other applications.




Yes you are right

On Windows symbolic links are created in a cmd tool:
e.g

mklink json2.txt json.txt

And it is something different than shortcut files (suffix .lnk)
--
https://mail.python.org/mailman/listinfo/python-list


Symbolic links on Windows

2021-11-17 Thread ast

Hello,

It seems that symbolic links on Windows are not
well reconized by modules os or pathlib.

I have a file named json.txt on my destop. With a
drag and drop right click on it I create a link
automatically named: json.txt - Raccourci.lnk

Then:

>>> from pathlib import Path

>>> p2 = Path('C:/Users/jm/desktop/json.txt - Raccourci.lnk')

>>> p2
WindowsPath('C:/Users/jm/desktop/json.txt - Raccourci.lnk')

>>> p2.exists()
True

>>> p2.is_file()
True

>>> p2.is_symlink()
False

With this last command I was expecting True and for
p2_is_file() I was expecting False



With os, it's the same

import os

>>> os.path.exists(p2)
True

>>> os.path.isfile(p2)
True

os.path.islink(p2)
False


What's wrong plz ?
--
https://mail.python.org/mailman/listinfo/python-list


One line sort

2021-11-15 Thread ast

A curiosity:

q = lambda x: x and q([i for i in x[1:] if i < x[0]]) + [x[0]] + q([i 
for i in x[1:] if i >= x[0]])


>>> q([7, 5, 9, 0])
[0, 5, 7, 9]
--
https://mail.python.org/mailman/listinfo/python-list


Re: Syntax not understood

2021-11-04 Thread ast

Le 04/11/2021 à 16:41, Stefan Ram a écrit :

ast  writes:

(scale * i for i in srcpages.xobj_box[2:]) is a generator, a single
object, it should not be possible to unpack it into 2 variables.


   But the value of the right-hand side /always/ is a single object!

   A syntax of an assignment statement that has been simplified
   by me but is sufficient for this post is:

target list = source expression

   . The evaluation of the source expression yields an object.

   If the target list is not a single target, that object must
   be an iterable with the same number of items as there are targets
   in the target list, and the items are assigned, from left to
   right, to the corresponding targets.

   A generator object /is/ an iterable, and, here, it apparently
   yields exactly two items.




understood

It is like:

x, y = (i for i in range(2))

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


Syntax not understood

2021-11-04 Thread ast

Hello

In this function

def get4(srcpages):
scale = 0.5
srcpages = PageMerge() + srcpages
x_increment, y_increment = (scale * i for i in srcpages.xobj_box[2:])
for i, page in enumerate(srcpages):
page.scale(scale)
page.x = x_increment if i & 1 else 0
page.y = 0 if i & 2 else y_increment
return srcpages.render()

found here

https://www.blog.pythonlibrary.org/2018/06/06/creating-and-manipulating-pdfs-with-pdfrw/

I do not understand this line:

x_increment, y_increment = (scale * i for i in srcpages.xobj_box[2:])

(scale * i for i in srcpages.xobj_box[2:]) is a generator, a single
object, it should not be possible to unpack it into 2 variables.

x, y = 1 generates an error
x, y = (i for i in range(10)) too

but not

x_increment, y_increment = (scale * i for i in srcpages.xobj_box[2:])

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


Recursion on list

2021-11-04 Thread ast

> li = []
> li.append(li)
> li
[[...]]

>li[0][0][0][0]
[[...]]

That's funny
--
https://mail.python.org/mailman/listinfo/python-list


Inheriting from str

2021-09-20 Thread ast

Hello

class NewStr(str):
def __init__(self, s):
self.l = len(s)

Normaly str is an immutable type so it can't be modified
after creation with __new__

But the previous code is working well

obj = NewStr("qwerty")
obj.l
6

I don't understand why it's working ?


(python 3.9)
--
https://mail.python.org/mailman/listinfo/python-list


Re: Ask for help on using re

2021-08-06 Thread ast

Le 06/08/2021 à 02:57, Jach Feng a écrit :

ast 在 2021年8月5日 星期四下午11:29:15 [UTC+8] 的信中寫道:

Le 05/08/2021 à 17:11, ast a écrit :

Le 05/08/2021 à 11:40, Jach Feng a écrit :



import regex

# regex is more powerful that re

text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n'
regex.findall(r'ch \d++(?!\.)', text)


['ch 4', 'ch 56']

## ++ means "possessive", no backtrack is allowed



Can someone explain how the difference appear? I just can't figure it out:-(



+, *, ? are greedy, means they try to catch as many characters
as possible. But if the whole match doesn't work, they release
some characters once at a time and try the whole match again.
That's backtrack.
With ++, backtrack is not allowed. This works with module regex
and it is not implemented in module re

with string = "ch 23." and pattern = r"ch \d+\."

At first trial \d+  catch 23
but whole match will fail because next character is . and . is not 
allowed (\.)


A backtrack happens:

\d+  catch only 2
and the whole match is successful because the next char 3 is not .
But this is not what we want.

with ++, no backtrack, so no match
"ch 23." is rejected
this is what we wanted


Using re only, the best way is probably

re.findall(r"ch \d+(?![.0-9])", text)
['ch 4', 'ch 56']
--
https://mail.python.org/mailman/listinfo/python-list


Re: Ask for help on using re

2021-08-05 Thread ast

Le 05/08/2021 à 17:11, ast a écrit :

Le 05/08/2021 à 11:40, Jach Feng a écrit :

I want to distinguish between numbers with/without a dot attached:


text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n'
re.compile(r'ch \d{1,}[.]').findall(text)

['ch 1.', 'ch 23.']

re.compile(r'ch \d{1,}[^.]').findall(text)

['ch 23', 'ch 4 ', 'ch 56 ']

I can guess why the 'ch 23' appears in the second list. But how to get 
rid of it?


--Jach



 >>> import re

 >>> text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n'

 >>> re.findall(r'ch \d+\.', text)
['ch 1.', 'ch 23.']

 >>> re.findall(r'ch \d+(?!\.)', text)   # (?!\.) for negated look ahead
['ch 2', 'ch 4', 'ch 56']


import regex

# regex is more powerful that re

>>> text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n'

>>> regex.findall(r'ch \d++(?!\.)', text)

['ch 4', 'ch 56']

## ++ means "possessive", no backtrack is allowed




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


Re: Ask for help on using re

2021-08-05 Thread ast

Le 05/08/2021 à 17:11, ast a écrit :

Le 05/08/2021 à 11:40, Jach Feng a écrit :

I want to distinguish between numbers with/without a dot attached:


text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n'
re.compile(r'ch \d{1,}[.]').findall(text)

['ch 1.', 'ch 23.']

re.compile(r'ch \d{1,}[^.]').findall(text)

['ch 23', 'ch 4 ', 'ch 56 ']

I can guess why the 'ch 23' appears in the second list. But how to get 
rid of it?


--Jach



 >>> import re

 >>> text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n'

 >>> re.findall(r'ch \d+\.', text)
['ch 1.', 'ch 23.']

 >>> re.findall(r'ch \d+(?!\.)', text)   # (?!\.) for negated look ahead
['ch 2', 'ch 4', 'ch 56']


ops ch2 is found. Wrong
--
https://mail.python.org/mailman/listinfo/python-list


Re: Ask for help on using re

2021-08-05 Thread ast

Le 05/08/2021 à 11:40, Jach Feng a écrit :

I want to distinguish between numbers with/without a dot attached:


text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n'
re.compile(r'ch \d{1,}[.]').findall(text)

['ch 1.', 'ch 23.']

re.compile(r'ch \d{1,}[^.]').findall(text)

['ch 23', 'ch 4 ', 'ch 56 ']

I can guess why the 'ch 23' appears in the second list. But how to get rid of 
it?

--Jach



>>> import re

>>> text = 'ch 1. is\nch 23. is\nch 4 is\nch 56 is\n'

>>> re.findall(r'ch \d+\.', text)
['ch 1.', 'ch 23.']

>>> re.findall(r'ch \d+(?!\.)', text)   # (?!\.) for negated look ahead
['ch 2', 'ch 4', 'ch 56']
--
https://mail.python.org/mailman/listinfo/python-list


Subtle difference between any(a list) and any(a generator) with Python 3.9

2021-07-29 Thread ast

Hello

Reading PEP572 about Python 3.9 assignment expressions,
I discovered a subtle difference between any(a list)
and any(a generator)

see:

>>> lines = ["azerty", "#qsdfgh", "wxcvbn"]
>>> any((comment := line).startswith('#') for line in lines)
True
>>> comment
"#qsdfgh"

>>> any([(comment := line).startswith('#') for line in lines])
True
>>> comment
'wxcvbn'

The two code snippets which seems very similar provide a
different value for "comment".

When "any" deals with a generator, it stops as soon it finds
a True value and returns True.

When "any" deals with a list, the whole list is calculated
first, and then "any" looks for a True.

Before 3.9 and the walrus operator, the two ways always provide
the same result, in a faster way with a generator.

With 3.9 and the walrus operator, result can be different








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


Re: list() strange behaviour

2021-01-22 Thread ast

Le 20/12/2020 à 21:00, danilob a écrit :




b = ((x[0] for x in a))



There is a useless pair of parenthesis

b = (x[0] for x in a)

b is a GENERATOR expression

first list(b) calls next method on b repetedly until b is empty.
So it provides the "content" of b

second list(b) provides nothing since b is empty
(there is no reset on generators)




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


Re: Returning from a multiple stacked call at once

2020-12-12 Thread ast

Le 12/12/2020 à 09:18, Cameron Simpson a écrit :

On 12Dec2020 07:39, ast  wrote:

In case a function recursively calls itself many times,
is there a way to return a data immediately without
unstacking all functions ?


Not really. Do you have an example where this is inconvenient?

There are alternatives, for example passing in a Queue and put()ing the
data onto the queue. It's quite dependent on what you're trying to do
though.

Cheers,
Cameron Simpson 



I don't really need it. I was just wondering and guessed it was
not feasible.

Here is a code where it would be useful. This code looks for a
path in a graph.
If the found path is long, say 100 nodes, then path_finder calls
itself recursively 100 times, and has to unstack 100 times to
provide the found path. It could be returned immediately.


def path_finder(graph, start, end, path=[]):

if start in path:
return None
if start == end:
return path + [start]   # Found !
if start not in graph:
return None

path = path + [start]

for node in graph[start]:
found_path = path_finder(graph, node, end, path)
if found_path:
return found_path
return None

graph = {'A': ['B', 'C'],
 'B': ['C', 'D'],
 'C': ['D'],
 'D': ['C'],
 'E': ['F'],
 'F': ['C']}

path_finder(graph, 'A', 'D')
--
https://mail.python.org/mailman/listinfo/python-list


Re: Returning from a multiple stacked call at once

2020-12-12 Thread ast

Le 12/12/2020 à 17:10, Oscar a écrit :

In article <5fd465b5$0$8956$426a7...@news.free.fr>, ast   wrote:

Hello

In case a function recursively calls itself many times,
is there a way to return a data immediately without
unstacking all functions ?


If you are referring to your "are you ok?" problem, please read up on
recursion and when and how to use it. You were doing it completely
wrong. You only call a function from *whitin itself* if you need
recursion. It's quite hard to explain in a few words, so just google it.
I'm sure there are many great explanations around.



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


Returning from a multiple stacked call at once

2020-12-11 Thread ast

Hello

In case a function recursively calls itself many times,
is there a way to return a data immediately without
unstacking all functions ?

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


Re: property

2020-06-30 Thread ast

Le 26/06/2020 à 15:12, Peter Otten a écrit :

Unknown wrote:




The getter/setter of the property builtin return a new property



p = property()
q = p.getter(None)
p is q

False

where you


  def getter(self, fget):
  self.fget = fget
  return self


modify the existing one.

  


Yes you are right. Thank you for noticing that.

My property seems better since you can choose any names
for the functions to be used for fget, fset and fdel.



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


Re: property

2020-06-30 Thread ast

Le 26/06/2020 à 10:16, R.Wieser a écrit :

ast,





I have absolutily /no idea/ about how that "fahrenheit = property()" comes
into play though.   



It just creates an empty property object.

You can then fill this object with the read/write/delete functions
with the methods getter, setter, deleter
--
https://mail.python.org/mailman/listinfo/python-list


property

2020-06-26 Thread ast

Hello,

I am wondering why this code is OK:

class Temperature:
def __init__(self):
self.celsius = 0

fahrenheit = property()

@fahrenheit.getter
def fahrenheit(self):
return 9/5*self.celsius +32

@fahrenheit.setter
def fahrenheit(self, value):
self.celsius = (value-32)*5/9


and this one is not:


class Temperature:
def __init__(self):
self.celsius = 0

fahrenheit = property()

@fahrenheit.getter
def f(self):
return 9/5*self.celsius +32

@fahrenheit.setter
def f(self, value):
self.celsius = (value-32)*5/9

In the second code, I just changed the names of the
decorated functions

Unforunately I was not able to find "property" source
code to understand how it works exactly

I wrote a my_property which makes the two previous codes
to work fine. This is why I don't understand why the
genuine property does't work when decorated functions
are named f rather than fahrenheit

Here it is:

class my_property:

def __init__(self, fget=None, fset=None, fdel=None):
self.fget = fget
self.fset = fset
self.fdel = fdel

def __get__(self, instance, owner):
if instance is None:
return self
return self.fget(instance)

def __set__(self, instance, value):
self.fset(instance, value)

def __delete__(self, instance):
self.fdel(instance)

def getter(self, fget):
self.fget = fget
return self

def setter(self, fset):
self.fset = fset
return self

def deleter(self, fdel):
self.fdel = fdel
return self
--
https://mail.python.org/mailman/listinfo/python-list


Can a print overwrite a previous print ?

2020-05-08 Thread ast

Hello


Suppose we want that:

print("abcdef"); print("ghi")

produces:

ghidef

The 2nd print overwrites the first one.
Is it feasible ?

It should since the progress bar tdqh seems to do that

try:

from tkdm import tkdm

for i in tqdm(range(100_000_000)):
pass

It produces a progress bar like this:
100%|███| 
1/1 [00:56<00:00, 1781611.52it/s]

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


Problem with doctest

2020-05-04 Thread ast

Hello

doctest of the sample function funct() doesn't works
because flag used by funct() is the one defined in
first line "flag = True" and not the one in the
doctest code ">>> flag = False".

Any work around known ?


flag = True  # <- funct() always use this one

def funct():
"""
Code for doctest:

>>> flag = True
>>> funct()
'Yes'
>>> flag = False #  <- Ignored unfortunalely
>>> funct()
'No'
"""

if flag:
return "Yes"
else:
return "No"

if __name__ == "__main__":
import doctest
doctest.testmod()



Failed example:
funct()
Expected:
'No'
Got:
'Yes'
**
1 items had failures:
   1 of   4 in __main__.funct
***Test Failed*** 1 failures.
--
https://mail.python.org/mailman/listinfo/python-list


Re: JH Conway memorial Life program

2020-04-28 Thread ast

Le 12/04/2020 à 23:40, Paul Rubin a écrit :

You might have heard by now that John Horton Conway died yesterday at
age 82, of complications from the SARS-Cov2 aka Corona virus.  Among his
many cool accomplishments was inventing the Game of Life, which was one
of my first exercises as a beginning programmer in middle school.  That
program used the naive approach of representing the game board as a 2-d
array and scanning all its cells at each generation.

Far better programmers and mathematicians than I am worked on
fantastically optimized Life programs and made wonderful discoveries
about Life patterns.  See https://conwaylife.com for a sample of that.

I never got too heavily into Life programming myself, but a year or two
ago I thought of a quite simple way to write a Life program whose
running time at each generation was linear in the number of active cells
(unlike my first program that I had written as a kid, whose running time
and space consumption was potentially unbounded even with a fixed
population).

In Conway's honor I'm appending the simple program (28 lines of Python)
below.

RIP, Prof. Conway.



#!/usr/bin/python3
from itertools import chain

def adjacents(cell):# generate coordinates of cell neighbors
 x, y = cell # a cell is just an x,y coordinate pair
 return ((x+i,y+j) for i in [-1,0,1] for j in [-1,0,1] if i or j)

def update(living): # living = currently living set of cells
 def ncount(cell):   # number of living neighbors of cell
 return sum(1 for c in adjacents(cell) if c in living)
 def uninhabitable(cell):# check if occupied cell should die
 return not(2 <= ncount(cell) <= 3)
 def fertile(cell):  # check if empty cell should have a birth
 return ncount(cell) == 3

 # get set of cells (living or not) that are adjacent to some living cell
 neighbors = set(chain.from_iterable(adjacents(c) for c in living))

 frontier = neighbors - living # the empty cells adjacent to living ones
 births = set(filter(fertile, frontier)) # are where births can happen
 deaths = set(filter(uninhabitable, living))
 return (living - deaths) | births

if __name__ == '__main__':
 r = set([(0,0),(0,1),(0,2),(1,2),(-1,1)])  # R-pentomino
 for i in range(1,1110):   # it should stabilize at generation 1104
 print (i,len(r))  # show generation number and population
 r = update(r)



I found in a Game Of Life program (not mine) a very clever method to
update a board of cell as a whole

It worths seeing it.

X is a numpy 2D ndarray

def evolve(X):
''' Evolves a board of Game of Life for one turn '''
# Dead cells as a boundary condition
# Count neighbours
# Alive if 3 neighbours or 2 neighbours and already alive

Xi = X.astype(int)
neigh = np.zeros(Xi.shape)

neigh[1:-1,1:-1] = (Xi[:-2,:-2]  + Xi[:-2,1:-1] + Xi[:-2,2:] +
Xi[1:-1,:-2] +Xi[1:-1,2:]  +
Xi[2:,:-2]   + Xi[2:,1:-1]  + Xi[2:,2:])

return np.logical_or(neigh==3,np.logical_and(Xi==1,neigh==2))
--
https://mail.python.org/mailman/listinfo/python-list


Re: Conway's game of Life, just because.

2020-04-28 Thread ast

Le 07/05/2019 à 05:31, Paul Rubin a écrit :

#!/usr/bin/python3
from itertools import chain

def adjacents(cell):# generate coordinates of cell neighbors
 x, y = cell # a cell is just an x,y coordinate pair
 return ((x+i,y+j) for i in [-1,0,1] for j in [-1,0,1] if i or j)

def update(living): # living = currently living set of cells
 def ncount(cell):   # number of living neighbors of cell
 return sum(1 for c in adjacents(cell) if c in living)
 def uninhabitable(cell):# check if occupied cell should die
 return not(2 <= ncount(cell) <= 3)
 def fertile(cell):  # check if empty cell should have a birth
 return ncount(cell) == 3

 # get set of cells (living or not) that are adjacent to some living cell
 neighbors = set(chain.from_iterable(adjacents(c) for c in living))

 frontier = neighbors - living # the empty cells adjacent to living ones
 births = set(filter(fertile, frontier)) # are where births can happen
 deaths = set(filter(uninhabitable, living))
 return (living - deaths) | births

if __name__ == '__main__':
 r = set([(0,0),(0,1),(0,2),(1,2),(-1,1)])  # R-pentomino
 for i in range(1,1110):   # it should stabilize at generation 1104
 print (i,len(r))  # show generation number and population
 r = update(r)




I found in a Game Of Life program (not mine) a very clever method to
update a board of cell.

It worths seeing it.

X is a numpy 2D ndarray

def evolve(X):
''' Evolves a board of Game of Life for one turn '''
# Dead cells as a boundary condition
# Count neighbours
# Alive if 3 neighbours or 2 neighbours and already alive

Xi = X.astype(int)
neigh = np.zeros(Xi.shape)

neigh[1:-1,1:-1] = (Xi[:-2,:-2]  + Xi[:-2,1:-1] + Xi[:-2,2:] +
Xi[1:-1,:-2] +Xi[1:-1,2:]  +
Xi[2:,:-2]   + Xi[2:,1:-1]  + Xi[2:,2:])

return np.logical_or(neigh==3,np.logical_and(Xi==1,neigh==2))


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


Re: Function to avoid a global variable

2020-04-28 Thread ast

Le 28/04/2020 à 09:52, ast a écrit :

Le 28/04/2020 à 09:39, Antoon Pardon a écrit :



Op 27/04/20 om 18:39 schreef Bob van der Poel:

Thanks Chris!

At least my code isn't (quite!) as bad as the xkcd example :)

Guess my "concern" is using the initialized array in the function:

    def myfunct(a, b, c=array[0,1,2,3] )

always feels like an abuse.

Has anyone seriously considered implementing  a true static variable 
in a

function? Is there a PEP?


You can emulate a static variable is with a closure.

def make_parseStack():

 depth = 0

 def parseStack(inc):
    nonlocal depth

 if depth > 50:
 ... report error and die nicely
 depth += inc

 return parseStack

parseStack = make_parseStack()



funny !

So we found 4 different ways to handle a memory in a function

1- Use a function parameter with a mutable default value

2- Use a function attribute

3- Use a callable object, and store your stuff inside an object attr

4- Use a closure to emulate a static function variable

Any more ?




5- Use a global variable, of course
--
https://mail.python.org/mailman/listinfo/python-list


Re: Function to avoid a global variable

2020-04-28 Thread ast

Le 28/04/2020 à 09:39, Antoon Pardon a écrit :



Op 27/04/20 om 18:39 schreef Bob van der Poel:

Thanks Chris!

At least my code isn't (quite!) as bad as the xkcd example :)

Guess my "concern" is using the initialized array in the function:

    def myfunct(a, b, c=array[0,1,2,3] )

always feels like an abuse.

Has anyone seriously considered implementing  a true static variable in a
function? Is there a PEP?


You can emulate a static variable is with a closure.

def make_parseStack():

     depth = 0

     def parseStack(inc):
    nonlocal depth

     if depth > 50:
     ... report error and die nicely
     depth += inc

     return parseStack

parseStack = make_parseStack()



funny !

So we found 4 different ways to handle a memory in a function

1- Use a function parameter with a mutable default value

2- Use a function attribute

3- Use a callable object, and store your stuff inside an object attr

4- Use a closure to emulate a static function variable

Any more ?


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


Re: Function to avoid a global variable

2020-04-28 Thread ast

Le 28/04/2020 à 09:13, Chris Angelico a écrit :

On Tue, Apr 28, 2020 at 4:56 PM ast  wrote:


Le 27/04/2020 à 04:46, Bob van der Poel a écrit :





"Best"? Not sure about that. Functions are first-class objects in
Python, so a function *is* a callable object. You don't have to create
a custom class with a call method just to be able to attach attributes
to your function.

ChrisA



Using a mutable object as a function default parameter value
and changing it inside the function looks like a "trick"
according to me.
--
https://mail.python.org/mailman/listinfo/python-list


Re: Function to avoid a global variable

2020-04-28 Thread ast

Le 28/04/2020 à 08:51, ast a écrit :

Le 27/04/2020 à 04:46, Bob van der Poel a écrit :

Does this make as much sense as anything else? I need to track calls to a
function to make sure it doesn't get called to too great a depth. I had a
global which I inc/dec and then check in the function. Works fine, but 
I do

need to keep a global around just for this.

So ... instead I wrote a short function:

  def parseStack(inc, depth=[0]):
  if depth[0] > 50:
  ... report error and die nicely
 depth[0] += inc

This gets rid of the global, and it moves my error check out of the main
code as well. But, I never feel all that great about using a list in the
function call for static storage.




Using a callable object is the best way to define a function
with a memory

class ParseStack:
     def __init__(self):
     self.depth=0
     def __call__(self, inc, reset=True):
     if reset:
     self.depth = 0
     if self.depth > 50:
     ... report error
     self.depth += 1
     ... do your stuff

parse_stack = ParseStack()

and use "function" parse_stack

parse_stack(43)
...



def __call__(self, inc, reset=False):
--
https://mail.python.org/mailman/listinfo/python-list


Re: Function to avoid a global variable

2020-04-27 Thread ast

Le 27/04/2020 à 04:46, Bob van der Poel a écrit :

Does this make as much sense as anything else? I need to track calls to a
function to make sure it doesn't get called to too great a depth. I had a
global which I inc/dec and then check in the function. Works fine, but I do
need to keep a global around just for this.

So ... instead I wrote a short function:

  def parseStack(inc, depth=[0]):
  if depth[0] > 50:
  ... report error and die nicely
 depth[0] += inc

This gets rid of the global, and it moves my error check out of the main
code as well. But, I never feel all that great about using a list in the
function call for static storage.




Using a callable object is the best way to define a function
with a memory

class ParseStack:
def __init__(self):
self.depth=0
def __call__(self, inc, reset=True):
if reset:
self.depth = 0
if self.depth > 50:
... report error
self.depth += 1
... do your stuff

parse_stack = ParseStack()

and use "function" parse_stack

parse_stack(43)
...
--
https://mail.python.org/mailman/listinfo/python-list


matplotlib: Difference between Axes and AxesSubplot

2020-04-27 Thread ast

Hello

It's not clear to me what the differences between
Axes and AxesSubplot classes are

AxesSubplot is a sub class of Axes

It is possible to draw in objects of both type with
plot, scatter ...

Axes object seems to be able to be inserted in AxesSubplot object
(It is strange because AxesSubplot is a sub class of Axes)

Here is a piece of code using both.

import matplotlib.pyplot as pyplot

figure = pyplot.figure()
axes = figure.add_subplot(111) # Renvoie un objet AxesSubplot, sous 
classe de Axes

axes.scatter(range(5), [x ** 2 for x in range(5)])
axes.set_xlim(0, 4)
axes.set_xlabel('axe des x')
axes2 = figure.add_axes([0.3, 0.5, 0.3, 0.3]) # renvoie un objet Axes
axes2.patch.set_color('lightyellow')
axes2.plot(range(5), range(5))

and the figure it produces:

http://www.python-simple.com/img/img32.png
--
https://mail.python.org/mailman/listinfo/python-list


Re: Something annoying about method __set_name__ in descriptors

2020-04-21 Thread ast

Le 21/04/2020 à 18:32, Dieter Maurer a écrit :

ast wrote at 2020-4-21 14:27 +0200:




I recently read the Python (3.9a5) documentation - and there
I found clearly expressed this behaviour (I no longer can
tell you exactly where I read this).

The reason comes from the implementation: when the descriptor
is instantiated, the name the instance is bound to is not yet known.
Class creation is complex in Python (details in the Python documentation):
first a so called "namespace" (a mapping from names to values) is constructed;
after this construction, the so called metaclass is called with
class name, bases, the constructed namespace and potentially additional
keyword arguments. It is the typical metaclass (`type`) which calls
`__set_name__` for descritors it finds in the namespace.

This has several ramifications:

  * `__set_name__` is not called "inline" (as you observed)

  * `__set_name__` is not called automatically for descriptors added
after class construction

  * `__set_name_` may not be called at all if the class uses
a custom metaclass.



Thank you for this explanation.
So it's not a bug it's a feature
--
https://mail.python.org/mailman/listinfo/python-list


Something annoying about method __set_name__ in descriptors

2020-04-21 Thread ast

Hello

From python version 3.6, there is a useful new method
__set_name__ which could be implemented in descriptors.

This method is called after a descriptor is instantiated
in a class. Parameter "name" is filled with the name
of the attribute refering to the descriptor in the class

Here is an example:

class Descriptor:
def __set_name__(self, owner, name):
print(name)

class A:
value = Descriptor()


value## produced by print in Descriptor


-

But I discovered that __set_name__ is not called immediately
after the execution of line "value = Descriptor()" but after
all class code execution ...

Here is an other example:

class Descriptor:
def __set_name__(self, owner, name):
print("From Descriptor's method __set_name__: ", name)


class Test:
aaa = Descriptor()
print("From class Test")

From class Test
From Descriptor's method __set_name__:  aaa
>>>

As you see, the print from __set_name__ occurs AFTER the print
from the class, I think every body was expecting the print
from __set_name__ before.

It is annoying in some real life, when one descriptor's method
is a decorator and you write things like:


class Temperature:
def __init__(self):
self.celsius= 0

fahrenheit = my_property()

@fahrenheit.getter
def fahrenheit(self):
return 1.8*self.celsius+ 32

@fahrenheit.setter
def fahrenheit(self, value):
self.celsius= (value -32)/1.8

and fahrenheit.getter is expecting an attribute in fahrenheit which
has not been set yet, it will be after all Temperature class code
execution ...









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


Re: Not understood error with __set_name__ in a descriptor class

2020-04-19 Thread ast

Le 19/04/2020 à 17:06, ast a écrit :

I understood where the problem is.

Once __get__ is defined, it is used to read self._name in method
__set_name__ and it is not défined yet. That's why I have
an error "'NoneType' object is not callable"
Thats a nice bug.
I need to think for a workaround


Hello

This code is working well: (I am using python 3.6.3)


class my_property:
     def __init__(self, fget=None, fset=None, fdel=None):
     self.fget = fget
     self.fset = fset
     self.fdel = fdel
     def __set_name__(self, owner, name):
     self._name = name
     print("Inside __set_name__ method:  ", self._name)

##    def __get__(self, instance, owner):
##    return self.fget(instance)


class Test:
     celsius = my_property()

print("Outside __set_name__ method: ", Test.celsius._name)


Here is the output:

= RESTART: C:/Users/jm/Desktop/python/my_property.py =
Inside __set_name__ method:   celsius
Outside __set_name__ method:  celsius


And this one doesn't. (I just removed ## to uncomment the 2 lines)
Do you understand why ?

class my_property:
     def __init__(self, fget=None, fset=None, fdel=None):
     self.fget = fget
     self.fset = fset
     self.fdel = fdel
     def __set_name__(self, owner, name):
     self._name = name
     print("Inside __set_name__ method:  ", self._name)

     def __get__(self, instance, owner):
     return self.fget(instance)


class Test:
     celsius = my_property()

print("Outside __set_name__ method: ", Test.celsius._name)

Here is the output:

= RESTART: C:/Users/jm/Desktop/python/my_property.py =
Inside __set_name__ method:   celsius
Traceback (most recent call last):
   File "C:/Users/jm/Desktop/python/my_property.py", line 17, in 
     print("Outside __set_name__ method: ", Test.celsius._name)
   File "C:/Users/jm/Desktop/python/my_property.py", line 11, in __get__
     return self.fget(instance)
TypeError: 'NoneType' object is not callable


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


Not understood error with __set_name__ in a descriptor class

2020-04-19 Thread ast

Hello

This code is working well: (I am using python 3.6.3)


class my_property:
def __init__(self, fget=None, fset=None, fdel=None):
self.fget = fget
self.fset = fset
self.fdel = fdel
def __set_name__(self, owner, name):
self._name = name
print("Inside __set_name__ method:  ", self._name)

##def __get__(self, instance, owner):
##return self.fget(instance)


class Test:
celsius = my_property()

print("Outside __set_name__ method: ", Test.celsius._name)


Here is the output:

= RESTART: C:/Users/jm/Desktop/python/my_property.py =
Inside __set_name__ method:   celsius
Outside __set_name__ method:  celsius


And this one doesn't. (I just removed ## to uncomment the 2 lines)
Do you understand why ?

class my_property:
def __init__(self, fget=None, fset=None, fdel=None):
self.fget = fget
self.fset = fset
self.fdel = fdel
def __set_name__(self, owner, name):
self._name = name
print("Inside __set_name__ method:  ", self._name)

def __get__(self, instance, owner):
return self.fget(instance)


class Test:
celsius = my_property()

print("Outside __set_name__ method: ", Test.celsius._name)

Here is the output:

= RESTART: C:/Users/jm/Desktop/python/my_property.py =
Inside __set_name__ method:   celsius
Traceback (most recent call last):
  File "C:/Users/jm/Desktop/python/my_property.py", line 17, in 
print("Outside __set_name__ method: ", Test.celsius._name)
  File "C:/Users/jm/Desktop/python/my_property.py", line 11, in __get__
return self.fget(instance)
TypeError: 'NoneType' object is not callable
--
https://mail.python.org/mailman/listinfo/python-list


Re: Floating point problem

2020-04-18 Thread ast

Le 18/04/2020 à 15:07, Souvik Dutta a écrit :

I have one question here. On using print(f"{c:.32f}") where c= 2/5 instead
of getting 32 zeroes I got some random numbers. The exact thing is
0.40002220446049250313
Why do I get this and not 32 zeroes?





2/5 = 0.0110011001100110011001...  and repeat 1001 infinitely

It cannot be represented exactly on a 64bits float




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


Re: Floating point problem

2020-04-17 Thread ast

Le 17/04/2020 à 13:40, Aakash Jana a écrit :


I am running python 3.8 only but my issue is I need more zeroes after my
result.
I want 2/5 = 0.40
But I am only getting 0.4


f"{2/5:.6f}"
'0.40'

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


Decorator with parameters

2020-04-06 Thread ast

Hello

I wrote a decorator to add a cache to functions.
I realized that cache dictionnary could be defined
as an object attribute or as a local variable in
method __call__.
Both seems to work properly.
Can you see any differences between the two variants ?

from collection import OrderedDict

class Memoize1:
def __init__(self, size=None):
self.size = size
self.cache = OrderedDict() ### cache defined as an attribute
def __call__(self, f):
def f2(*arg):
if arg not in self.cache:
self.cache[arg] = f(*arg)
if self.size is not None and len(self.cache) >self.size:
self.cache.popitem(last=False)
return self.cache[arg]
return f2

# variant

class Memoize2:
def __init__(self, size=None):
self.size = size
def __call__(self, f):
cache = OrderedDict()  ### cache defined as a local variable
def f2(*arg):
if arg not in cache:
cache[arg] = f(*arg)
if self.size is not None and len(cache) > self.size:
cache.popitem(last=False)
return cache[arg]
return f2

@Memoize1(16)
def fibo1(n):
if n < 2: return n
return fibo1(n-2)+fibo1(n-1)


@Memoize2(16)
def fibo2(n):
if n < 2: return n
return fibo2(n-2)+fibo2(n-1)
--
https://mail.python.org/mailman/listinfo/python-list


threading

2019-12-04 Thread ast

Hi

An operation like x+=1 on a global variable x is not thread safe because 
there can be a thread switch between reading and writing to x.

The correct way is to use a lock

lock = threading.Lock

with lock:
x+=1

I tried to write a program without the lock which should fail.
Here it is:

import threading

x = 0

def test():
global x
for i in range(100):
x+=1

threadings = []

for i in range(100):
t = threading.Thread(target=test)
threadings.append(t)
t.start()

for t in threadings:
t.join()

print(x)

1

The result is always correct: 1
Why ?

Secondly, how the switch between threads is done by the processor ? Is 
there a hardware interrupt coming from a timer ?

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


Re: Recursive method in class

2019-10-02 Thread ast

Le 02/10/2019 à 12:22, Richard Damon a écrit :

On 10/2/19 1:12 AM, ast wrote:

Le 01/10/2019 à 20:56, Timur Tabi a écrit :

Could you please fix your email software so that it shows a legitimate
email address in the From: line?  Your emails all show this:

  From: ast 

All of your emails are being caught in my spam filter because of this
address.  I would email you privately, but I know n...@gmail.com isn't
your real email address.



Do "legitimate" means and address with a dot ?
But your own email address doesn't have a dot.

I don't want to show my real email address
because I don't want to be flooded with spam.

I choose: ast.donotans...@gmail.com
Hope it will convenient for you


Legitimate means one that you 'own' or are authorized to use. If you
have not registered with gmail this email address, then your use of it
qualifies as abuse (as it may well be impersonation of someone else),
and may be enough grounds for the service you are using for posting to
permanently ban you from ever posting again. There are some domains
specifically reserved so that purpose, like invalid.

If you want to use an invalid email address, then you could use
something like 'ast@invalid' or 'ast@email.invalid' and then you know
that you can't be accidentally impersonating someone else.



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


Re: Recursive method in class

2019-10-01 Thread ast

Le 01/10/2019 à 20:56, Timur Tabi a écrit :

Could you please fix your email software so that it shows a legitimate
email address in the From: line?  Your emails all show this:

 From: ast 

All of your emails are being caught in my spam filter because of this
address.  I would email you privately, but I know n...@gmail.com isn't
your real email address.



Do "legitimate" means and address with a dot ?
But your own email address doesn't have a dot.

I don't want to show my real email address
because I don't want to be flooded with spam.

I choose: ast.donotans...@gmail.com
Hope it will convenient for you

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


Re: Recursive method in class

2019-10-01 Thread ast

Le 01/10/2019 à 13:18, Rhodri James a écrit :

On 01/10/2019 08:37, ast wrote:




The problem is that "factorial" in line
"return n * factorial(self, n - 1)" should not have been found
because there is no factorial function defined in the current
scope.


Not so.  "factorial" is in the global scope of your module, which is 
always available.




yes, you rae right. It is clear now
--
https://mail.python.org/mailman/listinfo/python-list


"Regular Expression Objects" scanner method

2019-10-01 Thread ast

Hello

I am trying to understand a program which use
a method named scanner on a re compiled object.

This program is named "Simple compiler" here:
https://www.pythonsheets.com/notes/python-generator.html

But unfortunately it is not documented

nor here:
https://docs.python.org/3.7/library/re.html#regular-expression-objects

nor with help

import re
lex = re.compile("foo")
help(lex.scanner)

Help on built-in function scanner:

scanner(string, pos=0, endpos=2147483647) method of _sre.SRE_Pattern 
instance


Does anybody know where to find a doc ?
--
https://mail.python.org/mailman/listinfo/python-list


Re: Recursive method in class

2019-10-01 Thread ast

Le 30/09/2019 à 13:11, Anders Märak Leffler a écrit :

What do you mean by transformed? This is probably your understanding
already, but a further consequence of when arguments are evaluated
plus what you said about data attributes is that the fib(self, n - 1)
call will follow the standard LEGB-lookup of whatever "fib" is, from
the point of view of the function object. As far as I know, there is
no transformation of these scopes - either when it comes to creating
the class, or creating the instances. (self is just the instance,
passed as an argument.)

Cf when you change a binding:


def factorial(self, n):

... if not n:
... return 1
... else:
... return n * factorial(self, n - 1)
...

Dummy = type("DummyObject", (object, ), {"factorial" : factorial})
instance = Dummy()
def factorial(self, n):

... print("Hello!")
... return 999
...

instance.factorial(5)   # Where will the call go ("old" or "new" factorial?)? 
Where will possible recursive calls go (and why)?

Hello!
4995

Oh, and as others have pointed out on this list - you/whoever runs the
system sending the mail might want to change the return address.
n...@gmail.com is somewhat consistently classed as spam.



//Anders

PS. We could further complicate this by adding a call to
self.factorial in the new function, but let's not go there. :)



I understood your example, but it doesn't answer my initial question.
I try to rewrite my question:

The following code is working well and I don't really understand why

def factorial(self, n):
if not n:
return 1
else:
return n * factorial(self, n - 1)

Dummy = type("DummyObject", (object, ), {"factorial" : factorial})
instance = Dummy()
instance.factorial(3)

6  # correct

The problem is that "factorial" in line
"return n * factorial(self, n - 1)" should not have been found
because there is no factorial function defined in the current
scope.

if you use "class" keyword to define the class

class Dummy:

def factorial(self, n):
if not n:
return 1
else:
return n * factorial(self, n - 1)

instance = Dummy()
instance.factorial(3)

It generate an error because "factorial" in line
"return n * factorial(self, n - 1)" is not found.

Traceback (most recent call last):
  File "", line 1, in 
instance.factorial(3)
  File "", line 7, in factorial
return n * factorial(self, n - 1)
NameError: name 'factorial' is not defined

This is OK to me

The correct way is to write:

class Dummy:

def factorial(self, n):
if not n:
return 1
else:
return n * self.factorial(n - 1)

instance = Dummy()
instance.factorial(3)

6 # correct

So, to summarize, if you create a class with type(name, bases, dict_)
or with the "class" keyword, recursive methods can't be writen
in the same way. This is what puzzle me.

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


Re: Recursive method in class

2019-09-30 Thread ast

Le 27/09/2019 à 14:26, Jan van den Broek a écrit :

On 2019-09-27, ast  wrote:

Is it feasible to define a recursive method in a class ?
(I don't need it, it's just a trial)

Here are failing codes:


class Test:
  def fib(self, n):
  if n < 2: return n
  return fib(self, n-2) + fib(self, n-1)

   self.fib(...)

[Schnipp]



Yes you are right. I forgot that class methods
don't see class attributes

An other workaround:

 def fib(self, n):
 if n < 2: return n
 return Test.fib(self, n-2) + Test.fib(self, n-1)

It comes from https://www.pythonsheets.com/notes/python-object.html

>>> def fib(self, n):
... if n <= 2:
... return 1
... return fib(self, n-1) + fib(self, n-2)
...
>>> Fib = type('Fib', (object,), {'val': 10,
...   'fib': fib})
>>> f = Fib()
>>> f.val
10
>>> f.fib(f.val)
55

So it means that when classes are constructed explicitely
with type(name, bases, dict_), some methods are transformed
--
https://mail.python.org/mailman/listinfo/python-list


Recursive method in class

2019-09-27 Thread ast

Hello

Is it feasible to define a recursive method in a class ?
(I don't need it, it's just a trial)

Here are failing codes:


class Test:
def fib(self, n):
if n < 2: return n
return fib(self, n-2) + fib(self, n-1)

t = Test()

t.fib(6)

-
Traceback (most recent call last):
return fib(self, n-2) + fib(self, n-1)
NameError: name 'fib' is not defined
-

An other try:

class Test:
@staticmethod
def fib(n):
if n < 2: return n
return fib(n-2) + fib(n-1)

t = Test()
t.fib(6)


Traceback (most recent call last):
return fib(n-2) + fib(n-1)
NameError: name 'fib' is not defined
-
--
https://mail.python.org/mailman/listinfo/python-list


Re: __init__ is not invoked

2019-09-26 Thread ast

Le 26/09/2019 à 15:17, Peter Otten a écrit :

ast wrote:





__init__ is called only if __new__ returns an instance of ClassB:




 I was ignoring that. thank you
--
https://mail.python.org/mailman/listinfo/python-list


Re: __init__ is not invoked

2019-09-26 Thread ast

Le 26/09/2019 à 14:20, ast a écrit :

Hello

In the following code found here:
https://www.pythonsheets.com/notes/python-object.html

__init__ is not invoked when we create an object
with "o = ClassB("Hello")". I don't understand why.
I know the correct way to define __new__ is to write
"return object.__new__(cls, arg)" and not "return object"


 >>> class ClassB(object):
... def __new__(cls, arg):
... print('__new__ ' + arg)
... return object
... def __init__(self, arg):
... print('__init__ ' + arg)
...

 >>> o = ClassB("Hello")
__new__ Hello


Normaly, when running "o = ClassB("Hello")", we first run
__call__ from type of ClassB which is type. This __call__
method is supposed to launch __new__ from ClassB and then
__init__ from classB too. The output of __new__ is mapped
to self parameter of __init__.
But it seems things don't work like that here. Why ?



Maybe  __init__ is called by object.__new__ call and not
by type.__call_ as I thought.
So of course here without any call to object.__new__, __init__
is not called

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


__init__ is not invoked

2019-09-26 Thread ast

Hello

In the following code found here:
https://www.pythonsheets.com/notes/python-object.html

__init__ is not invoked when we create an object
with "o = ClassB("Hello")". I don't understand why.
I know the correct way to define __new__ is to write
"return object.__new__(cls, arg)" and not "return object"


>>> class ClassB(object):
... def __new__(cls, arg):
... print('__new__ ' + arg)
... return object
... def __init__(self, arg):
... print('__init__ ' + arg)
...

>>> o = ClassB("Hello")
__new__ Hello


Normaly, when running "o = ClassB("Hello")", we first run
__call__ from type of ClassB which is type. This __call__
method is supposed to launch __new__ from ClassB and then
__init__ from classB too. The output of __new__ is mapped
to self parameter of __init__.
But it seems things don't work like that here. Why ?
--
https://mail.python.org/mailman/listinfo/python-list


Funny code

2019-09-25 Thread ast

Hello

A line of code which produce itself when executed

>>> s='s=%r;print(s%%s)';print(s%s)
s='s=%r;print(s%%s)';print(s%s)

Thats funny !
--
https://mail.python.org/mailman/listinfo/python-list


Re: Exception

2019-09-24 Thread ast

Le 24/09/2019 à 15:51, אורי a écrit :

https://stackoverflow.com/a/24752607/1412564


thank you for link. it's clear now
--
https://mail.python.org/mailman/listinfo/python-list


Exception

2019-09-24 Thread ast

Hi

It is not clear to me why the following code
generates 2 exceptions, ZeroDivisionError and
ArithmeticError. Since ZeroDivisionError is
catched, it shoud not bubble out.

Found here:
https://www.pythonsheets.com/notes/python-new-py3.html

>>> def func():
... try:
... 1 / 0
... except ZeroDivisionError:
... raise ArithmeticError
...
>>> func()
Traceback (most recent call last):
  File "", line 3, in func
ZeroDivisionError: division by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "", line 1, in 
  File "", line 5, in func
ArithmeticError


There is a work around (python >= 3.3)

>>> def func():
... try:
... 1 / 0
... except ZeroDivisionError:
... raise ArithmeticError from None
...
>>> func()
Traceback (most recent call last):
  File "", line 1, in 
  File "", line 5, in func
ArithmeticError
--
https://mail.python.org/mailman/listinfo/python-list


Strange Class definition

2019-09-16 Thread ast

Hello

Following syntax doesn't generate any errors:

>>> foo=0
>>> Class Foo:
   foo

But class Foo seems empty

Is it equivalent to ?

>>> class Foo:
pass



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


Re: what's the differences: None and null?

2019-09-15 Thread ast

Le 14/09/2019 à 03:40, Random832 a écrit :

On Fri, Sep 13, 2019, at 21:22, Hongyi Zhao wrote:

what's the differences: None and null?


null isn't really a concept that exists in Python... while None fills many of 
the same roles that null does in some other languages, it is a proper object, 
with __str__ and __repr__ methods (that return 'None'), __hash__ (that returns 
an arbitrary value), etc.




I add that None is a singleton. There is only one None object.
So testing if a variable is None is done with identity check:

if var is None:
pass
--
https://mail.python.org/mailman/listinfo/python-list


Re: itertools product(infinite iterator) hangs

2019-09-13 Thread ast

Le 14/09/2019 à 04:26, Oscar Benjamin a écrit :

I've been staring at this for a little while:

from itertools import product

class Naturals:
 def __iter__(self):
 i = 1
 while True:
 yield i
 i += 1

N = Naturals()
print(iter(N))
print(product(N))  # <--- hangs

When I run the above the call to product hangs but I can't see why. I
would expect that since I'm not iterating over the product it would
just call iter(N) but clearly not since iter(N) returns a generator
instantly where as product(N) hangs.

What am I missing?

Oscar



here is a pseudo code for product:

def product(*args, repeat=1):
# product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy
# product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111
pools = [tuple(pool) for pool in args] * repeat
result = [[]]
for pool in pools:
result = [x+[y] for x in result for y in pool]
for prod in result:
yield tuple(prod)


clearly "tuple(pool)" hangs with an infinite iterable pool


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


Re: Get Count of function arguments passed in

2019-09-11 Thread ast

Le 11/09/2019 à 12:11, Sayth Renshaw a écrit :

Hi

I want to allow as many lists as needed to be passed into a function.
But how can I determine how many lists have been passed in?

I expected this to return 3 but it only returned 1.

matrix1 = [[1, -2], [-3, 4],]
matrix2 = [[2, -1], [0, -1]]
matrix3 = [[2, -1], [0, -1]]
# print(add(matrix1, matrix2))

def add(*matrix):
 print(len(locals()))

add(matrix1,matrix2,matrix3)

Cheers

Sayth



It returns 1 because there is only 1 local variable
inside function add. It's a list matrix which contains
the 3 matrix

If you want the number of arguments passed, then
just call: len(matrix)

def add(*matrix):
print(len(matrix))



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


UserList from module collections

2019-09-10 Thread ast

Hello

I read in a course that class UserList from module
collections can be used to create our own custom list

Example

>>> from collections import UserList
>>> class MyList(UserList):
... def head(self):
... return self.data[0]
... def queue(self):
... return self.data[1:]
...
>>> l = MyList([1, 2, 3])
>>> l.append(4)
>>> l
[1, 2, 3, 4]
>>> l.head()
1
>>> l.queue()
[2, 3, 4]


But I can do exactly the same without UserList


>>> class MyList(list):
def head(self):
return self[0]
def queue(self):
return self[1:]

>>> l = MyList([1, 2, 3])
>>>  l.append(4)
>>> l
[1, 2, 3, 4]
>>> l.head()
1
>>> l.queue()
[2, 3, 4]


So what UserList is used for ?
--
https://mail.python.org/mailman/listinfo/python-list


How python knows where non standard libraries are stored ?

2019-09-07 Thread ast

Hello

List sys.path contains all paths where python shall
look for libraries.

Eg on my system, here is the content of sys.path:

>>> import sys
>>> sys.path
['',
'C:\\Users\\jean-marc\\Desktop\\python',
'C:\\Program Files\\Python36-32\\python36.zip',
'C:\\Program Files\\Python36-32\\DLLs',
'C:\\Program Files\\Python36-32\\lib',
'C:\\Program Files\\Python36-32',
'C:\\Program Files\\Python36-32\\lib\\site-packages']

The last path is used as a location to store libraries
you install yourself.

If I am using a virtual environment (with venv) this last
path is different

'C:\\Users\\jean-marc\\Desktop\\myenv\\lib\\site-packages'

I looked for windows environment variables to tell python
how to fill sys.path at startup but I didn't found.

So how does it work ?
--
https://mail.python.org/mailman/listinfo/python-list


File not closed

2019-03-20 Thread ast

Hello

In the following snippet, a file is opened but
without any variable referring to it.
So the file can't be closed.

[line.split(":")[0]
 for line in open('/etc/passwd')
 if line.strip() and not line.startswith("#")]

What do you think about this practice ?



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


dash/underscore on name of package uploaded on pypi

2019-02-28 Thread ast

Hello

I just uploaded a package on pypi, whose name is "arith_lib"

The strange thing is that on pypi the package is renamed "arith-lib"
The underscore is substitued with a dash

If we search for this package:

pip search arith

arith-lib (2.0.0) - A set of functions for miscellaneous arithmetic
(so a dash)

For installation both:

pip install -U arith_lib
pip install -U arith-lib

are working well

and in both case I got a directory with an underscore

C:\Program Files\Python36-32\Lib\site-packages

28/02/2019  16:57  arith_lib
28/02/2019  16:57  arith_lib-2.0.0.dist-info

What happens ?
--
https://mail.python.org/mailman/listinfo/python-list


Quirk difference between classes and functions

2019-02-25 Thread ast

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 ?
--
https://mail.python.org/mailman/listinfo/python-list


Re: Dictionary

2019-02-25 Thread ast

Le 24/02/2019 à 05:21, Himanshu Yadav a écrit :

fibs={0:0,1:1}
def rfib(n):
   global fibs
if not fibs.get(n):
 fibs[n]=rfib(n-2)+rfib(n-1)
 return fibs[n]

Why it is gives error??



Nothing to do with the malfunction, but you dont need
to define fibs as global since you dont remap "fibs"
in side the function.

As explained by Peter, when n equals 0, not fibs.get(n)
will return True and recursivity goes on with n=-1, -2
until you reach the maximum allowed number of recursion
depth
--
https://mail.python.org/mailman/listinfo/python-list


sys.modules

2019-02-21 Thread ast

Hello

Is it normal to have 151 entries in dictionary sys.modules
just after starting IDLE or something goes wrong ?

>>> import sys
>>> len(sys.modules)
151

Most of common modules seems to be already there,
os, itertools, random 

I thought that sys.modules was containing loaded modules
with import command only.

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


Re: Why float('Nan') == float('Nan') is False

2019-02-13 Thread ast

Le 13/02/2019 à 14:21, ast a écrit :

Hello

 >>> float('Nan') == float('Nan')
False

Why ?

Regards



Thank you for answers.

If you wonder how I was trapped with it, here
is the failing program.


r = float('Nan')

while r==float('Nan'):
inp = input("Enter a number\n")
try:
r = float(inp)
except ValueError:
r = float('Nan')
--
https://mail.python.org/mailman/listinfo/python-list


Why float('Nan') == float('Nan') is False

2019-02-13 Thread ast

Hello

>>> float('Nan') == float('Nan')
False

Why ?

Regards

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


Re: Permutations using a recursive generator

2018-09-18 Thread ast

Le 18/09/2018 à 17:01, ast a écrit :

error: permut instead of S


     yield from permut(li2, prefix+[elt])

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


Permutations using a recursive generator

2018-09-18 Thread ast

Hello

I found a smart and very concise code to
generate all permutations of a list.
I put it here if someone is interested to
figure out how it works


def permut(li, prefix=[]):

if len(li)==1:
yield prefix + li
else:
for elt in li:
li2 = li.copy()
li2.remove(elt)
yield from S(li2, prefix+[elt])


exemple of usage

>>> list(permut(['a', 'b', 'c']))
[['a', 'b', 'c'], ['a', 'c', 'b'], ['b', 'a', 'c'], ['b', 'c', 'a'], 
['c', 'a', 'b'], ['c', 'b', 'a']]


>>> list(permut([0,1,2,3]))
[[0, 1, 2, 3], [0, 1, 3, 2], [0, 2, 1, 3], [0, 2, 3, 1], [0, 3, 1, 2], 
[0, 3, 2, 1], [1, 0, 2, 3], [1, 0, 3, 2], [1, 2, 0, 3], [1, 2, 3, 0], 
[1, 3, 0, 2], [1, 3, 2, 0], [2, 0, 1, 3], [2, 0, 3, 1], [2, 1, 0, 3], 
[2, 1, 3, 0], [2, 3, 0, 1], [2, 3, 1, 0], [3, 0, 1, 2], [3, 0, 2, 1], 
[3, 1, 0, 2], [3, 1, 2, 0], [3, 2, 0, 1], [3, 2, 1, 0]]

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


Re: Speed of animation with matplotlib.animation

2018-06-19 Thread ast

Le 19/06/2018 à 11:47, Peter Otten a écrit :

ast wrote:


Le 19/06/2018 à 10:57, Peter Otten a écrit :

ast wrote:






No, with dt = 100 it should last

200 * 100ms = 20.000ms = 20s

with dt = 0.1 it should last

200 * 0.1ms = 20ms = 0.02s

but your computer is probably not fast enough for that.




You are right. I didn't noticed that interval was in ms
Ty
--
https://mail.python.org/mailman/listinfo/python-list


Re: Speed of animation with matplotlib.animation

2018-06-19 Thread ast

Le 19/06/2018 à 10:57, Peter Otten a écrit :

ast wrote:


I noticed that the speed of animations made
with module matplotlib.animation always seems
wrong.



dt = 0.1  # 100 ms
  

interval : number, optional

  Delay between frames in milliseconds. Defaults to 200.


What's wrong ?



From the above I would conclude that you get a 100 ms delay with


dt = 100




So the animation should last 200*0.1 = 20s
but it is twice faster
--
https://mail.python.org/mailman/listinfo/python-list


Speed of animation with matplotlib.animation

2018-06-19 Thread ast

Hello

I noticed that the speed of animations made
with module matplotlib.animation always seems
wrong.

Here is a small example for demonstration purpose:


import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

fig = plt.figure()
ax = fig.add_subplot(111)
txt = ax.text(0.5, 0.5, "", transform=ax.transAxes)

dt = 0.1  # 100 ms

def animate(i):
txt.set_text("time= %.1f" % (i*dt))
return txt,


ani = animation.FuncAnimation(fig=fig,
  func=animate,
  frames = 200,
  interval = dt,
  blit = True,
  repeat=False)

plt.show()

--
so function animate is ran every interval=dt=100ms
with i=0, 1, 2, ..., 200 and it simply prints time
(i*dt) on the figure.

The animation should last 20s, but on my computer
it is twice faster

A link to FuncAnimation doc: https://bit.ly/2t5UKjA

interval : number, optional

Delay between frames in milliseconds. Defaults to 200.


What's wrong ?
--
https://mail.python.org/mailman/listinfo/python-list


round

2018-06-07 Thread ast

Hi

round is supposed to provide an integer when
called without any precision argument.

here is the doc:

>>> help(round)

round(number[, ndigits]) -> number

Round a number to a given precision in decimal digits (default 0 digits).
This returns an int when called with one argument, otherwise the
same type as the number

but in some circumstances it provides a float

import numpy as np

M = np.array([[0, 9],[2, 7]], dtype=int)
np.linalg.det(M)
-18.004
round(np.linalg.det(M))
-18.0 # i was expecting an integer -18, not a float

# same problem with np.round
np.round(np.linalg.det(M))
-18.0
--
https://mail.python.org/mailman/listinfo/python-list


Re: Entering a very large number

2018-03-25 Thread ast

Le 25/03/2018 à 03:47, Steven D'Aprano a écrit :

On Sun, 25 Mar 2018 00:05:56 +0100, Peter J. Holzer wrote:






The Original Poster (OP) is concerned about saving, what, a tenth of a
microsecond in total? Hardly seems worth the effort, especially if you're
going to end up with something even slower.




I regret that many answers are malicious, as your.

The question was how to enter a large number without
going through a string, no matter why.
This question is absolutely legitimate, contrary to
some people think.
It seems that it is not feasible unless writting it in
a single line, which is awful.
OK, go on with the string, and Wolfgang solution using
triple quote is good.





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


Re: Entering a very large number

2018-03-23 Thread ast

Le 23/03/2018 à 14:16, Antoon Pardon a écrit :

On 23-03-18 14:01, ast wrote:

Le 23/03/2018 à 13:43, Rustom Mody a écrit :

On Friday, March 23, 2018 at 5:46:56 PM UTC+5:30, ast wrote:




What meaningful information from number can you easily retrieve from
representing the number in some kind of table form that you can't from
just writing the number on one line?



digit n° 103 is 1
digit n° 150 is 7
...

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


Re: Entering a very large number

2018-03-23 Thread ast

Le 23/03/2018 à 13:55, Wolfgang Maier a écrit :

On 03/23/2018 01:30 PM, Wolfgang Maier wrote:

On 03/23/2018 01:16 PM, ast wrote:




n = int(
     ''.join("""
37107287533902102798797998220837590246510135740250
46376937677490009712648124896970078050417018260538
74324986199524741059474233309513058123726617309629

...


45876576172410976447339110607218265236877223636045
17423706905851860660448207621209813287860733969412
""".split())
)



yes, good idea

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


Re: Entering a very large number

2018-03-23 Thread ast

Le 23/03/2018 à 13:30, Wolfgang Maier a écrit :

On 03/23/2018 01:16 PM, ast wrote:




A very simple improvement would be to use a single
triple-quoted string. Assuming you are copy/pasting
the number from somewhere that will save a lot of your
time.


no, it seems that sone \n are inserted inside the number

>>> C = int("""
1234
5678""")

Traceback (most recent call last):
  File "", line 3, in 
5678""")
ValueError: invalid literal for int() with base 10: '\n1234\n5678'


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


Re: Entering a very large number

2018-03-23 Thread ast

Le 23/03/2018 à 13:43, Rustom Mody a écrit :

On Friday, March 23, 2018 at 5:46:56 PM UTC+5:30, ast wrote:

Hi

I found this way to put a large number in
a variable.


What stops you from entering the number on one single (v long) line?



It is not beautiful and not very readable. It is better to
have a fixed number of digits per line (eg 50)

import this

Beautiful is better than ugly.
Readability counts.




In case there is a religious commitment to PEP 8 dicta, the recommended
meditation is this line (also from PEP8):

"However, know when to be inconsistent -- sometimes style guide recommendations just 
aren't applicable"



Yes I am using pylint which flags too long lines (80 characters)
--
https://mail.python.org/mailman/listinfo/python-list


Entering a very large number

2018-03-23 Thread ast

Hi

I found this way to put a large number in
a variable.

C = int(
"28871482380507712126714295971303939919776094592797"
"22700926516024197432303799152733116328983144639225"
"94197780311092934965557841894944174093380561511397"
"4215424169339729054237110027510420801349667317"
"5515285922696291677532547505856101949404200039"
"90443211677661994962953925045269871932907037356403"
"22737012784538991261203092448414947289768854060249"
"76768122077071687938121709811322297802059565867")

It works but is it not optimal since there is a
string to int conversion.

I was not able to put an integer directly because
character '\' for line cut doesnt work inside an
integer

C = \
28871482380507712126714295971303939919776094592797\
22700926516024197432303799152733116328983144639225\
...
76768122077071687938121709811322297802059565867

doesn't work

Do you have a better idea ?

Thx


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


Re: How to make Python run as fast (or faster) than Julia

2018-02-22 Thread ast

Le 22/02/2018 à 19:53, Chris Angelico a écrit :

On Fri, Feb 23, 2018 at 2:15 AM, ast  wrote:

Le 22/02/2018 à 13:03, bartc a écrit :


On 22/02/2018 10:59, Steven D'Aprano wrote:







for count in 1, 10, 100, 1000:
 print(count, timeit("cache(maxsize=None)(fib)(20)", setup=setup,
number=count))



 hum ... very astute


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


Re: How to make Python run as fast (or faster) than Julia

2018-02-22 Thread ast

Le 22/02/2018 à 13:03, bartc a écrit :

On 22/02/2018 10:59, Steven D'Aprano wrote:
https://www.ibm.com/developerworks/community/blogs/jfp/entry/Python_Meets_Julia_Micro_Performance?lang=en 



While an interesting article on speed-up techniques, that seems to miss 
the point of benchmarks.


On the fib(20) test, it suggests using this to get a 30,000 times speed-up:

     from functools import lru_cache as cache

     @cache(maxsize=None)
     def fib_cache(n):
     if n<2:
     return n
     return fib_cache(n-1)+fib_cache(n-2)



It's a meaningless to test the execution time of a function
with a cache decorator on 1.000.000 loops

The first execution, ok, you get something meaningfull
but for the other 999.999 executions, the result is already on
the cache so you just measure the time to read the result
in a dictionnary and output it.

On my computer:

>>> setup = """\
from functools import lru_cache as cache
@cache(maxsize=None)
def fib(n):
if n < 2: return n
return fib(n-1) + fib(n-2)
"""
>>> from timeit import timeit

>>> timeit("fib(20)", setup=setup, number=1)
0.00010329007704967808

>>> timeit("fib(20)", setup=setup, number=100)
0.0001489834564836201

so 100 loops or 1 loop provides similar results
as expected !





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


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

2018-02-22 Thread ast

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   |   +   +

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


Re: Writing some floats in a file in an efficient way

2018-02-22 Thread ast

Le 21/02/2018 à 18:23, bartc a écrit :

On 21/02/2018 15:54, ast wrote:

Le 21/02/2018 à 15:02, bartc a écrit :

On 21/02/2018 13:27, ast wrote:




Time efficient or space efficient?


space efficient


If the latter, how many floats are we talking about?


10^9






Although it might be better to convert to proper 32-bit float format in 
this case. This will halve space and probably time requirements.)




Yes, storing 32 bits only floats is a good idea.
and the good news is that struct.pack() does the job.

from struct import *

>>> pack('>ff', 3.1234, 5.3e-7)
b'@G\xe5\xc95\x0eES'  # 2*4 bytes

>>> unpack('>ff', b'@G\xe5\xc95\x0eES')
(3.1233999729156494, 5.30225361146e-07)

What happens if we input some out of range floats ?

>>> pack('>dd', 3.1e-500, 5.3e400)
b'\x00\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\x00\x00\x00\x00\x00'
>>> unpack('>dd', 
b'\x00\x00\x00\x00\x00\x00\x00\x00\x7f\xf0\x00\x00\x00\x00\x00\x00')

(0.0, inf)

So underflow/overflow are well handled

I saw there is a half precision float too, on 16 bits, but it is
really unaccurate

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


Re: Writing some floats in a file in an efficient way

2018-02-21 Thread ast

Le 21/02/2018 à 14:27, ast a écrit :

struct.pack() as advised works fine.
Exemple:

>>> import struct
>>> struct.pack(">d", -0.0)
b'\x80\x00\x00\x00\x00\x00\x00\x00'

before I read your answers I found a way
with pickle

>>> import pickle
>>> pickle.dumps(-0.0)[3:-1]
b'\x80\x00\x00\x00\x00\x00\x00\x00'

but struct.pack() is better
Thx


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


Re: Writing some floats in a file in an efficient way

2018-02-21 Thread ast

Le 21/02/2018 à 15:02, bartc a écrit :

On 21/02/2018 13:27, ast wrote:




Time efficient or space efficient?


space efficient


If the latter, how many floats are we talking about?


10^9




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


Writing some floats in a file in an efficient way

2018-02-21 Thread ast

Hello

I would like to write a huge file of double precision
floats, 8 bytes each, using IEEE754 standard. Since
the file is big, it has to be done in an efficient
way.

I tried pickle module but unfortunately it writes
12 bytes per float instead of just 8.

Example:

import pickle

f = open("data.bin", "wb")
mypickler = pickle.Pickler(f)

mypickler.dump(0.0)
mypickler.dump(-0.0)

f.close()

Let's see what file data.bin contains now:

80 03 47
00 00 00 00 00 00 00 00
2E
80 03 47
80 00 00 00 00 00 00 00
2E

We see our 2 floats
00 00 00 00 00 00 00 00
which is the IEEE754 representation for 0.0 and
80 00 00 00 00 00 00 00
which is the IEEE754 representation for -0.0
yes, there are two 0 for floats, a positive and
a negative one ;-)

but there is a 3 bytes overhead 80 03 47 and an
ending byte 2E for each float. This is a 50% overhead.

Is there a way to write a float with only 8 bytes ?

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


Re: Old format with %

2018-02-14 Thread ast

Le 14/02/2018 à 13:46, ast a écrit :

Hello

It seems that caracter % can't be escaped

 >>>"test %d %" % 7
ValueError: incomplete format

 >>>"test %d \%" % 7
ValueError: incomplete format

 >>>"test %d" % 7 + "%"
'test 7%'  # OK

But is there a way to escape a % ?

thx


Found, double % to escape it

>>>"test %d%%" % 7
'test 7%'
--
https://mail.python.org/mailman/listinfo/python-list


Old format with %

2018-02-14 Thread ast

Hello

It seems that caracter % can't be escaped

>>>"test %d %" % 7
ValueError: incomplete format

>>>"test %d \%" % 7
ValueError: incomplete format

>>>"test %d" % 7 + "%"
'test 7%'  # OK

But is there a way to escape a % ?

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


Re: Problem with timeit

2017-12-18 Thread ast


"Steve D'Aprano"  a écrit dans le message de 
news:5a33d0fc$0$2087$b1db1813$d948b...@news.astraweb.com...

On Sat, 16 Dec 2017 12:25 am, ast wrote:



"Thomas Jollans"  a écrit dans le message de
news:mailman.74.1513341235.14074.python-l...@python.org...

On 2017-12-15 11:36, ast wrote:








py> x = 123456**123456
py> s = str(x)
py> len(s)
628578




I discovered that log functions from math module
works with integers, whatever their size, there is
no conversion to float.


import math
x = 123456**123456
math.log10(x)

628577.7303641582   (instantaneous)

so 628578 digits


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


Re: Problem with timeit

2017-12-15 Thread ast


"ast"  a écrit dans le message de 
news:5a33a5aa$0$10195$426a7...@news.free.fr...

Ty Peter and Steve, I would never have found that
explanation myself 


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


Re: Problem with timeit

2017-12-15 Thread ast


"Thomas Jollans"  a écrit dans le message de 
news:mailman.74.1513341235.14074.python-l...@python.org...

On 2017-12-15 11:36, ast wrote:




No, this is right. The calculation takes practically no time; on my
system, it takes some 10 ns. The uncertainty of the timeit result is at
least a few hundred nanoseconds.


There are more than 10 multiplications to perform on a
soaring size integer. I have some doubts "x=123456**123456 "
only takes 10 ns on your system.

On my computer it takes roughtly 4 s, mesured with a watch.
I can't do "len(str(x))" to know the size, I have to kill the process
But x.bit_length() answers 2088091, so x should have about
60 digits

If I measure execution time:


t=time(); x=123456**123456; print(time()-t)

0.0

There is still something wrong

I suppose that my computer CPU goes to 100% busy and
that the timer used by timeit or time no longer works.






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


Problem with timeit

2017-12-15 Thread ast

Hi

Time measurment with module timeit seems to work with some 
statements but not with some other statements on my computer.


Python version 3.6.3

from timeit import Timer


Timer("'-'.join([str(i) for i in range(10)])").timeit(1)

0.179271876732912

Timer("'-'.join([str(i) for i in range(10)])").timeit(10)

1.7445643231192776

It's OK, with 10 more loops I get 10 more execution time.

But with exponentiation, it's a mess


Timer("x=123456**123456").timeit(1)

6.076191311876755e-06

Timer("x=123456**123456").timeit(10)

3.841270313387213e-06

All wrong, the calculation of 123456**123456 is much longer
than 6 microseconds, it takes few seconds, and with 10 loops 
timeit provided a shorter time ...


What happens plz ?

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


Re: asyncio awaitable object

2017-12-08 Thread ast


"ast"  a écrit dans le message de 
news:5a2a568c$0$3699$426a7...@news.free.fr...

I made some experiment.

It seems that the iterator shall provide None values, an other value
raises an exception: "RuntimeError: Task got bad yield: 1"

and in instruction "res = await obj", res got the StopIteration exception
value

See my test program and output.

import asyncio

class Test:

   def __init__(self):
   self.i = 0
   def __await__(self):
   return self
   def __iter__(self):
   return self
   def __next__(self):
   if self.i < 5:
   self.i += 1
   return None
   else:
   raise StopIteration(11)

test = Test()

async def coro1():
   print("Enter coro1")
   res = await test
   print("end of coro1, res= ", res)

async def coro2():
   print("Enter coro2")
   for i in range(8):
   print("in coro2")
   await asyncio.sleep(0)

loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait([coro1(), coro2()]))

== RESTART ==
Enter coro1
Enter coro2
in coro2
in coro2
in coro2
in coro2
in coro2
end of coro1, res=  11
in coro2
in coro2
in coro2 


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


asyncio awaitable object

2017-12-08 Thread ast

Hello,

According to: 
https://www.python.org/dev/peps/pep-0492/#await-expression

an awaitable object is:

- A native coroutine object returned from a native coroutine function
- A generator-based coroutine object returned from a function decorated 
with types.coroutine()

- An object with an __await__ method returning an iterator

I dont understand the last one.

For example in instruction "res = await obj"

where obj has a __await__ method returning an iterator

What kind of data this generator is supposed to provide when next() 
is applied to it and what are these data becoming ?


what res contains when the iterator has finished to iterate ?

It seems that PEP492 documentation says nothing about it (or I dont 
understand, english is not my native language)










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


asyncio loop.call_soon()

2017-11-28 Thread ast

Hello

Python's doc says about loop.call_soon(callback, *arg):

Arrange for a callback to be called as soon as possible. The callback is called 
after call_soon() returns, when control returns to the event loop.


But it doesn't seem to be true; see this program:

import asyncio

async def task_func():
   print("Entering task_func")

def callback():
   print("Entering callback")

async def main():
   print("Entering main")
   task = loop.create_task(task_func())
   loop.call_soon(callback)
   await task

loop = asyncio.get_event_loop()
loop.run_until_complete(main())

Execution provides following output:

Entering main
Entering task_func
Entering callback

callback is executed AFTER task_func, I expected it
to be executed BEFORE.

When "main()" coroutine reach line "await task", it let the control 
to the event loop, and it seems that the loop starts to execute 
task instead of callback. Then, when task is over the loop runs 
callback


This is not what the doc says: callback should be called as soon
as possible when the loop has control, with a priority over other
tasks pending in the loop








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


  1   2   3   >