Re: pathlib PurePosixPath
On 10/10/2017 08:44, Sayth Renshaw wrote: > >>> Hi >>> >>> How do I create a valid file name and directory with pathlib? >>> >>> When I create it using PurePosixPath I end up with an OSError due to an >>> obvously invlaid path being created. >> >> You're on Windows. The rules for POSIX paths don't apply to your file >> system, and... >> >>> OSError: [Errno 22] Invalid argument: >>> 'C:\\Users\\Sayth\\Projects\\results/Warwick Farm2017-09-06T00:00:00.json' >> >> ... the colon is invalid on Windows file systems. You'll have to >> replace those with something else. >> >> ChrisA > > Thanks. Updated the script. But shouldn't it create the file if it doesn't > exist? Which none of them will. The documentation says "Pure path objects provide path-handling operations which don’t actually access a filesystem". But the "Concrete paths" subclass is described later with support for a number of file system operations. -- https://mail.python.org/mailman/listinfo/python-list
Re: comprehension parsing
On 05/11/2022 22:11, MRAB wrote: On 2022-11-05 18:52, cactus wrote: On Saturday, 5 November 2022 at 16:06:52 UTC, cactus wrote: I should have quoted the full comprehensions: all((srt(m, n) in c_np) == (srt(a, b) in c_ap) for (m, a), (n, b) in combinations(na8, 2)) all( srt(m, n) in c_np == srt(a, b) in c_ap) for (m, a), (n, b) in combinations(na8, 2)) The comparison operators can be chained, so: a == b == c is equivalent to: (a == b) and (b == c) except that the common term ('b' in this case) is evaluated only once. 'in' is one of those comparison operators, so: srt(m, n) in c_np == srt(a, b) in c_ap is equivalent to: (srt(m, n) in c_np) and (c_np == srt(a, b)) and (srt(a, b) in c_ap) except that the common terms ('c_np' and 'srt(a, b)') are evaluated only once. Chaining makes most sense with multiple '==' or a series of '<' and/or '<=' or a series of '>' and/or '>=', as in '1 <= n <= 10'. Thanks for a most helpful explanation -- https://mail.python.org/mailman/listinfo/python-list
Does os.path relpath produce an incorrect relative path?
I am wondering whether I have misunderstood the semantics of os.path relpath or whether it has a bug. Here is a short test program: --- from os.path import relpath, split src_path = 'C:\\lib\\src\\' vcx_path = 'C:\\build.vs22\\lib\\lib.vcxproj' rel_path = relpath(src_path, vcx_path) print(f"{vcx_path = }\n{src_path = }\n{rel_path = }\n") vcx_path = 'C:\\build.vs22\\lib\\' rel_path = relpath(src_path, vcx_path) print(f"{vcx_path = }\n{src_path = }\n{rel_path = }\n") vcx_path = 'C:\\build.vs22\\lib\\lib.vcxproj' rel_path = relpath(src_path, split(vcx_path)[0]) print(f"{vcx_path = }\n{src_path = }\n{rel_path = }\n") --- and its output with Python 3.11: --- vcx_path = 'C:\\build.vs22\\lib\\lib.vcxproj' src_path = 'C:\\lib\\src\\' rel_path = '..\\..\\..\\lib\\src' vcx_path = 'C:\\build.vs22\\lib\\' src_path = 'C:\\lib\\src\\' rel_path = '..\\..\\lib\\src' vcx_path = 'C:\\build.vs22\\lib\\lib.vcxproj' src_path = 'C:\\lib\\src\\' rel_path = '..\\..\\lib\\src' --- The first of these three results produces an incorrect relative path because relpath does not strip off any non-directory tails before comparing paths. Is this a bug or my misunderstanding of relpath semantics? Comments would be appreciated as I don't waste developer time if this is not a bug. regards Brian -- https://mail.python.org/mailman/listinfo/python-list
Re: Does os.path relpath produce an incorrect relative path?
On 26/05/2023 16:42, Eryk Sun wrote: On 5/26/23, cactus wrote: Surprisingly (for me at least) the alternative provided by the pathlib module 'relative_to' method doesn't provide for full relative path computation. I was expecting this would offer everything that os.path offers but it doesn't in this case. Starting with Python 3.12, the relative_to() method has a walk_up parameter. It defaults to False for the sake of backward compatibility. https://docs.python.org/3.12/library/pathlib.html#pathlib.PurePath.relative_to Thanks, it is good to know that this is coming. Brian -- https://mail.python.org/mailman/listinfo/python-list
Behaviour of pop() for dictionaries
The pop() method exists for five mainstream data items and shows a range of different behaviours for each of them. But, of the five, pop for dictionaries is the only one for which the first parameter is required and this makes d.pop() for dictionaries an error rather than doing something useful. I came across this in trying to use this sequence for a dictionary : if len(d.keys()) == 1: v = d.pop() I found it surprising that this failed given how the pops for the other types work. So I then tried: v = d.values()[0] and this doesn't work either since dict_keys items don't accept indexing. So I was driven to use: v = list(d.values())[0] which seems to me a lot less intuitive (and messier) than d.pop(). These: v = next(iter(d.values())) v, = d.values() also seem poor substitutes for giving d.pop() for dictionaries a useful and intuitive purpose. Am I missing the obvious way to obtain the value (or the key) from a dictionary that is known to hold only one item? More importantly, is there a good reason why we don't have d.pop() for dictionaries? Brian -- https://mail.python.org/mailman/listinfo/python-list
Re: Behaviour of pop() for dictionaries
On 14/06/2021 08:29, Greg Ewing wrote: On 14/06/21 4:19 am, BlindAnagram wrote: Am I missing the obvious way to obtain the value (or the key) from a dictionary that is known to hold only one item? v = d.popitem()[1] Thanks, Greg, I missed that. More importantly, is there a good reason why we don't have d.pop() for dictionaries? My guess is because it's not generally useful to get an returns the value arbitrary value from a dict without its corresponding key. Hence the existence of popitem(). However, d.pop(key, [default]) returns the value (or the default) and consistency with other pops (a good thing in my view) would suggest that d.pop() could return a random value, which would serve my purpose when there is only one element. -- https://mail.python.org/mailman/listinfo/python-list
Re: Behaviour of pop() for dictionaries
On 14/06/2021 20:43, Chris Angelico wrote: On Tue, Jun 15, 2021 at 5:41 AM BlindAnagram wrote: However, d.pop(key, [default]) returns the value (or the default) and consistency with other pops (a good thing in my view) would suggest that d.pop() could return a random value, which would serve my purpose when there is only one element. Is this actually important or are you just looking for a meaningless "inconsistency"? Dictionaries are fundamentally different from lists. Is it really that hard to use popitem? No I am not looking for meaningless inconsistency - just the opposite in fact - meaningful consistency. I believe that consistency in how methods common to different types work is useful since it adds to the coherence of the language as a whole and avoids the need to remember special cases. No it isn't hard to use popitem() but it evidently proved hard for me to remember that it was there. Brian -- https://mail.python.org/mailman/listinfo/python-list
Re: Behaviour of pop() for dictionaries
On 15/06/2021 00:11, dn wrote: On 15/06/2021 09.18, BlindAnagram wrote: On 14/06/2021 20:43, Chris Angelico wrote: On Tue, Jun 15, 2021 at 5:41 AM BlindAnagram ... No it isn't hard to use popitem() but it evidently proved hard for me to remember that it was there. If that's a problem, you're going to love using deques with their 'popping from the left' and 'popping from the right' concepts! I think the difference here is that I know I am going to have to look at the documentation for dequeue when I want to use it. For lists, sets and dictionaries, I don't expect to look at the documentation and pop() seemed a good bet for what I wanted to do. I don't know if you are ComSc student or not, but there isn't even consistency at the theoretical level. I first arrived at the concept of "queuing" and "dequeuing" (NB the latter is not the same as the Python Collections module "deque" library) whilst studying Queue Theory in Operations Research. At about the same time, my ComSc studies took me into "stacks". My student days are well over (about 60 years over). Queues are known as FIFO constructs - "first-in, first-out". Stacks are somewhat the opposite: LIFO - "last-in, first-out". The "pop" operation was defined as taking the "next" item from the queue or the "last" item from a stack (the opposite of "push"). However, between queue and stack, the term "next" refers to opposite ends of the (implementing in Python) list! In fact, coming from a Burroughs mainframe, which ran on "stack architecture" (cf IBM's multiplicity of "ALU registers"), it came as something of a surprise when programming languages started allowing me to "pop" elements that weren't at the LIFO-end of the 'list', eg list.pop( 3 ) where len( list ) > 4! Next consider how the terms "next" and "element" factor into the thinking. If we consider a (Python) list there is an implied sequence of elements based upon their relative position. Notice also that the basic implementation of list.pop() is LIFO! Whereas, the definition of a set involves no concept of sequence or order - only of membership (and that the elements are "hashable"). Accordingly, a pop() operation returns an "arbitrary value", cf 'next please'. Similarly, a dict's keys are referred-to as hashable, with the idea of "random access" to an element via its key (cf the "sequential access" of a list). Thus, we can ask to pop() a dict, but only if we provide a key - in which case, pop( key ) is the same as dict[ key ] except that the key-value pair is also removed from the dict! Recall though, it is possible to use list.pop() without any argument. So, consistency has been thrown-out-the-window there as well. Also, with LIFO in-mind, Python v3.7 brought a concept of 'sequence' (population order) to dicts, and thus we now have this "guarantee" in popitem() - and thus a memory-confusion for those of us who learned the original "arbitrary" definition - confusion both of dict behavior and of dict.popitem() specifically! Worse confusion awaits (and referring to a conversation 'here' last week) Python's pop() exhibits elements of both an "expression" and of a "statement", ie it not only returns a value, but it affects (?"side-effects") the underlying collection. Thus, no pop() for strings, tuples, etc, because they are immutable collections! The action of pop() is clearly inconsistent across types of collection. It's effect is data-structure dependent because the purposes of those structures are inherently different. "Consistency" would aid memory, but "polymorphism" can only deliver functionality according to the characteristics of the specific data-type! Yes, but we can still seek consistency where it is possible Having entered the queue-of-life a long time ago, and shuffling ever closer to 'the end of the line', this memory-challenged 'silver-surfer' prefers to reserve pop() for straightforward stacks and lists, which implies quite enough inconsistency, without trying to convolute my mind to pop()-ing dicts, sets (or 'worse'!). That said, whether I actually use dict.pop() or not, these 'features' which are consistent in name but not necessarily in arguments or effects, contribute to Python's great flexibility and power! Thank goodness for help() and the Python docs... I don't like 'pop's at all since it meant that a valve had exploded on the Ferranti Pegasus that was my first encounter with computers. Brian -- https://mail.python.org/mailman/listinfo/python-list
Re: Behaviour of pop() for dictionaries
On 15/06/2021 01:36, Terry Reedy wrote: On 6/14/2021 5:18 PM, BlindAnagram wrote: I believe that consistency in how methods common to different types work is useful since it adds to the coherence of the language as a whole and avoids the need to remember special cases. Each collection class *is* a special case, and pop has to be adjusted to each. However, you seem to have missed an essential commonality. Lists and dicts are both subscripted classes. So the basic API is col.pop(sub), which removes and returns the sub item, whereas col[sub] leaves and returns. Lists have a special index, -1, the most commonly used, so that is the default. In fact, when I proposed list.pop(), I only proposed that, as I wanted pop to be the inverse of append, so a list could be used as a stack. Bad list subscripts are an error (unless one is slicing), whereas where dicts allow a default (when subscripted with the get method). Hence the optional default only for dicts. At one time, dicts, like sets, were unordered collections (of functional item pairs). dict.pop(), with no arg, could have been used to return a random 2-ple, but Guido is generally against having return types depend on arguments. So a new popxxx name was added. Note that deques have a popleft in addition to pop (right). Thanks for the interesting history. Having found that dict.pop() caused an error, I did wonder whether it should have returned a (key, value) pair but quickly came to the conclusion that this would be awful because it would be inconsistent with the normal value returned by pop(x). Sadly this did not result in any recollection that there was a popitem() :-( Brian -- https://mail.python.org/mailman/listinfo/python-list
Global VS Local Subroutines
Is there any difference in performance between these two program layouts: def a(): ... def(b): c = a(b) or def(b): def a(): ... c = a(b) I would appreciate any insights on which layout to choose in which circumstances. -- https://mail.python.org/mailman/listinfo/python-list
Re: Global VS Local Subroutines
On 10/02/2022 15:20, Chris Angelico wrote: On Fri, 11 Feb 2022 at 02:13, BlindAnagram wrote: Is there any difference in performance between these two program layouts: def a(): ... def(b): c = a(b) or def(b): def a(): ... c = a(b) I would appreciate any insights on which layout to choose in which circumstances. Great question! The difference is that, in the second case, a() isn't available anywhere else. So the real question is: Is that good or bad? Does it make sense to call a() from outside of your second function, even for testing? If so, maybe name it _a() so it's private, but keep it global. Does a() need a lot of information from the context of your second function? If so, it's easier to have a closure, with one function inside another. Both styles make sense, and your question is well put: it's a design decision with no "right" or "wrong", just different choices with different implications. ChrisA Thanks Chris, I thought it was mostly a design choice but I wasn't sure whether there would be any significant performance issues. Brian -- https://mail.python.org/mailman/listinfo/python-list
Re: Global VS Local Subroutines
On 10/02/2022 16:52, Rob Cliffe wrote: On 10/02/2022 12:13, BlindAnagram wrote: Is there any difference in performance between these two program layouts: def a(): ... def(b): c = a(b) or def(b): def a(): ... c = a(b) I would appreciate any insights on which layout to choose in which circumstances. The way to answer questions about performance is not to guess (often difficult or impossible), but to measure. Profiling tools are available to see where a program spends how much of its time. But a simpler approach might be to try to run the guts of your program 1000 or 100 times, and find how long it takes with each layout (not with a stopwatch 😁 but getting the program to record the start time, end time and the difference). That said, I will venture a guess (or at least, an observation): def a(): ... Thanks for the suggestion, Rob. I considered doing this but it would take quite a bit of careful work to be sure of obtaining meaningful results so I felt it better to ask the question here in case there was an quick answer on performance before doing the hard work. is executable code. It creates the function `a` which did not exist before (or creates the new version if it did). This takes a certain amount of time. In your 2nd layout, this overhead occurs every time b() is called. So I would *guess* that this would be slower. Of course it depends on how many times b() is called and probably on lots of other things. This is exactly what I felt too but I then wondered if the code was recreated dynamically or was static with just a reference being created on each invocation of the parent. The overhead in this case would be negligible. But then I thought 'what about the context for the inner function invocation' - maybe its not as simple as this! Oh dear, I need to understand Python's internals. At which point I asked the question! Brian -- https://mail.python.org/mailman/listinfo/python-list
Enigma 1140 - link problem
Hi Jim, In my comment/solution for this Enigma I tried to post a link to my number theory library but my HTML got removed. Could you please replace the first sentence with: A solution using my http://173.254.28.24/~brgladma/number_theory.py";>number theory library: (without the line wrapping). thanks Brian -- https://mail.python.org/mailman/listinfo/python-list
Matplotlib and Python 3.7
Now that Python 3.7 has reached release candidate status, I thought that I should try it. But I use Matplotlib a lot and this fails to install with Python 3.7 because "freetype and png cannot be installed" (I am using Windows 10). I am wondering if anyone knows how to work around this issue? I looked for a way to report the issue to the Matplotlib team but the only forum I could find for reporting issues required me to create an account, which I don't want to do. -- https://mail.python.org/mailman/listinfo/python-list
Python 3.7 Windows Help Behaviour
In Python 3.7.0 on Windows the help file (python370.chm) displays with a fixed line length and does not adjust its line length when the user expands the help window horizontally. This behaviour is different to that of the Python 3.6 help file (python360.chm) which adjusts its text to fit the horizontal width of the help window. Is this a deliberate change or one that can be turned on or off in some way (I prefer the Python 3.6 behaviour)? -- https://mail.python.org/mailman/listinfo/python-list
Re: Python 3.7 Windows Help Behaviour
On 29/06/2018 17:53, Terry Reedy wrote: > On 6/29/2018 6:14 AM, BlindAnagram wrote: >> In Python 3.7.0 on Windows the help file (python370.chm) displays with a >> fixed line length and does not adjust its line length when the user >> expands the help window horizontally. This behaviour is different to >> that of the Python 3.6 help file (python360.chm) which adjusts its text >> to fit the horizontal width of the help window. >> >> Is this a deliberate change or one that can be turned on or off in some >> way (I prefer the Python 3.6 behaviour)? > > I believe that this is a deliberate regression imposed by 'experts' who > believe in form over function and 'controlling the user experience'. > 3.6.6 has been 'fixated' also. Thank you for your response. If you are right it is a pity that the user choice of width has been removed since it now looks stupidly narrow on my high resolution display. It looks like I will have to use the Python 3.6 file even in Python 3.7 :-( -- https://mail.python.org/mailman/listinfo/python-list
Re: Python 3.7 Windows Help Behaviour
On 30/06/2018 10:43, Steven D'Aprano wrote: > On Fri, 29 Jun 2018 12:53:15 -0400, Terry Reedy wrote: > >> On 6/29/2018 6:14 AM, BlindAnagram wrote: >>> In Python 3.7.0 on Windows the help file (python370.chm) displays with >>> a fixed line length and does not adjust its line length when the user >>> expands the help window horizontally. This behaviour is different to >>> that of the Python 3.6 help file (python360.chm) which adjusts its text >>> to fit the horizontal width of the help window. >>> >>> Is this a deliberate change or one that can be turned on or off in some >>> way (I prefer the Python 3.6 behaviour)? >> >> I believe that this is a deliberate regression imposed by 'experts' who >> believe in form over function and 'controlling the user experience'. >> 3.6.6 has been 'fixated' also. > > Sounds like somebody should raise a bug report. I see that this has been done: https://bugs.python.org/issue34006 -- https://mail.python.org/mailman/listinfo/python-list
Re: Python 3.7 Windows Help Behaviour
On 03/07/2018 03:41, Terry Reedy wrote: > On 7/2/2018 8:57 PM, Steven D'Aprano wrote: >> On Fri, 29 Jun 2018 12:53:15 -0400, Terry Reedy wrote: >> >>> On 6/29/2018 6:14 AM, BlindAnagram wrote: >>>> In Python 3.7.0 on Windows the help file (python370.chm) displays with >>>> a fixed line length and does not adjust its line length when the user >>>> expands the help window horizontally. This behaviour is different to >>>> that of the Python 3.6 help file (python360.chm) which adjusts its text >>>> to fit the horizontal width of the help window. >>>> >>>> Is this a deliberate change or one that can be turned on or off in some >>>> way (I prefer the Python 3.6 behaviour)? >>> >>> I believe that this is a deliberate regression imposed by 'experts' who >>> believe in form over function and 'controlling the user experience'. >>> 3.6.6 has been 'fixated' also. >> >> I think that's been reverted: >> >> https://github.com/python/cpython/commit/580c7db172a41d6311c0f3a7aec321597576e214 >> > > Yes, I wrote the blurb, merged it, and ordered and approved the backports. >Thank you, Terry (and others who contributed), for your help with this - I much appreciate all your efforts. Brian -- https://mail.python.org/mailman/listinfo/python-list
Re: Serious error in int() function?
On 13/04/2016 08:41, martin.spic...@gmail.com wrote: > Hi, > > there may be a serious error in python's int() function: > > print int(float(2.8/0.1)) > > yields > > 27 > > instead of 28!! > > I am using Python Python 2.7.6, GCC 4.8.2 on Linux Ubuntu. > > Is that known? This arises because finite floating point arithmetic is not exact so 2.8/0.1 results in 27.996. And, since the int() function truncates towards zero, this results in a value of 27. If you want the nearest integer you should use round(x) rather than int(x). -- https://mail.python.org/mailman/listinfo/python-list
Re: Serious error in int() function?
On 14/04/2016 07:52, ast wrote: > > a écrit dans le message de > news:52f7516c-8601-4252-ab16-bc30c59c8...@googlegroups.com... >> Hi, >> >> there may be a serious error in python's int() function: >> >> print int(float(2.8/0.1)) >> >> yields >> >> 27 >> >> instead of 28!! >> >> I am using Python Python 2.7.6, GCC 4.8.2 on Linux Ubuntu. >> >> Is that known? >> Best, >> Martin > > > I have a similar question, so I post my message here. > Hope this will not annoy the OP > > > Is it sure that the square root of a square number is always > an integer ? > > I would not like to get a result as 345. > > from math import sqrt > sqrt(16) > 4.0 sqrt(16).is_integer() > True > for n in range(100): > ... if not sqrt(n**2).is_integer(): > ... print(sqrt(n**2)) > > it seems to work ... but does it work for all integers ? Assuming that IEEE 754 floating point arithmetic is being used, the sqrt() function will return an exact integer square root for square integers provided that the square root is exactly representable. This means that the result will be correct provided it has 53 or less bits - just short of 16 decimal digits (i.e for square numbers with less than 32 digits). With an integer square root function (isqrt), this program: for exp in count(20): v = 2 ** exp - 1 if isqrt(v) != sqrt(v): print(exp, isqrt(v), sqrt(v)) break terminates with: 54 18014398509481983 1.8014398509481982e+16 showing a first error for a 54 bit square root -- https://mail.python.org/mailman/listinfo/python-list
Re: Serious error in int() function?
On 14/04/2016 08:59, blindanag...@nowhere.net wrote: > On 14/04/2016 07:52, ast wrote: > This means that the result will be correct provided it has 53 or less > bits - just short of 16 decimal digits (i.e for square numbers with less > than 32 digits). > > With an integer square root function (isqrt), this program: > > for exp in count(20): > v = 2 ** exp - 1 > if isqrt(v) != sqrt(v): > print(exp, isqrt(v), sqrt(v)) > break > > terminates with: > > 54 18014398509481983 1.8014398509481982e+16 > > showing a first error for a 54 bit square root > I should also have said that the square root of integer squares with between 15 and 30 decimal digits will only be correct if the square numbers themselves are exactly representable in 53 bits. So we can expect failures for squares with 16 or more digits. -- https://mail.python.org/mailman/listinfo/python-list
Re: Serious error in int() function?
On 14/04/2016 09:13, blindanag...@nowhere.net wrote: > On 14/04/2016 08:59, blindanag...@nowhere.net wrote: >> On 14/04/2016 07:52, ast wrote: > >> This means that the result will be correct provided it has 53 or less >> bits - just short of 16 decimal digits (i.e for square numbers with less >> than 32 digits). >> >> With an integer square root function (isqrt), this program: >> >> for exp in count(20): >> v = 2 ** exp - 1 >> if isqrt(v) != sqrt(v): >> print(exp, isqrt(v), sqrt(v)) >> break >> >> terminates with: >> >> 54 18014398509481983 1.8014398509481982e+16 >> >> showing a first error for a 54 bit square root >> > I should also have said that the square root of integer squares with > between 15 and 30 decimal digits will only be correct if the square > numbers themselves are exactly representable in 53 bits. So we can > expect failures for squares with 16 or more digits. However, if a number with 31 or less digits is known to be the square of an integer, the IEEE754 sqrt function will (I believe) give the correct result. -- https://mail.python.org/mailman/listinfo/python-list
Re: Serious error in int() function?
On 15/04/2016 01:36, Dennis Lee Bieber wrote: > On Thu, 14 Apr 2016 13:07:03 +0100, blindanag...@nowhere.net declaimed the > following: > >> On 14/04/2016 09:13, blindanag...@nowhere.net wrote: >>> On 14/04/2016 08:59, blindanag...@nowhere.net wrote: On 14/04/2016 07:52, ast wrote: >>> This means that the result will be correct provided it has 53 or less bits - just short of 16 decimal digits (i.e for square numbers with less than 32 digits). With an integer square root function (isqrt), this program: for exp in count(20): v = 2 ** exp - 1 if isqrt(v) != sqrt(v): print(exp, isqrt(v), sqrt(v)) break terminates with: 54 18014398509481983 1.8014398509481982e+16 showing a first error for a 54 bit square root >>> I should also have said that the square root of integer squares with >>> between 15 and 30 decimal digits will only be correct if the square >>> numbers themselves are exactly representable in 53 bits. So we can >>> expect failures for squares with 16 or more digits. >> >> However, if a number with 31 or less digits is known to be the square of >> an integer, the IEEE754 sqrt function will (I believe) give the correct >> result. > > How could it EXCEPT by having ~15 significant digits and an exponent -- > since that is all the data that is provided by a double precision floating > point. It can have up to about 30 significant digits because we know thaat it is the square of a an integer that is representable in IEEE754 floating point. So when we consider its square root we only have to consider the squares of integers that are representable and find the one that is 'nearest' to our 30 bit integer. When x is a representable integer the gap between (x- 1)^2, x^2 and (x + 1)^2 is approximately 2 * x and this means that ~30 digit perfect squares will have different floating point representations because they differ by a 15 digit value and will hence differ in their first ~15 significant digits. -- https://mail.python.org/mailman/listinfo/python-list
Re: Smarter algo, was Re: 03 digression by brute force
On 15/12/2018 09:56, jf...@ms4.hinet.net wrote: > Appreciate your thoughtfully analysis on this code. Before generalize it with > arbitrary additions, as Peter suggested:-), a recursive version is needed. I > may give it a try on this Sunday. > > > Avi Gross at 2018/12/15 UTC+8 AM8:13:37 wrote: >> REAL SUBJECT: Analysis of alternate algorithms. >> >> Peter & Jach and anyone interested, >> >> As Peter said in his altered subject line, Jack changed directions from >> tweaking an algorithm to trying something quite different. >> >> Reminder of the problem. >> >> Horizontal View: >> SEND + MORE = MONEY >> >> Vertical View: >> SEND >> +MORE >> ... >> MONEY >> >> Hard to be precise as I am sticking to plain text in my message. The three >> words above are meant to be right adjusted. >> >> When solving it horizontally, Jach and I used variants of a brute force >> approach. Substitute all possible combinations. He did it in-line and used >> eval. I did it by making lists of items on both sides and summing the int() >> of each component and comparing. We tried both our algorithms and his was >> slower and he profiled that the cause was that eval() was much more >> expensive as were his use of regular expression functions. For comparison, >> mine used int() and string manipulation functions and sets and dictionaries. >> >> But the real puzzle is meant to be solved in a more vertical way by humans >> using logic. I won't do that here but note we have 4 equations going down >> but 8 unknowns. And the equations are not unique. >> >> The rightmost column (I will call it the first as our arithmetic proceeds >> from right to left) is meant to represent ONES and provides the equation: >> >> (D+E== Y) or (D+E == Y + 10) >> >> Worse, for the next column, you either get a "1" carried from the previous >> addition or not and either pass a "1" along to the next column or not. 4 >> Possibilities. >> >> (N+R==E) or (N+R+1==E) or (N+R==E+10) or (N+R+1==E+10) >> >> Getting a headache yet? >> >> For a human, they need a way to come up with additional info in terms of >> constraints. >> >> There is a guiding inequality that looks like this: >> >> S is not the same as any of the others. Anytime you solve for another, the >> list of possible values for S shrinks. >> Ditto for each other variable. >> Or, since anything plus 0 is itself, then D and E adding up to Y (with no >> possible carry) cannot be 0. >> >> But getting a computer to do this might be a bit harder than blunt-force >> searches. So let's see why Jach's new algorithm was faster. >> >> The code I am analyzing can be viewed in the archives and will not be >> entered again: >> >> https://mail.python.org/pipermail/python-list/2018-December/738454.html >> >> So what did Jach try in his newer version? It is what I call a vertical >> approach but one a computer can do easier than a human can or would. I see >> it is a very specific algorithm that hard codes in these variables as global >> entities that are altered by a set of nested functions. S, E, N, D, M, O, R, >> Y. There are approaches that might be better such as passing a dictionary >> partially filled out from one function to the next as the only one that >> prints the solution is the final function call. >> >> So his is not a general solution. >> >> What interests me as a probable reason this is faster is the number of >> situations it tries. The earlier versions asked itertools.permutations() to >> provide all unique combinations of ten tokens in eight positions. So there >> were 10 choices for the first and 9 for the second and so on adding up to >> 10!/2! or 1,814,400 different combinations tried. That approaches 2 million. >> >> Jack broke the problem down into evaluating the units column with a loop >> like this: >> >> itertools.permutations(range(10), 3) >> >> That is 720 possibilities. He then doubled that to 1,440 to consider a >> carry. Only if the selected values for the three variables in contention >> (plus a carry) does he go on to call to evaluate the tens column. >> >> It then shrinks a bit more as he no longer gets the permutations of all 10 >> digits. He subtracts the three values that might work for the units, so he >> is asking for permutations of 7 digits, two at a time. That is 42, doubled >> again to 84 for carry purposes. And this function is not called 1,440 times, >> but quite a bit fewer. >> >> So, similarly, of those 84 loops for tens, he only sometimes calls to >> evaluate hundreds. As mentioned, the set of 10 digits shrinks some more and >> this continues upward to functions that evaluate hundreds and thousands and >> finally the one evaluating ten thousands pretty much prints out an answer it >> finds. >> >> So overall iterations can be shown to drop. We could add code to measure how >> many times each function is called and come up with an exact value for this >> built-in problem. I did and the functions were called this many time
Re: 03 digression by brute force
On 14/12/2018 02:24, jf...@ms4.hinet.net wrote: > Just for fun:-) On my ooold PC, it takes 0.047 seconds to run the following > algorithm on the problem 'SNED + MORE == MONEY". > > - > import time > import itertools > > #S, E, N, D, M, O, R, Y > n = 0 > digits = {x for x in range(10)} > > def tenThousand(u, Cin): # Cin == M > global n > if Cin == M: > print(S, E, N, D, '+', M, O, R, E, '==', M, O, N, E, Y) > n += 1 > > def thousand(u, Cin): # Cin + S + M == 10 * Cout + O > global S, M, n > rest = digits - set(u) > for g in itertools.permutations(rest, 2): > for Cout in range(2): > if Cin + g[0] + g[1] == 10 * Cout + O: > S = g[0]; M = g[1] > tenThousand(u + g, Cout) > > def hundred(u, Cin): # Cin + E + O == 10 * Cout + N > global O, n > rest = digits - set(u) > for g in itertools.permutations(rest, 1): > for Cout in range(2): > if Cin + E + g[0] == 10 * Cout + N: > O = g[0] > thousand(u + g, Cout) > > def ten(u, Cin): # Cin + N + R == 10 * Cout + E > global N, R, n > rest = digits - set(u) > for g in itertools.permutations(rest, 2): > for Cout in range(2): > if Cin + g[0] + g[1] == 10 * Cout + E: > N = g[0]; R = g[1] > hundred(u + g, Cout) > > def unit(): # D + E == 10 * Cout + Y > global D, E, Y, n > n = 0 > for g in itertools.permutations(range(10), 3): # g is a tuple > for Cout in range(2): # add two items so Cout is 0 or 1 > if g[0] + g[1] == 10 * Cout + g[2]: > D = g[0]; E = g[1]; Y = g[2] > ten(g, Cout) > print(n) > > if __name__ == '__main__': > start = time.time() > unit() > print(time.time() - start) > - > There are quite a few Python based solvers for alphametics around on the net, for example: http://code.activestate.com/recipes/576615-alphametics-solver/ There is also a long discussion here on ways of doing this: https://enigmaticcode.wordpress.com/2016/06/22/solving-alphametics-with-python/ -- https://mail.python.org/mailman/listinfo/python-list
Re: Enumerate - int object not subscriptable
On 20/08/2019 13:00, Sayth Renshaw wrote: > Hi > > I want to do basic math with a list. > > > for idx, num in enumerate(a): > print(idx, num) > > This works, but say I want to print the item value at the next index as well > as the current. > > for idx, num in enumerate(a): > print(num[idx + 1], num) a = [1, 2, 3, 4, 5, 6, 7, 8] for idx, num in enumerate(a): print(a[idx + 1], num) -- https://mail.python.org/mailman/listinfo/python-list
encapsulating a global variable
I would appreciate advice on whether it is possible to avoid the use of a global variable used in a function by encapsulating it in a class without maaking any changes to the call interface (which I cannot change). I have: seen = dict() def get_it(piece): ... return seen[piece] and I am wondering if it is possible to use a class something like class get_it(object): seen = dict() def __call__(piece): return seen[piece] to avoid the global variable. Brian Gladman -- https://mail.python.org/mailman/listinfo/python-list
Re: encapsulating a global variable
On 25/02/2020 12:56, Chris Angelico wrote: > On Tue, Feb 25, 2020 at 11:41 PM BlindAnagram > wrote: >> >> I would appreciate advice on whether it is possible to avoid the use of >> a global variable used in a function by encapsulating it in a class >> without maaking any changes to the call interface (which I cannot change). > > Why bother? If you aren't changing where the function's called, then > its state is effectively global anyway, so what's the point of the > class? It's a good question! The main reason is that I would like to know if it is possible as I then have a choice. The choice might not be there. Brian -- https://mail.python.org/mailman/listinfo/python-list
Re: encapsulating a global variable
On 25/02/2020 12:50, Musbur wrote: > > Am 25.02.2020 13:38 schrieb BlindAnagram: >> and I am wondering if it is possible to use a class something like >> >> class get_it(object): >> >> seen = dict() >> >> def __call__(piece): >> return seen[piece] > > What happened when you tried it? The nearest I got was: - class orientate(object): seen = defaultdict() @classmethod def do(self, piece, two_sided=False): which works but requires a change to the function call interface from orientate(piece) to orientate.do(piece). I was hoping that repalcing the above with: - class orientate(object): seen = defaultdict() @classmethod def __call__(self, piece, two_sided=False): would eliminate the need for the 'do' but this gives the error: builtins.TypeError: orientate() takes no arguments Brian -- https://mail.python.org/mailman/listinfo/python-list
Re: encapsulating a global variable
On 25/02/2020 14:14, Rhodri James wrote: > On 25/02/2020 12:38, BlindAnagram wrote: >> I would appreciate advice on whether it is possible to avoid the use of >> a global variable used in a function by encapsulating it in a class >> without maaking any changes to the call interface (which I cannot >> change). >> >> I have: >> >> >> seen = dict() >> >> def get_it(piece): >> ... >> return seen[piece] >> >> >> and I am wondering if it is possible to use a class something like >> >> >> class get_it(object): >> >> seen = dict() >> >> def __call__(piece): >> return seen[piece] >> >> >> to avoid the global variable. > > I wouldn't. Calling the class name creates an instance of the class, so > won't actually do what you want. You could rewrite the class and create > an instance to call instead: > > class GetIt: > seen = dict() > > def __call__(self, piece): > return GetIt.seen[piece] > > get_it = GetIt() > > but then you have a global class instance hanging around, which is not > actually any better than a global dictionary. Thanks. Does that not have the advantage of preventing the global directory being directly fiddled with elsewhere? Which is one of my reasons for thinking about this. Brian -- https://mail.python.org/mailman/listinfo/python-list
Re: encapsulating a global variable
On 25/02/2020 14:13, Chris Angelico wrote: > On Wed, Feb 26, 2020 at 12:11 AM BlindAnagram > wrote: >> >> On 25/02/2020 12:56, Chris Angelico wrote: >>> On Tue, Feb 25, 2020 at 11:41 PM BlindAnagram >>> wrote: >>>> >>>> I would appreciate advice on whether it is possible to avoid the use of >>>> a global variable used in a function by encapsulating it in a class >>>> without maaking any changes to the call interface (which I cannot change). >>> >>> Why bother? If you aren't changing where the function's called, then >>> its state is effectively global anyway, so what's the point of the >>> class? >> >> It's a good question! >> >> The main reason is that I would like to know if it is possible as I then >> have a choice. The choice might not be there. >> > > Well, yes, you can, but you would need a global instance of that class > (or use the global class object itself). So you'd still have a global. > > But if this is a transitional thing, then the answer is a resounding > YES. You can start by packaging up all your state with a class, and > have a single global instance of that class; but then you can rework > your function to take an optional parameter which is a non-global > instance of the class. Then all your state is kept in there, and you > actually truly *do* avoid global state. As a good example of how this > works, check out Python's random module - you can call > random.randrange() to get a random number in a particular range, or > you can instantiate your own random.Random() object and call its > randrange() method. The first form uses global state; the second form > doesn't. Thanks, I think I understand most of this but the eample will help a lot. My interest in this stems from wanting to keep the dictionary only available to the function that uses it and also a worry about being called from threaded code. Brian -- https://mail.python.org/mailman/listinfo/python-list
Re: encapsulating a global variable
On 25/02/2020 14:14, Rhodri James wrote: > On 25/02/2020 12:38, BlindAnagram wrote: >> I would appreciate advice on whether it is possible to avoid the use of >> a global variable used in a function by encapsulating it in a class >> without maaking any changes to the call interface (which I cannot >> change). >> >> I have: >> >> >> seen = dict() >> >> def get_it(piece): >> ... >> return seen[piece] >> >> >> and I am wondering if it is possible to use a class something like >> >> >> class get_it(object): >> >> seen = dict() >> >> def __call__(piece): >> return seen[piece] >> >> >> to avoid the global variable. > > I wouldn't. Calling the class name creates an instance of the class, so > won't actually do what you want. You could rewrite the class and create > an instance to call instead: > > class GetIt: > seen = dict() > > def __call__(self, piece): > return GetIt.seen[piece] > > get_it = GetIt() > > but then you have a global class instance hanging around, which is not > actually any better than a global dictionary. This doesn't work for me since get_it(piece) returns the error: builtins.TypeError: get_it() takes no arguments Brian -- https://mail.python.org/mailman/listinfo/python-list
Re: encapsulating a global variable
On 25/02/2020 16:36, Rhodri James wrote: > On 25/02/2020 15:20, BlindAnagram wrote: >>> class GetIt: >>> seen = dict() >>> >>> def __call__(self, piece): >>> return GetIt.seen[piece] >>> >>> get_it = GetIt() >>> >>> but then you have a global class instance hanging around, which is not >>> actually any better than a global dictionary. >> This doesn't work for me since get_it(piece) returns the error: >> >> builtins.TypeError: get_it() takes no arguments > > It works for me (pace sticking something in GetIt.seen to avoid getting > a KeyError). You aren't muddling up the class name and instance name > are you? Apologies, I misunderstoof your proposal - it woks fine now I have understood it Brian -- https://mail.python.org/mailman/listinfo/python-list
Re: encapsulating a global variable (BlindAnagram)
On 25/02/2020 17:16, Christman, Roger Graydon wrote: >> On Tue, 25 Feb 2020 3:06 PM BlindAnagram wrote: > >> My interest in this stems from wanting to keep the dictionary only >> available to the function that uses it and also a worry about being >> called from threaded code. > > It seems like the simplest solution for this is to make > a completely new file (module) containing nothing but > the dictionary and this one function that uses it. > Then you can import the function from the module > wherever it is called without importing the dictionary. > > The thing I find curious is that apparently no other > function is allowed to create or populate the dictionary > in the first place. Is it practical to have the entire > dictionary statically defined? The dictionary is a static variable of the function. It is updated by the function and must maintain values across function calls. Reading some more, it seems that I can create static function variables using attributes. Brian -- https://mail.python.org/mailman/listinfo/python-list
Behaviour of os.path.join
I came across an issue that I am wondering whether I should report as an issue. If I have a directory, say: base='C:\\Documents' and I use os.path.join() as follows: join(base, '..\\..\\', 'build', '') I obtain as expected from the documentation: 'C:\\Documents\\..\\..\\build\\' But if I try to make the directory myself (as I tried first): join(base, '..\\..\\', 'build', '\\') I obtain: 'C:\\' The documentation says that an absolute path in the parameter list for join will discard all previous parameters but '\\' is not an absoute path! Moreover, if I use join(base, '..\\..\\', 'build', os.sep) I get the same result. This seems to me to be a bug that I should report but to avoid wasting developer time I wanted to hear what others feel about this. -- https://mail.python.org/mailman/listinfo/python-list
Re: Behaviour of os.path.join
On 26/05/2020 16:22, Ben Bacarisse wrote: > BlindAnagram writes: > >> I came across an issue that I am wondering whether I should report as an >> issue. If I have a directory, say: >> >> base='C:\\Documents' >> >> and I use os.path.join() as follows: >> >> join(base, '..\\..\\', 'build', '') > > It rather defeats the purpose of os.sep if you include it in a part of > the path. What you mean is better expressed as > > join(base, '..', '..', 'build', '') > > (and base includes it too, but I can't suggest an alternative because I > don't know your intent is far as defaults go.) Thanks for your input but while that part of my path may not be to your liking, it works fine and does not seem to be relevant to my concern, which is that join appears to treat os.sep as an absolute path, which it is not. -- https://mail.python.org/mailman/listinfo/python-list
Re: Behaviour of os.path.join
On 26/05/2020 16:25, Stefan Ram wrote: > BlindAnagram writes: >> The documentation says that an absolute path in the parameter list for >> join will discard all previous parameters but '\\' is not an absoute path! > > The source code for "join" in "ntpath.py" does not seem to > bother to call "is_absolute". Instead it contains (simplified): > > seps = '\\/' > if p_path and p_path[0] in seps: > # Second path is absolute Thanks, that seems to confirm this as a bug. -- https://mail.python.org/mailman/listinfo/python-list
Re: Behaviour of os.path.join
On 26/05/2020 16:59, Mats Wichmann wrote: > On 5/26/20 8:56 AM, BlindAnagram wrote: >> I came across an issue that I am wondering whether I should report as an >> issue. If I have a directory, say: >> >> base='C:\\Documents' >> >> and I use os.path.join() as follows: >> >> join(base, '..\\..\\', 'build', '') >> >> I obtain as expected from the documentation: >> >> 'C:\\Documents\\..\\..\\build\\' >> >> But if I try to make the directory myself (as I tried first): >> >> join(base, '..\\..\\', 'build', '\\') >> >> I obtain: >> >> 'C:\\' >> >> The documentation says that an absolute path in the parameter list for >> join will discard all previous parameters but '\\' is not an absoute path! > > But it is - an absolute path is one that starts with the pathname separator. On Windows, when part of a string representing a file or directory path, '\\' acts as a directory separator. It may imply, as you say, that it is a path on the current drive but it also behaves as a move to a sub-directory of what has appeared to its left. And this is how it is treated in other os.path functions. For example: base = "C:\\Documents\\Finance\\" abspath(base) 'C:\\Documents\\Finance' where it can be seen that '\\' is being treated as a directory separator. In my view it is not sensible to have some functions treating '\\' in one way and others differently. I would hence expect join() to accept '\\' as an addition to a file path on Windows and not a signal of an absolute path. > The concept of paths is ugly in Windows because of the drive letter - a > drive letter is not actually part of a path, it's an additional piece of > context. If you leave out the drive letter, your path is relative or > absolute within the current drive letter; if you include it your path is > relative or absolute within the specified drive letter. So Python has > behaved as documented here: the indicator for an absolute path has > discarded everything (except the drive letter, which is necessary to > maintain the context you provided) which came before it in the join. > > If indeed you're seeking a path that is terminated by the separator > character, you need to do what you did in the first example - join an > empty string at the end (this is documented). The terminating separator > _usually_ isn't needed. Sadly, sometimes it appears to be... I agree that handling file paths on Windows is very ugly, especially so if some of the directory/file names include spaces. But I don't see that as an excuse for this specific ambiguity in Python in the handling of '\\' when embedded in, or added to, paths. -- https://mail.python.org/mailman/listinfo/python-list
Re: Behaviour of os.path.join
On 26/05/2020 17:09, Stefan Ram wrote: > Mats Wichmann writes: >> an absolute path is one that starts with the pathname separator. > > The Python Library Reference does not use the term > "pathname separator". It uses "directory separator" > (os.sep) and "filename separator" ('/' on Unix). > > On Windows: > > |>>> import pathlib > |>>> import os > |>>> pathlib.PureWindowsPath('\\').is_absolute() > |False > |>>> pathlib.PureWindowsPath(os.sep).is_absolute() > |False > |>>> pathlib.PureWindowsPath('/').is_absolute() > |False Thanks, that seems to suggest that there is an issue and that I should hence submit this as an issue. -- https://mail.python.org/mailman/listinfo/python-list
Re: Behaviour of os.path.join
On 26/05/2020 17:46, MRAB wrote: > On 2020-05-26 16:48, BlindAnagram wrote: >> On 26/05/2020 16:22, Ben Bacarisse wrote: >>> BlindAnagram writes: >>> >>>> I came across an issue that I am wondering whether I should report >>>> as an >>>> issue. If I have a directory, say: >>>> >>>> base='C:\\Documents' >>>> >>>> and I use os.path.join() as follows: >>>> >>>> join(base, '..\\..\\', 'build', '') >>> >>> It rather defeats the purpose of os.sep if you include it in a part of >>> the path. What you mean is better expressed as >>> >>> join(base, '..', '..', 'build', '') >>> >>> (and base includes it too, but I can't suggest an alternative because I >>> don't know your intent is far as defaults go.) >> >> Thanks for your input but while that part of my path may not be to your >> liking, it works fine and does not seem to be relevant to my concern, >> which is that join appears to treat os.sep as an absolute path, which it >> is not. >> > If it starts with the path separator, then it's absolute (well, absolute > on that drive). Agreed. I did not think that I needed to add this exception to my comment as I thought from the the context that it would be clear that I was questioning how it worked at the end of a path, not when used at its start. -- https://mail.python.org/mailman/listinfo/python-list
Re: Behaviour of os.path.join
On 26/05/2020 16:59, Mats Wichmann wrote: > On 5/26/20 8:56 AM, BlindAnagram wrote: >> I came across an issue that I am wondering whether I should report as an >> issue. If I have a directory, say: >> >> base='C:\\Documents' >> >> and I use os.path.join() as follows: >> >> join(base, '..\\..\\', 'build', '') >> >> I obtain as expected from the documentation: >> >> 'C:\\Documents\\..\\..\\build\\' >> >> But if I try to make the directory myself (as I tried first): >> >> join(base, '..\\..\\', 'build', '\\') >> >> I obtain: >> >> 'C:\\' >> >> The documentation says that an absolute path in the parameter list for >> join will discard all previous parameters but '\\' is not an absoute path! > > But it is - an absolute path is one that starts with the pathname separator. In a string giving a file path on Windows '\\' is recognised as a separator between directories and not as an indicator that what follows is an absolute path based on the drive letter (although it might, as you say, imply a drive context). > The concept of paths is ugly in Windows because of the drive letter - a > drive letter is not actually part of a path, it's an additional piece of > context. If you leave out the drive letter, your path is relative or > absolute within the current drive letter; if you include it your path is > relative or absolute within the specified drive letter. So Python has > behaved as documented here: the indicator for an absolute path has > discarded everything (except the drive letter, which is necessary to > maintain the context you provided) which came before it in the join. This is not consistent with how other file management functions in os.path operate since they willingly accept '\\' as a directory separator. > If indeed you're seeking a path that is terminated by the separator > character, you need to do what you did in the first example - join an > empty string at the end (this is documented). The terminating separator > _usually_ isn't needed. Sadly, sometimes it appears to be... -- https://mail.python.org/mailman/listinfo/python-list
Re: Behaviour of os.path.join
On 26/05/2020 18:51, Mats Wichmann wrote: > On 5/26/20 10:57 AM, BlindAnagram wrote: >> On 26/05/2020 16:59, Mats Wichmann wrote: >>> On 5/26/20 8:56 AM, BlindAnagram wrote: >>>> I came across an issue that I am wondering whether I should report as an >>>> issue. If I have a directory, say: >>>> >>>> base='C:\\Documents' >>>> >>>> and I use os.path.join() as follows: >>>> >>>> join(base, '..\\..\\', 'build', '') >>>> >>>> I obtain as expected from the documentation: >>>> >>>> 'C:\\Documents\\..\\..\\build\\' >>>> >>>> But if I try to make the directory myself (as I tried first): >>>> >>>> join(base, '..\\..\\', 'build', '\\') >>>> >>>> I obtain: >>>> >>>> 'C:\\' >>>> >>>> The documentation says that an absolute path in the parameter list for >>>> join will discard all previous parameters but '\\' is not an absoute path! >>> >>> But it is - an absolute path is one that starts with the pathname separator. >> >> On Windows, when part of a string representing a file or directory path, >> '\\' acts as a directory separator. It may imply, as you say, that it >> is a path on the current drive but it also behaves as a move to a >> sub-directory of what has appeared to its left. And this is how it is >> treated in other os.path functions. For example: >> >> base = "C:\\Documents\\Finance\\" >> abspath(base) >> 'C:\\Documents\\Finance' >> >> where it can be seen that '\\' is being treated as a directory >> separator. In my view it is not sensible to have some functions >> treating '\\' in one way and others differently. I would hence expect >> join() to accept '\\' as an addition to a file path on Windows and not >> a signal of an absolute path. > > Unlike the string join method, which would behave as you seem to want, > the os.path.join method "knows" it is working on paths, so it's going to > assign some meaning to the content of the pieces. If it was up to me I > might not have chosen the approach Python did of "if we see a piece that > looks like an absolute path, discard what came before", but that's the > one that was chosen, presumably for good reasons, and it is so > documented. And the pathlib library module chose to retain that > behavior: "When several absolute paths are given, the last is taken as > an anchor (mimicking os.path.join()’s behaviour)". So it's just > something to get used to? I agree with much of what you say. But I believe that it is more natural and less 'dangerous' when a functions behaviour matches that which its name implies, that is, to join things together, not to throw one of them away! And, I don't presume that there were good reasons since it might simply have been an oversight, which is why I raised it (even Python developers are not perfect :-) -- https://mail.python.org/mailman/listinfo/python-list
Re: Behaviour of os.path.join
On 27/05/2020 09:13, Barry Scott wrote: > > >> On 26 May 2020, at 18:01, BlindAnagram wrote: >> >> On 26/05/2020 17:09, Stefan Ram wrote: >>> Mats Wichmann writes: >>>> an absolute path is one that starts with the pathname separator. >>> >>> The Python Library Reference does not use the term >>> "pathname separator". It uses "directory separator" >>> (os.sep) and "filename separator" ('/' on Unix). >>> >>> On Windows: >>> >>> |>>> import pathlib >>> |>>> import os >>> |>>> pathlib.PureWindowsPath('\\').is_absolute() >>> |False >>> |>>> pathlib.PureWindowsPath(os.sep).is_absolute() >>> |False >>> |>>> pathlib.PureWindowsPath('/').is_absolute() >>> |False >> >> Thanks, that seems to suggest that there is an issue and that I should >> hence submit this as an issue. > > Can you post the a link to the issue please? The issue that I raised here was whether the behaviour of os.path.join() in treating the Windows directory separator '\\' as an absolute path should be considered a bug. The behaviour of join came up for me when I tried to use the os.path functions to create a path that could only ever be used as a directory and never a file. The only way that I found to designate a path as a directory path was to add '\\' at the end. But this doesn't work in using os.path becaause the other os.path functions just strip it off and turn the directories back into files. I had hoped that join's documented use of an empty final parameter to add '\\' might behave differently but it gets stripped off as well :-( I thought that the description of pathlib behaviour above suported the view that the os.path.joing behaviour is a bug, and in a sense it does, but more importantly it an indication that pathib, not os.path, should be the module of choice for anyone who spends a lot of time manipulating paths on Windows. -- https://mail.python.org/mailman/listinfo/python-list
Re: Behaviour of os.path.join
On 27/05/2020 13:30, Ben Bacarisse wrote: > BlindAnagram writes: > >> The issue that I raised here was whether the behaviour of os.path.join() >> in treating the Windows directory separator '\\' as an absolute path >> should be considered a bug. > > You think it should be considered to be a relative path? The only > meaning that would give you want you wanted from > > os.path.join(, '\\') > > would be to treat it as being relative to the drive and to the > directory. In other words you want '\\' to be a synonym for '.' The > usual meaning of '\\' (outside of this specific function) is "root on > the current drive" but that can't sensibly be appended to any path. > >> The behaviour of join came up for me when I tried to use the os.path >> functions to create a path that could only ever be used as a directory >> and never a file. The only way that I found to designate a path as a >> directory path was to add '\\' at the end. But this doesn't work in >> using os.path becaause the other os.path functions just strip it off and >> turn the directories back into files. > > Nothing about the name can turn a directory into a file (or vice versa). > If c:\x\y is a file, calling it c:\x\y\ won't change that, but it might > give you an error when you try to access it. That may be what you want. > If so, appending '.' is likely to be more portable. That is true if you know for sure how your path will be used. But if you don't, there is a world of difference between passing the paths 'name' and 'name\\' on for others to use. And in this situation it doesn't help when os.path functions strip the directory separator off. This situation resulted in a bug that was surprisingly hard to track down because it created hidden files instead of directories as intended. After finding and correcting the '\\' that had been stripped off, the desired directories couldn't then be creaated on the target because hidden files were present with these names. -- https://mail.python.org/mailman/listinfo/python-list
Re: Behaviour of os.path.join
On 27/05/2020 14:53, Rhodri James wrote: > On 27/05/2020 14:41, BlindAnagram wrote: >> That is true if you know for sure how your path will be used. >> >> But if you don't, there is a world of difference between passing the >> paths 'name' and 'name\\' on for others to use. And in this situation it >> doesn't help when os.path functions strip the directory separator off. > > Only if you impose meaning externally, which implies you do know how > your path will be used after all. If you want to know whether a given > path corresponds to a file or a directory on a filing system, there's no > real substitute for looking on the filing system. Anything else is, as > you have discovered, error-prone. I'm sorry that you don't believe me but all I know is how I intend the path to be used. And the os.path functions aren't helpful here when they actually _change_ the meanings of paths on Windows: >> fp= "C:\\Documents\finance\\" >> abspath(fp) 'C:\\Documents\\finance' If you believe these 'before' and 'after' paths are the same I can only assume that you don't work on Windows (where one refers to a directory and the other a file without an extension). -- https://mail.python.org/mailman/listinfo/python-list
Re: Behaviour of os.path.join
On 27/05/2020 16:49, Rhodri James wrote: > On 27/05/2020 16:12, BlindAnagram wrote: >> I'm sorry that you don't believe me but all I know is how I intend the >> path to be used. And the os.path functions aren't helpful here when >> they actually_change_ the meanings of paths on Windows: >> >>>> fp= "C:\\Documents\finance\\" >>>> abspath(fp) >> 'C:\\Documents\\finance' >> >> If you believe these 'before' and 'after' paths are the same I can only >> assume that you don't work on Windows (where one refers to a directory >> and the other a file without an extension). > > More accurately, one is not a legal filename but both are legal > directory names. If they are to be created, which is my situation, the result will be a diretory and a file. > I entirely believe that you have a problem, but I'm inclined to think > it's of your own making. You seem to have decided how paths work > without checking whether the language agrees with you. It doesn't, and > hasn't for over a decade without a significant number of complaints (as > in I can't remember the last one, and I've been around here for a while > -- it's too hot for me to want to go hunt in the archives :-). Why do you believe my understanding of Python is lacking? It seems to me that I have tried to avoid this very issue by explicitly sending a directory and I have been thwarted by a combination of poor knowledge elsewhere and a poorly designed function that changes the semantics of what it is offered. I would be surprised if issues such as these were not, at least in significant part, the reason why we now have pathlib. > How are these unexpected extensionless files getting created? I believe by attempting to make the directory I send absolute with abspath() and then copying a file to this path. They expected this to copy the file into the directory with its original name but instead it copies it to the file that abspath 'kindly' converts my directory into. I did complain about their lack of knowledge but I also have a right to complain about a function that converts an explicitly specified directory into a file :-) -- https://mail.python.org/mailman/listinfo/python-list
Re: Behaviour of os.path.join
On 27/05/2020 16:53, Ben Bacarisse wrote: > BlindAnagram writes: > >> On 27/05/2020 13:30, Ben Bacarisse wrote: >>> BlindAnagram writes: >>> >>>> The issue that I raised here was whether the behaviour of os.path.join() >>>> in treating the Windows directory separator '\\' as an absolute path >>>> should be considered a bug. >>> >>> You think it should be considered to be a relative path? The only >>> meaning that would give you want you wanted from >>> >>> os.path.join(, '\\') >>> >>> would be to treat it as being relative to the drive and to the >>> directory. In other words you want '\\' to be a synonym for '.' The >>> usual meaning of '\\' (outside of this specific function) is "root on >>> the current drive" but that can't sensibly be appended to any path. >>> >>>> The behaviour of join came up for me when I tried to use the os.path >>>> functions to create a path that could only ever be used as a directory >>>> and never a file. The only way that I found to designate a path as a >>>> directory path was to add '\\' at the end. But this doesn't work in >>>> using os.path becaause the other os.path functions just strip it off and >>>> turn the directories back into files. >>> >>> Nothing about the name can turn a directory into a file (or vice versa). >>> If c:\x\y is a file, calling it c:\x\y\ won't change that, but it might >>> give you an error when you try to access it. That may be what you want. >>> If so, appending '.' is likely to be more portable. >> >> That is true if you know for sure how your path will be used. >> >> But if you don't, there is a world of difference between passing the >> paths 'name' and 'name\\' on for others to use. And in this situation it >> doesn't help when os.path functions strip the directory separator off. > > As it should. Relying on a trailing \ having the right effect is > brittle to say the least. In my case less brittle than leaving it out. I don't want to bore people with the details but the convention on the target system is that directory paths must always end with '\\' into order to be interpreted as directories. Its not my choice but I see this as a perfectly reasonable convention. Obviously others may disagree. >> This situation resulted in a bug that was surprisingly hard to track >> down because it created hidden files instead of directories as >> intended. > > If so, the bug is not in os.path.join and trying to fix it by insisting > that a path have trailing \ may well just stacking up more problems for > later. > >> After finding and correcting the '\\' that had been stripped off, the >> desired directories couldn't then be creaated on the target because >> hidden files were present with these names. > > As I said, that's a dodgy thing to rely on. It may be that you can't > fix the bug any other way (some aspect of the overall design may be > broken), but I would urge you to try. Its not my bug to fix - the semantics of what I send is very clear on any Windows system. -- https://mail.python.org/mailman/listinfo/python-list
Re: Behaviour of os.path.join
On 27/05/2020 18:37, Roel Schroeven wrote: > BlindAnagram schreef op 27/05/2020 om 18:39: >> On 27/05/2020 16:49, Rhodri James wrote: >>> On 27/05/2020 16:12, BlindAnagram wrote: >>>> I'm sorry that you don't believe me but all I know is how I intend the >>>> path to be used. And the os.path functions aren't helpful here when >>>> they actually_change_ the meanings of paths on Windows: >>>> >>>>>> fp= "C:\\Documents\finance\\" >>>>>> abspath(fp) >>>> 'C:\\Documents\\finance' >>>> >>>> If you believe these 'before' and 'after' paths are the same I can only >>>> assume that you don't work on Windows (where one refers to a directory >>>> and the other a file without an extension). >>> >>> More accurately, one is not a legal filename but both are legal >>> directory names. >> >> If they are to be created, which is my situation, the result will be a >> diretory and a file. > > os.mkdir('C:\\Documents\\finance') creates a directory. > open('C:\\Documents\\finance', 'w') creates a file. > > The difference is in the operation, not in the name. > > 'C:\\Documents\\finance' is a pathname, which can refer to either a > directory or a file. > 'C:\\Documents\\finance\\' could refer to a directory, but to me looks > more like a partial pathname, not a complete one. > > I can't think of any reason for ending pathnames with (back)slashes. > Just use os.path.join(directory, filename) when you need to refer to a > file in the directory. > >> I would be surprised if issues such as these were not, at least in >> significant part, the reason why we now have pathlib. > > That should be easy to verify: the reasons are listed in the PEP: > https://www.python.org/dev/peps/pep-0428 > I don't see your issue there. I don't think anyone has ever considered > it an issue at all really. > >>> How are these unexpected extensionless files getting created? >> >> I believe by attempting to make the directory I send absolute with >> abspath() and then copying a file to this path. They expected this to >> copy the file into the directory with its original name but instead it >> copies it to the file that abspath 'kindly' converts my directory into. > > We're getting closer to the real issue here. What functions were used > copy these files? With which parameters? > Were the destination directories created before copying the files to them? > >> I did complain about their lack of knowledge but I also have a right to >> complain about a function that converts an explicitly specified >> directory into a file :-) > > Again, a pathname is never inherently a directory or a file. You can define a path however you want but it won't change the fact that on Windows a path that ends in '\\' is inherently a path to a directory. -- https://mail.python.org/mailman/listinfo/python-list
Re: Behaviour of os.path.join
On 27/05/2020 18:42, Roel Schroeven wrote: > BlindAnagram schreef op 27/05/2020 om 18:53: >> Its not my bug to fix - the semantics of what I send is very clear on >> any Windows system. > > That's the first time I see any mention of those semantics, and I've > been using Windows since the Windows 3.1 days (and MS-DOS before that, > since 3.2 IIRC). Well I can only say that I am surpised that anyone working on Windows code development for as long as you have doesn't know that a path that ends in '\\' is a path to a directory. -- https://mail.python.org/mailman/listinfo/python-list
Re: Behaviour of os.path.join
On 27/05/2020 23:39, Roel Schroeven wrote: > BlindAnagram schreef op 27/05/2020 om 22:55: >> On 27/05/2020 18:42, Roel Schroeven wrote: >>> BlindAnagram schreef op 27/05/2020 om 18:53: >>>> Its not my bug to fix - the semantics of what I send is very clear on >>>> any Windows system. >>> >>> That's the first time I see any mention of those semantics, and I've >>> been using Windows since the Windows 3.1 days (and MS-DOS before that, >>> since 3.2 IIRC). >> >> Well I can only say that I am surpised that anyone working on Windows >> code development for as long as you have doesn't know that a path that >> ends in '\\' is a path to a directory. > > A path ending in a backslash cannot refer to a file, that much is true. > So if you have such a path and you insist that path is not an incomplete > path, than it must out of necessity be a directory. But a path not > ending in a backslash can refer to a directory just as well. I understand that directory paths do not necessarily end in a '\\'. But I am NOT claiming that paths on Windows are paths to directories if and only if they end in '\\' - there is only ONE 'if' in my claim. And this can be refuted with a single counterexample. > If those semantics are as clear as you say, it shouldn't be too > difficult to point us to a section in the Windows documentation that > confirms that. I don't know whether, in the many gigabytes of MS documentation that exists since Windows first emerged, this has ever been explicitly stated. And I am not going to look as it isn't important to me that people accept my claim. But I do find it interesting that it seems important to others here that I should withdraw it. [snip] > I find no hints of adding a backslash at the end to indicate directories. > If you can point me to convincing evidence in the documentation I'll > change my mind. And if you find a counterexample, I will change mine. > I'm sorry if my language seems abrasive; that is not my intention. I'm > only trying to help you and clear up a misunderstanding (which could be > mine, if it turns out you're right after all). No need to apologise, I don't have any problem with your input to this exchange. -- https://mail.python.org/mailman/listinfo/python-list
Re: Behaviour of os.path.join
On 28/05/2020 14:51, Eryk Sun wrote: > On 5/27/20, Chris Angelico wrote: >> On Thu, May 28, 2020 at 7:07 AM BlindAnagram >> wrote: >>> You can define a path however you want but it won't change the fact that >>> on Windows a path that ends in '\\' is inherently a path to a directory. >> >> Citation needed. > > See [MS-FSA] 2.1.5.1 Server Requests an Open of a File [1]. Here are > the relevant statements: > > The operation MUST be failed with STATUS_OBJECT_NAME_INVALID under > any of the following conditions: > > * If PathName contains a trailing backslash and > CreateOptions.FILE_NON_DIRECTORY_FILE is TRUE. > > > If PathName contains a trailing backslash: > * If StreamTypeToOpen is DataStream or > CreateOptions.FILE_NON_DIRECTORY_FILE is TRUE, the operation MUST > be failed with STATUS_OBJECT_NAME_INVALID > > Internally, WinAPI CreateFileW calls NTAPI NtCreateFile with the > create option FILE_NON_DIRECTORY_FILE (i.e. only open or create a data > file stream), unless backup semantics are requested in order to be > able to open a directory (i.e. an index stream), in which case the > call uses neither FILE_NON_DIRECTORY_FILE nor FILE_DIRECTORY_FILE and > leaves it up to the path name. In other words, with backup semantics, > if you need to ensure that only a directory is opened, add a trailing > slash. > > NTAPI STATUS_OBJECT_NAME_INVALID translates to WinAPI > ERROR_INVALID_NAME (123), which translates to C EINVAL (22). > > [1]: > https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-fsa/8ada5fbe-db4e-49fd-aef6-20d54b748e40 > Thank you for making the effort to answer a number of issues raaised in this thread. I much appreciate your input. -- https://mail.python.org/mailman/listinfo/python-list
Re: Behaviour of os.path.join
On 27/05/2020 23:39, Roel Schroeven wrote: > I find no hints of adding a backslash at the end to indicate directories. > > If you can point me to convincing evidence in the documentation I'll > change my mind. See the post from Eryk Sun, later in this thread. -- https://mail.python.org/mailman/listinfo/python-list
Re: Cygwin and Python3
On 10/02/2016 23:05, Mike S wrote: > On 2/10/2016 5:05 AM, Mark Lawrence wrote: [snip] >>> Have you seen this? >>> http://www.davidbaumgold.com/tutorials/set-up-python-windows/ >>> >> >> I have now, but I'm perfectly happy with the free versions of Visual >> Studio. [snip] > I don't see any references to VS on that page so I don't know what > you're referring to. I suspect that Mark is reacting indirectly to the misleading implication on that page that it is necessary to install Cygwin if you want to develop Python code on Windows. -- https://mail.python.org/mailman/listinfo/python-list
indexing in format strings
With: l = [1,2,3] this: print('{0[0]:d}..{0[2]:d}'.format(l)) gives 1..3 but this: print('{0[0]:d}..{0[-1]:d}'.format(l)) gives: Traceback (most recent call last): File "", line 1, in builtins.TypeError: list indices must be integers, not str which seems to me counterintuitive. I expected indexing in a format string to behave as it does elsewhere but this seems not to be true. -- https://mail.python.org/mailman/listinfo/python-list
Re: indexing in format strings
On 11/04/2014 22:33, blindanagram wrote: Thanks, Mark and Terry, for your rapid responses. An interesting thread. Brian -- https://mail.python.org/mailman/listinfo/python-list
Re: How keep Python 3 moving forward
On 24/05/2014 08:13, wxjmfa...@gmail.com wrote: > Le vendredi 23 mai 2014 22:16:10 UTC+2, Mark Lawrence a écrit : >> An article by Brett Cannon that I thought might be of interest >> >> http://nothingbutsnark.svbtle.com/my-view-on-the-current-state-of-python-3 >> >> >> >> -- >> >> My fellow Pythonistas, ask not what our language can do for you, ask >> >> what you can do for our language. >> >> >> >> Mark Lawrence >> >> >> >> --- >> >> This email is free from viruses and malware because avast! Antivirus >> protection is active. >> >> http://www.avast.com > > = > = > > Quote: > """ And with Python 3.4 I really have not heard anyone complain that they > wouldn't like to use Python 3 instead of Python 2. """ > > Or the devs do not wish to listen. > > Python 3 will never work. It works for me. -- https://mail.python.org/mailman/listinfo/python-list
Bad comment on Enigmatic Code
Hi Jim, When you get a moment, can you please remove the wrongly formatted Python comment I made on your site? Thanks Brian -- https://mail.python.org/mailman/listinfo/python-list
Re: Bad comment on Enigmatic Code
On 10/09/2014 07:05, Steven D'Aprano wrote: > blindanagram wrote: > >> Hi Jim, >> >> When you get a moment, can you please remove the wrongly formatted >> Python comment I made on your site? >> >> Thanks >> >> Brian > > Who is Jim, and what comment are you talking about? > > Perhaps you have sent this message to the wrong address? > My apologies for this unintended message to this newsgroup. Brian -- https://mail.python.org/mailman/listinfo/python-list
GCD in Fractions
What is the rationale for gcd(x, y) in Fractions returning a negative value when y is negtive? For example gcd(3, -7) returns -1, which means that a co-prime test that would work in many other languages 'if gcd(x, y) == 1' will fail in Python for negative y. And, of course, since -|x| is less than |x|, returning -|x| rather than |x| is not returning the greatest common divisor of x and y when y is negative. -- https://mail.python.org/mailman/listinfo/python-list
Re: GCD in Fractions
On 23/09/2014 12:53, Wolfgang Maier wrote: > On 09/23/2014 10:16 AM, blindanagram wrote: >> What is the rationale for gcd(x, y) in Fractions returning a negative >> value when y is negtive? >> > > I guess it is implemented this way because its main use is in the > Fraction constructor. This is not guaranteed once it is exposed as a function that is available to all Python users. >> For example gcd(3, -7) returns -1, which means that a co-prime test that >> would work in many other languages 'if gcd(x, y) == 1' will fail in >> Python for negative y. [snip] > Given that the implementation is particularly useful for Fraction() it > is debatable whether the function shouldn't be called _gcd instead of > gcd, but otherwise it makes sense. As you imply, it would make sense if it hadn't been exposed for more general use. However, I am less sure that it is sensible to have a gcd function exposed for end user use when it conflicts with the function's usual definition. -- https://mail.python.org/mailman/listinfo/python-list
Re: GCD in Fractions
On 23/09/2014 13:50, Steven D'Aprano wrote: > blindanagram wrote: > >> What is the rationale for gcd(x, y) in Fractions returning a negative >> value when y is negtive? > > Good question. > > Normally, gcd is only defined for non-negative integers. Wolfram Mathworld, > for example, doesn't mention negative values at all (as far as I can see): > > http://mathworld.wolfram.com/GreatestCommonDivisor.html > > although buried deep in the documentation for Mathematica's GCD function is > hidden the fact that it treats GCD(-a, -b) the same as GCD(a, b): > > http://functions.wolfram.com/IntegerFunctions/GCD/04/02/01/ > > and sure enough Wolfram Alpha tells me that the GCD of *all* of: > > (100, 20) > (-100, 20) > (100, -20) > (-100, -20) > > are equal to +20. On the other hand, Excel and LibreOffice both give an > error for the GCD of a negative value, and I've seen versions of gcd() > which do the same as fractions.gcd. So I think there is not one single > standard way to extend GCD to negative numbers. > >> For example gcd(3, -7) returns -1, which means that a co-prime test that >> would work in many other languages 'if gcd(x, y) == 1' will fail in >> Python for negative y. > > True, but either of: > > abs(gcd(x, y)) == 1 > gcd(x, y) in (1, -1) > > will work. > > >> And, of course, since -|x| is less than |x|, returning -|x| rather than >> |x| is not returning the greatest common divisor of x and y when y is >> negative. > > That's a good argument for gcd if it were in a general maths module, but > since it is specifically used for generating fractions, I guess that the > developers won't be very convinced by that. That's an argument for a private gcd within the fractions module and a a 'normal' version in math. -- https://mail.python.org/mailman/listinfo/python-list
Re: GCD in Fractions
On 23/09/2014 18:20, Ian Kelly wrote: > On Tue, Sep 23, 2014 at 10:38 AM, Wolfgang Maier > wrote: >> Maybe fractions.gcd could be renamed, but be wrapped or reimplemented >> correctly somewhere else in the stdlib or even in fractions ? > > +1 > > I don't think the math module as suggested upthread is the right > place, as that module houses wrappers of C functions that operate on > floats. I'm also not sure where is better, though. Maybe the > reimplemented version should just keep the name fractions.gcd. Since the gcd is only used once in fractions anyway, it would be easy to change gcd here with very little impact on the performance of the fractions module (if necessary a local version could be added to work within fractions as it does now). -- https://mail.python.org/mailman/listinfo/python-list
Re: GCD in Fractions
On 23/09/2014 18:26, Stefan Behnel wrote: > Wolfgang Maier schrieb am 23.09.2014 um 18:38: >> While at first I thought this to be a rather irrelevant debate over module >> private vs public naming conventions, I now think the OP is probably right >> and renaming fractions.gcd to fractions._gcd may be a good idea. > For negative numbers, the "expected" behaviour seems to be unclear, so the > current behaviour is just as good as any, so backwards compatibility > concerns clearly win this fight. The expected behaviour is not unclear for anyone who takes the mathematical properties of the GCD seriously. It's a shame that Python doesn't. -- https://mail.python.org/mailman/listinfo/python-list
Re: GCD in Fractions
On 23/09/2014 18:55, Stefan Behnel wrote: > blindanagram schrieb am 23.09.2014 um 19:43: >> On 23/09/2014 18:26, Stefan Behnel wrote: >>> Wolfgang Maier schrieb am 23.09.2014 um 18:38: >>>> While at first I thought this to be a rather irrelevant debate over module >>>> private vs public naming conventions, I now think the OP is probably right >>>> and renaming fractions.gcd to fractions._gcd may be a good idea. >>> For negative numbers, the "expected" behaviour seems to be unclear, so the >>> current behaviour is just as good as any, so backwards compatibility >>> concerns clearly win this fight. >> >> The expected behaviour is not unclear for anyone who takes the >> mathematical properties of the GCD seriously. It's a shame that Python >> doesn't. > > May I ask how you get from one little function in the well-defined scope of > a data type module (which is not named "math" or "integers" or "natural" or > anything like it) to the extrapolation that Python doesn't take > mathematical properties serious? Firstly I have to choose between two possibilities: (a) that the name of the function has been deliberately chosen to imply that it calculates the mathematical function known as the 'greatest commmon divisor'; or (b) that the initials 'gcd' have been chosen by pure chance and the association between this function and the 'greatest commmon divisor' has arisen from pure coincidence. Of these, I find (a) overwhelmingly more likely. Seccondly (as others here have pointed out), the mathematical properties of the greatest common divisor are well defined for both positive and negative integers. But the Python function called gcd doesn't have some of these properties. I hence conclude that Python doesn't take the mathematical properties of the greatest common divisor seriously since it doesn't ensure that its version of this function has these properties. -- https://mail.python.org/mailman/listinfo/python-list
Re: GCD in Fractions
On 23/09/2014 20:30, Mark Lawrence wrote: > On 23/09/2014 18:43, blindanagram wrote: >> On 23/09/2014 18:26, Stefan Behnel wrote: >>> Wolfgang Maier schrieb am 23.09.2014 um 18:38: >>>> While at first I thought this to be a rather irrelevant debate over >>>> module >>>> private vs public naming conventions, I now think the OP is probably >>>> right >>>> and renaming fractions.gcd to fractions._gcd may be a good idea. >>> For negative numbers, the "expected" behaviour seems to be unclear, >>> so the >>> current behaviour is just as good as any, so backwards compatibility >>> concerns clearly win this fight. >> >> The expected behaviour is not unclear for anyone who takes the >> mathematical properties of the GCD seriously. It's a shame that Python >> doesn't. >> > All you need do is raise an issue on the bug tracker, provide a patch to > code, test and docs and the job is done. Thank you for your helpful comment. I will happily do this if after discussion here there is a reasonable level of support and encouragement for such an action. However, there is at least one person here who takes the view that backward compatibility outranks mathematical correctness and I don't want to find that 'I am banging my head against a brick wall' if this is likely to be the stance that Python developers take. -- https://mail.python.org/mailman/listinfo/python-list
Re: GCD in Fractions
On 24/09/2014 12:44, Steven D'Aprano wrote: > blindanagram wrote: [snip] > - Mathworld says that GCD of two negative numbers is a negative number; > > - but Mathematica says that GCD of two negative numbers is a positive; > > - Wikipedia agrees with Mathematica and disagrees with Mathworld; After looking at these (and several other) on-line mathematical sites, I realised that I would have to go back to long standing mathemmatical references to find how the gcd is defined by those that explicitly cover the greatest common divisor for negative integers (I did this before raising the issue here). All four that I have so far looked at have definitions that lead to gcd(a, b) for integers being equal to gcd(|a|, |b|). I hope to visit a University library shortly to review more. Does anyone know of such a reference that uses a definition that conflicts with gcd(a, b) for integers being equal to gcd(|a|, |b|)? -- https://mail.python.org/mailman/listinfo/python-list
Re: GCD in Fractions
On 24/09/2014 17:13, Stefan Behnel wrote: > blindanagram schrieb am 24.09.2014 um 15:25: >> On 24/09/2014 12:44, Steven D'Aprano wrote: [snip] > We have an open tracker ticket now on changing *something* about the > current situation. Let's just add some new functionality somewhere if > people really want it (as in "need it for their code", not just "want it > for purity reasons" or "sleep better when they know it's out there"), but > please, everyone, stop complaining about "fractions.gcd" not catering for > your needs. It does what it's there for, even if the name is more public or > more generic than you might want. There are other ways to fix the actual > problem and move on. This has never been about my need to use fractions.gcd since I don't even use it (I have my own implementation). -- https://mail.python.org/mailman/listinfo/python-list
Re: GCD in Fractions
On 24/09/2014 17:34, Mark Lawrence wrote: > On 24/09/2014 12:14, Mark Dickinson wrote: >> Mark Lawrence yahoo.co.uk> writes: >>> Somebody got there first http://bugs.python.org/issue22477 >> >> I think there's good reason to suspect that Brian Gladman and >> blindanagram are one and the same. :-) >> >>>>> sorted("BrianGladman".lower()) == sorted("blindanagram") >> True >> > Is that considered proof that I still reign supreme as the most > unobservant person on the planet? :) I am afraid not - you are far from alone :-) I have used this alias for quite a few years now on sci.crypt without people realising who 'owns' it (there are reasons why people on sci.crypt might discover this). -- https://mail.python.org/mailman/listinfo/python-list
Snowed In?
Hi Geoff Are you snowed in? Its OK here. Brian -- http://mail.python.org/mailman/listinfo/python-list
Enigma (Tantaliser 482)
Hi Jim, I woke up this morning realising that my published code for this tantaliser is not very good. I would hence be most grateful if you could substitute the attached version. best regards, Brian from itertools import combinations, permutations, product # enumerate the names A, B, C, D, E, F, G = range(7) nms = dict(enumerate(('Alice', 'Beatrice', 'Constance', 'Deborah', 'Emily', 'Flavia', 'Gertrude'))) # enumerate the sins an, av, en, it, lu, pr, sl = range(7) sns = dict(enumerate(('anger', 'avarice', 'envy', 'intemperance', 'lust', 'pride', 'sloth'))) # all seven sins occur among Beatrice, Deborah, Emily, Gertrude so # we have the following arrangement of unknown sins (*), which must # be permutations of anger, avarice, envy, intemperance and pride # Beatrice: *, * # Deborah: lust, * # Emily: lust, * # Gertrude: sloth, * s1 = {an, av, en, it, pr} sol_g1 = set() for p in permutations(s1, 3): # the set of sins for Beatrice, Deborah, Emily and Gertrude tb, td, te, tg = s1.difference(p), {lu, p[0]}, {lu, p[1]}, {sl, p[2]} sol_g1.add(tuple(frozenset(x) for x in (tb, td, te, tg))) # the arrangement of unknown sins among Alice, Constance and Flavia is: # Alice: sloth, * # Constance: anger, * # Flavia: *, * # since each sin occurs against two names, there are 14 sins among all # seven names; the first group above has all seven sins plus lust, so # this group must have all seven sins minus lust; so the four unknowns # here must be permutations of avarice, envy, intemperance and pride s2 = {av, en, it, pr} sol_g2 = set() for q in permutations(s2, 2): # the set of sins for Alice, Constance and Flavia ta, tc, tf = {sl, q[0]}, {an, q[1]}, s2.difference(q) sol_g2.add(tuple(frozenset(x) for x in (ta, tc, tf))) for (tb, td, te, tg), (ta, tc, tf) in product(sol_g1, sol_g2): # map names to pairs of sins p2s = dict(zip(range(7), (ta, tb, tc, td, te, tf, tg))) # Constance, Emily and Flavia have no sin shared by any pair if any(p2s[x] & p2s[y] for x, y in combinations((C, E, F), 2)): continue # Alice and Gertrude admit sloth, Deborah and Emily admit lust if not (sl in p2s[A] and sl in p2s[G] and lu in p2s[D] and lu in p2s[E]): continue # Alice is not proud and Beatrice is not avaricious if pr in p2s[A] or av in p2s[B]: continue # Flavia is neither intemperate nor proud if p2s[F].intersection([it, pr]): continue # Deborah shows no anger; Constance and Deborah share a sin if an in p2s[D] or not p2s[C] & p2s[D]: continue u = [nms[x] for x in range(7) if it in p2s[x]] v = [nms[x] for x in range(7) if en in p2s[x]] print('Intemperance: {} and {}; Envy: {} and {}.'.format(*u, *v)) print() for n in range(7): print('{}: {}, {}'.format(nms[n], *(sns[s] for s in sorted(p2s[n] -- https://mail.python.org/mailman/listinfo/python-list
Re: Enigma (Tantaliser 482)
On 19/05/2017 10:06, BlindAnagram wrote: > Hi Jim, > > I woke up this morning realising that my published code for this > tantaliser is not very good. > > I would hence be most grateful if you could substitute the attached version. > >best regards, > > Brian Apologies - posted in error -- https://mail.python.org/mailman/listinfo/python-list
Re: Proposed new syntax
On 10/08/2017 15:28, Steve D'Aprano wrote: > Every few years, the following syntax comes up for discussion, with some > people > saying it isn't obvious what it would do, and others disagreeing and saying > that it is obvious. So I thought I'd do an informal survey. > > What would you expect this syntax to return? > > [x + 1 for x in (0, 1, 2, 999, 3, 4) while x < 5] 1, 2, 3 > For comparison, what would you expect this to return? (Without actually trying > it, thank you.) > > [x + 1 for x in (0, 1, 2, 999, 3, 4) if x < 5] 1, 2, 3, 4, 5 > > > > How about these? > > [x + y for x in (0, 1, 2, 999, 3, 4) while x < 5 for y in (100, 200)] 100, 200, 101, 201, 102, 202 > > [x + y for x in (0, 1, 2, 999, 3, 4) if x < 5 for y in (100, 200)] 100, 200, 102, 201, 102, 202, 103, 203, 104, 204 -- https://mail.python.org/mailman/listinfo/python-list