Re: A missing iterator on itertools module?
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?
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?
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
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)
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
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
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)
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)
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
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
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
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
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
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
> li = [] > li.append(li) > li [[...]] >li[0][0][0][0] [[...]] That's funny -- https://mail.python.org/mailman/listinfo/python-list
Inheriting from str
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
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
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
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
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
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
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
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
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
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
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
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
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 ?
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
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
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.
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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?
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
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
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
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 ?
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
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
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
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
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
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
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
Hello >>> float('Nan') == float('Nan') False Why ? Regards -- https://mail.python.org/mailman/listinfo/python-list
Re: Permutations using a recursive generator
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
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
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
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
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
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
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
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
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
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
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
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
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
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 ...)
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
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
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
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
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 %
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 %
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
"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
"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
"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
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
"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
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()
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