Re: Python slang
Lawrence D’Oliveiro: >> [...] as much like C++ as >> possible. > > Nevertheless, Python copied the C misfeature [...] You segued a little too easily from C++ to C. When talking language evolution and inspirations, they are entirely different things. - Anders -- https://mail.python.org/mailman/listinfo/python-list
Re: Python slang
Marco Sulla via Python-list: > Well, they are the most used languages. They weren't when Python was created. Python's terms raise/except and self were normal for the time. C++ was the odd one out. throw/catch and this are Stroustrup's inventions, no other language used those terms. It was only later that language designers fell into the notion that it was crucial for a new language's success to look as much like C++ as possible. regards, Anders -- https://mail.python.org/mailman/listinfo/python-list
Re: sobering observation, python vs. perl
Charles T. Smith: I've really learned to love working with python, but it's too soon to pack perl away. I was amazed at how long a simple file search took so I ran some statistics: Write Python in pythonic style instead of translated-from-Perl style, and the tables are turned: $ cat find-rel.py | import sys | def main(): | for fn in sys.argv[1:]: | tn = None | with open(fn, 'rt') as fd: | for line in fd: | if ' is ready' in line: | tn = line.split(' is ready', 1)[0] | elif 'release_req' in line: | print tn | main() $ time python find-rel.py *.out real0m0.647s user0m0.616s sys0m0.029s $ time perl find-rel.pl *.out real0m0.935s user0m0.910s sys0m0.023s I don't have your log files and my quickly assembled test file doesn't actually contain the phrase 'release_req', so my results may be misleading. Perhaps you'll try it and post your results? regards, Anders -- https://mail.python.org/mailman/listinfo/python-list
Re: NaN comparisons - Call For Anecdotes
Steven D'Aprano: I'll give you the benefit of the doubt, and assume that when you first posted you hadn't realised that the audience here does not have the relevant experience, but by refusing to ask the question elsewhere, and by making snide comments that "they don't like beer", that pretty much gives the game away that you're looking to have your opinion confirmed rather than looking for an honest answer. I really did run out of time when I said I did: I spent the last 5 days running a chess tournament with 137 participants, with the tournament management software written in Python by yours truly. Which worked beautifully, Python is a great language. And I'm going to Iceland on vacation tomorrow, so I'm not going to start a new discussion of a different mailing list just now, maybe later. Not everyone is as prolific a writer as you are, Steven. The talk about "the wrong list" would have carried more weight if you had started out by saying "wrong list", instead of going through every other argument first, before punting like that. By the way, which list is the appropriate one? The numpy and SciPy mailing lists are first and foremost about numpy and SciPy, I presume. Is there a general numerics-list somewhere also? I don't see any on https://mail.python.org/mailman/listinfo. By the way, you guys seem to have overlooked the opportunity for arbitrage: *Anyone* can go to a numerical list, poll for examples, and come back and earn some beer :) regards, Anders -- https://mail.python.org/mailman/listinfo/python-list
Re: NaN comparisons - Call For Anecdotes
alister wrote: I don't have time to start this discussion over again on another mailing list. Don't anyone on those lists read python-list also? they possibly do, but prefer to keep discussions to the proper forum The semantics of the Python programming language is on-topic for python-list. This is about float.__eq__, not about numpy or SciPy. Maybe they just don't like beer? regards, Anders -- https://mail.python.org/mailman/listinfo/python-list
Re: NaN comparisons - Call For Anecdotes
Joel Goldstick wrote: I've been following along here, and it seems you haven't received the answer you want or need. So far I received exactly the answer I was expecting. 0 examples of NaN!=NaN being beneficial. I wasn't asking for help, I was making a point. Whether that will lead to improvement of Python, well, I'm not too optimistic, but I feel the point was worth making regardless. regards, Anders -- https://mail.python.org/mailman/listinfo/python-list
Re: NaN comparisons - Call For Anecdotes
Ethan Furman: I would suggest you ask for this on the numerical mailing lists instead of here -- and you may not want to offer a beer to everyone that has an anecdote for NaN behavior being useful. I don't have time to start this discussion over again on another mailing list. Don't anyone on those lists read python-list also? regards, Anders -- https://mail.python.org/mailman/listinfo/python-list
Re: NaN comparisons - Call For Anecdotes
Steven D'Aprano wrote: I assumed that you realised that the 64-bit(?) values you were receiving in binary could be interpreted as ints. After all, you have to unpack them from some bytes. Since that's not what you're doing, I have no idea what it is. Stop obsessing over how NaN's came to exist in my software. That's just context. The argument is over how those NaNs should behave. Their provenance is not relevant. I have no idea how you imagine processing IEEE-754 floating-point values in int form. Cast your 64-bit float into a 64-bit int. I can construct a bijective mapping between any data structure and a subset of the natural numbers, but that has nothing to do with practical programming. A "cast" value would be impossible to work with. My use case is: Working with IEEE-754 floating-point values. That means storing and retrieving them, serialising and transferring them, accepting them as user input, printing them, all the usual things you do with values. But apparently not arithmetic? Of course also arithmetic. I left it out of the list because then you would say "hah! if you're doing arithmetic then it's not a generic algorithm". Apparently I can't win, you are going to nitpick anything I write. Ah, well there's your problem. NANs are special, as a signed zeroes and INFs. Does it distress you that x + x = x when x is an INF? No. When the same algorithm is capable of dealing with ints, bytestrings, text string, tuples, list, dictionaries, time stamps, NoneType's, bools, floating-point floats and a thousand other things, ^ Obviously not, or you wouldn't be complaining about the inability to handle floats. NaNs are not floating-point values. A floating-point value has a sign, an exponent and a mantissa. They are "IEEE 754 floating point" values, though. The hardware devices generating your float data... do they also generate ints, bytestrings, text strings, tuples, lists, dicts, time stamps, None, bools, and a thousand other things? If not, I wonder why you are insisting that you have to handle a *specialised* data type using a *generic* algorithm. All the other types are also specialised, for their separate purpose. That doesn't make them non-reflexive. I'm not unsympathetic to your problem, which is why I proposed two new operators, === and !==, and a change to == and !=, in another thread. Would == always doing an identity test before calling __eq__ solve your problem? If not, what would it take to solve your problem? It would not solve it. Two bitwise identical NaNs would still compare different. What would solve the problem is making identical NaNs compare equal. regards, Anders -- https://mail.python.org/mailman/listinfo/python-list
Re: NaN comparisons - Call For Anecdotes
Chris Angelico: If you need to do bitwise comparisons, then the easiest way is to use the bitpattern, converted to an integer. A 64-bit float becomes a 64-bit integer. It's then very simple to compare them, and reflexivity is maintained. At what point do you actually need them to be floats? What are you really doing with them? What does one do with floats? Add, subtract, multipy, divide, display, input, store and retrieve to and from various formats. All the usual stuff. Why would my use be different from anyone elses? What you and Steven seem to be saying is that I should employ strategies to avoid NaNs ever being compared. I'll take that one step further and say that as long as NaN!=NaN, everyone should seek to avoid NaNs ever being compared. regards, Anders -- https://mail.python.org/mailman/listinfo/python-list
Re: NaN comparisons - Call For Anecdotes
Steven D'Aprano wrote: It seems to me that the trivial work-around is: * gather packed floats from some device, as ints * process them *as ints* in some way which requires reflexivity * unpack back into floats * (maybe) much later perform numeric calculations on them Although perhaps I don't understand your use-case. Clearly you do not. floats are not ints. I have no idea how you imagine processing IEEE-754 floating-point values in int form. My use case is: Working with IEEE-754 floating-point values. That means storing and retrieving them, serialising and transferring them, accepting them as user input, printing them, all the usual things you do with values. And doing so in a way that does not require special handling in algorithms that are otherwise generic. When the same algorithm is capable of dealing with ints, bytestrings, text string, tuples, list, dictionaries, time stamps, NoneType's, bools, floating-point floats and a thousand other things, then NaNs stand out as the values that have special algorithm-breaking magic. I gave an example of such an algorithm in an earlier reply to Chris. regards, Anders -- https://mail.python.org/mailman/listinfo/python-list
Re: NaN comparisons - Call For Anecdotes
I wrote: | class Monitor(Thread): | def run(self): | old = self.get_current_value() | while not self.Terminated: | new = self.get_current_value() | if new != old: | print(time.asctime(), "changed to", new) | old = new | time.sleep(1) Huh, I don't know what happened to the identation here, I'l try again: class Monitor(Thread): def run(self): old = self.get_current_value() while not self.Terminated: new = self.get_current_value() if new != old: print(time.asctime(), "changed to", new) old = new time.sleep(1) regards, Anders -- https://mail.python.org/mailman/listinfo/python-list
Re: [Python-Dev] == on object tests identity in 3.x
Steven D'Aprano wrote: - Dropping reflexivity preserves the useful property that NANs compare unequal to everything. Please present an example from real life where that turned out useful, and earn yourself a beer! I've only experienced examples to the contrary. - Keeping reflexivity for NANs would have implied some pretty nasty things, e.g. if log(-3) == log(-5), then -3 == -5. >>> log(-3) Traceback (most recent call last): File "", line 1, in ValueError: math domain error You were perhaps referring to the log functions in C and Fortran, not math.log? The tradeoffs are different in those languages, so choices the IEEE-754 committee made with C and Fortran in mind may be less relevant for Python. regards, Anders -- https://mail.python.org/mailman/listinfo/python-list
Re: NaN comparisons - Call For Anecdotes
I wrote: Steven D'Aprano wrote: Oh, you've read the IEEE-754 standard, and that's what it says? "We're going to specify this behaviour for NANs just to annoy people" perhaps? I was referring to the deliberate choice to enforce IEEE-754 rules in Python. There is no force of law that requires Python to do so. And just to be clear, I didn't mean python-dev did this to annoy people either. I just meant that the choice made is not supported by any use case, so there's no upside to outweigh the problems it creates. At least I've yet to hear any use case. So far I'm 0 beers in debt. regards, Anders -- https://mail.python.org/mailman/listinfo/python-list
Re: NaN comparisons - Call For Anecdotes
Den 14-07-08 19:23, Skip Montanaro skrev: In addition to what others have written, I will add one thing. There are certainly situations where raising an exception is bad. Consider all the people in the scientific computing community doing fancy linear algebra sorts of things, often with missing data. They generally want NaN propagated and not have some long running calculation crash in the middle. NaN!=NaN doesn't cause NaN's to propagate any more or any less. It simply causes a different branch of code to run, quite often the wrong one. regards, Anders -- https://mail.python.org/mailman/listinfo/python-list
Re: NaN comparisons - Call For Anecdotes
Ethan Furman skrev: What exception? Apparently your claims about NaN in Python are all wrong -- have you been using a custom interpreter? >>> float('inf') - float('inf') nan If you deliberately try to manufacture NaN's, you can. I never said otherwise. regards, Anders -- https://mail.python.org/mailman/listinfo/python-list
Re: NaN comparisons - Call For Anecdotes
Steven D'Aprano wrote: Oh, you've read the IEEE-754 standard, and that's what it says? "We're going to specify this behaviour for NANs just to annoy people" perhaps? I was referring to the deliberate choice to enforce IEEE-754 rules in Python. There is no force of law that requires Python to do so. regards, Anders -- https://mail.python.org/mailman/listinfo/python-list
Re: NaN comparisons - Call For Anecdotes
Ian Kelly wrote: As far as I know nothing changed between 2.4 and 2.7 in this regard. Python has always had NaN compare unequal to everything, per the standard. It might have been platform-specific in 2.4. Okay, here's your problem: there isn't just one binary representation for NaN. I'm fully aware of that. Whether NaN's are one equivalence class or several is not the issue. What matters is the integrity of the equivalence relation. Following the standard isn't a good reason itself? If a standard tells you to jump of a cliff... regards, Anders -- https://mail.python.org/mailman/listinfo/python-list
Re: NaN comparisons - Call For Anecdotes
Chris Angelico wrote: Why *should* all NaNs be equal to each other? You said on the other list that NaN==NaN was equivalent to (2+2)==(1+3), but that assumes that NaN is a single "thing". I don't actually care if all NaN bitpatterns are in the same equivalence group or if each bitpattern is its own equivalence group. I just want the == equivalence relation to be sound. For hash keys, float object identity will successfully look them up: Except you can't expect to rely on object identity in most interesting cases. >>> x = float('nan') >>> import struct >>> y = struct.unpack('>> d[x] = "found" >>> d[y] Traceback (most recent call last): File "", line 1, in KeyError: nan and also: >>> def f(): return float('inf')/float('inf') >>> f() == f() False >>> f() is f() False But any time you compare floats for equality, you *already* have to understand what you're doing (because of rounding and such), so I don't see why the special case on NaN is significant, unless as mentioned above, you want all NaNs to be equal, which doesn't make sense. Let me conjure up a simple example: | class Monitor(Thread): | def run(self): | old = self.get_current_value() | while not self.Terminated: | new = self.get_current_value() | if new != old: | print(time.asctime(), "changed to", new) | old = new | time.sleep(1) This is a completely generic change detection algorithm, and not a "floating-point algorithm" in any way: It will work on strings, lists, sets, anything that get_current_value returns, including non-NaN floats. You don't need to know anything about floating-point representation to write or use such an algorithm, why should you? It works on tuples, sets, lists, serial port handles, module objects, pretty much anything you can imagine -- except NaN floats. regards, Anders -- https://mail.python.org/mailman/listinfo/python-list
NaN comparisons - Call For Anecdotes
Most people don't need to deal with NaN's in Python at all, fortunately. They just don't appear in normal computation, because the interpreter raises an exception instead. It happens in my work I come across them quite a lot. I'm writing software that talks to embedded applications that can contain NaN values for a variety of reasons - never-initialised storage, initialise-to-NaN, hardware failures etc. So when my software reads these values in binary, unpack them using the struct module, and goes to work. And NaN's are no different from any other value, it's something to store, compare, display etc. And that worked fine in my Python 2.4 apps. Then I upgraded to 2.7 and it broke. Because 2.7 goes out of it's way to ensure that NaN's don't compare equal to themselves. I discovered it when a sanity check told me that two functions, to_binary and from_binary, weren't each other's inverse, as they were intended to be. Apparently, bitPattern==to_binary(from_binary(bitPattern)) wasn't true for this particular value of bitPattern. Of course, the bit pattern in question was the binary representation for a floating-point NaN. Panic time! If I can't trust == to return True for (mathematically) equal objects, that means that every single algorithm I had ever written that explicitly or implicitly does .__eq__ or .__ne__ comparison was suspect! That meant I had 3 lines of code to review. Every time there's a comparison, if there was any chance that either value could be a float NaN, I would have to change e.g. if x==y: to if x==y or (isinstance(x, float) and isinstance(y, float) and math.isnan(x) and math.isnan(y)): To make it bearable, I could wrap the pattern up in a function and write if my_equal(x,y): but I would still lose, because the standard library does == and != all over the place without calling my_equal. In the end I came up with this hack: Every time I struct.unpack'd a float, I check if it's a NaN, and if it is, then I replace it with a reference to a single, shared, "canonical" NaN. That means that container objects that skip __equal__ when comparing an object to itself will work -- e.g. hash keys. It's half a solution, of course: Any further computation with a NaN value will change it to a different NaN object, so I still needed to do explicit NaN-checks in various places. I'm sure there are still NaN-related bugs in my code, but right now it's "good enough" - I haven't seen NaN-related bugs in a good while. Now, all this bothers me. Not that I had to do some work to get stuff to work in an imperfect world. No, what bothers me is that this behaviour was explicitly and deliberately put in for no good reason. The only reason is "standard says so". Not that there's any legal requirement for Python to follow the IEEE-754 standard. Or for that matter, for Python's spelling of IEEE-754 comparisons to be "==". So I make this claim: float.__eq__ implementing IEEE-754 NaN comparison rules creates real problems for developers. And it has never, ever, helped anyone do anything. "Never" is a strong claim, and easily disproven if false: Simply provide a counterexample. So that is my challenge: If you have a program (a pre-existing and useful one, not something artificial created for this challenge) that benefits from NaN!=NaN and that would fail if x==x for all float objects x, then please come forward and show it, and I'll buy you a beer the next time I'm at PyCon. regards, Anders -- https://mail.python.org/mailman/listinfo/python-list
Re: grimace: a fluent regular expression generator in Python
Ben Last wrote: north_american_number_re = (RE().start .literal('(').followed_by.exactly(3).digits.then.literal(')') .then.one.literal("-").then.exactly(3).digits .then.one.dash.followed_by.exactly(4).digits.then.end .as_string()) Very cool. It's a bit verbose for my taste, and I'm not sure how well it will cope with nested structure. Here's my take on what readable regexps could look like: north_american_number_re = RE.compile(r""" ^ "(" digit{3} ")" # And why shouldn't a regexp "-" digit{3} # include en embedded comment? "-" digit{4} $ """) The problem with Perl-style regexp notation isn't so much that it's terse - it's that the syntax is irregular (sic) and doesn't follow modern principles for lexical structure in computer languages. You can get a long way just by ignoring whitespace, putting literals in quotes and allowing embedded comments. Setting the re.VERBOSE flag achieves two out of three, so you can write: north_american_number_re = RE.compile(r""" ^ ( \d{3} ) # Definite improvement, though I really miss putting - \d{3} # literals in quotes. - \d{4} $ """) It's too bad re.VERBOSE isn't the default. regards, Anders -- http://mail.python.org/mailman/listinfo/python-list
Re: Tabs -vs- Spaces: Tabs should have won.
Thomas 'PointedEars' Lahn wrote: > I am getting the idea here that you mean the right thing, but that you > explain it wrong. Feel free to write the much longer essay that explains it all unambiguously, I'm not going to. regards, Anders -- http://mail.python.org/mailman/listinfo/python-list
Re: Tabs -vs- Spaces: Tabs should have won.
Steven D'Aprano wrote: > I can't fathom why 8 position tabs were *ever* the default, let alone why > they are still the default. That's because they were not invented as a means for programmers to vary indentation. Originally, tabs were a navigation device: When you press the tab key, you skip ahead to the next tab column. The notion that whitespace characters are inserted into the text would have been very alien to someone using text processing software anno 1970. Same thing with space and enter; on typewriters the space bar doesn't "type" anything onto the paper, it moves to the next column, and that thinking carried over to computers. The reason the tab stop is a full 8 positions: for faster navigation. If it were 3 positions, it would take forever to skip from the start of line to column 60. You'd appreciate that, if you were e.g. writing a fiduciary report with some text to the left and two number columns to the right, back in the day before spreadsheets and word processor tables. Skip a column or two too far? Adjust by backspacing (another navigation key). As for why 8 is still the default - well, what else should it be? 2, 3, 4, 5? I for one am thankful that we have so far been spared the flamewar armegeddon of all the world's programmers trying to agree on that. > Cameron Simpson wrote: >> Personally, I like to use the tab _key_ as an input device, but to have >> my editor write real spaces to the file in consequence. Just like in the old days:) regards, Anders -- http://mail.python.org/mailman/listinfo/python-list
Re: Q: finding distance between 2 time's
jkv wrote: Hi Martin, What i usally do is to convert the two times to seconds since epoch and compare the two values in seconds. You can use time.mktime to convert localtime to seconds since epoch. There's no need to convert - simply retrieve the times as absolute times to begin with: file_age_in_seconds = time.time() - os.path.getmtime(filename) Only convert to local time for presentation. - Anders -- http://mail.python.org/mailman/listinfo/python-list
Re: Boolean tests
Ethan Furman wrote: > Even if we find out that C.__nonzero__ is called, what was it that > __nonzero__ did again? reinforce the impression that he is unaware of the double-underscore functions and what they do and how they work. Only if your newsreader malfunctioned and refused to let you read the rest of the paragraph. Of course I know what __nonzero__ does. regards, Anders -- http://mail.python.org/mailman/listinfo/python-list
Re: Boolean tests [was Re: Attack a sacred Python Cow]
Steven D'Aprano wrote: On Tue, 29 Jul 2008 00:23:02 +, Steven D'Aprano wrote: Dude. Dude. Just... learn some Python before you embarrass yourself further. I'm sorry Anders, that was a needlessly harsh thing for me to say. I apologize for the unpleasant tone. Still, __nonzero__ is a fundamental part of Python's behaviour. You should learn about it. Hm, first you apologize, then you repeat the insult? That's no basis for a conversation. Bye from here. regards, Anders -- http://mail.python.org/mailman/listinfo/python-list
Re: Boolean tests [was Re: Attack a sacred Python Cow]
Steven D'Aprano wrote: On Sun, 27 Jul 2008 23:45:26 -0700, Carl Banks wrote: I want something where "if x" will do but a simple explicit test won't. Explicit tests aren't simple unless you know what type x is. If you don't even know a duck-type for x, you have no business invoking any methods on that object. If you do know a duck-type for x, then you also know which explicit test to perform. Explicit tests are not necessarily simple for custom classes. Testing for emptiness could be arbitrarily complex. That's why we have __nonzero__, so you don't have to fill your code with complex expressions like (say) if len(x.method()[x.attribute]) > -1 Instead you write it once, in the __nonzero__ method, and never need to think about it again. Okay, so you have this interesting object property that you often need to test for, so you wrap the code for the test up in a method, because that way you only need to write the complex formula once. I'm with you so far. But then you decide to name the method "__nonzero__", instead of some nice descriptive name? What's up with that? This is the kind of code I would write: class C: def attribute_is_nonnegative(self): return len(self.method()[self.attribute]) > -1 ... c = get_a_C() if c.attribute_is_nonnegative(): ... Now suppose you were reading these last few lines and got to wondering if get_a_C might ever return None. The answer is obviously no. get_a_C must always return a C object or something compatible. If not, it's a bug and an AttributeError will ensue. The code tells you that. By giving the method a name the intent of the test is perfectly documented. In comparison, I gather you would write something like this: class C: def __nonzero__(self): return len(self.method()[self.attribute]) > -1 ... c = get_a_C() if c: ... Again, the question is, can get_a_C return None? Well that's hard to say really. It could be that "if c" is intended to test for None. Or it could be intended to call C.__nonzero__. Or it could be cleverly intended to test not-None and C.__nonzero__ at the same time. It may be impossible to discern the writer's true intent. Even if we find out that C.__nonzero__ is called, what was it that __nonzero__ did again? Did it test for the queue being non-empty? Did it test for the queue being not-full? Did it test whether for the consumer thread is running? Did it test for if there are any threads blocked on the queue? Better dig up the class C documentation and find out, because there is no single obvious interpretation of what is means for an object to evaluate to true. "if x" is simple to type, but not so simple to read. "if x.namedPredicate()" is harder to type, but easier to read. I prefer the latter because code is read more often than it is written. regards, Anders -- http://mail.python.org/mailman/listinfo/python-list
Re: Rant (was Re: x*x if x>10
Gary Herron wrote: >>> A = [1,2,3] >>> B = [4,5,6] >>> C = [7,8,9] >>> A+B+C [1, 2, 3, 4, 5, 6, 7, 8, 9] >>> sum([A,B,C], []) [1, 2, 3, 4, 5, 6, 7, 8, 9] Careful now, this can be very slow. sum uses __add__, not __iadd__, which gives this approach quadratic worst-case runtime. - Anders -- http://mail.python.org/mailman/listinfo/python-list
Re: Recursion Performance Question
B wrote: > > # pass in window handle and parent node > def gwl(node, hwnd): > if hwnd: > yield node, hwnd > for nd, wnd in Wnd.gwl(node.children[-1], GetWindow(hwnd, > GW_CHILD)): > yield nd, wnd > for nd, wnd in Wnd.gwl(node, GetWindow(hwnd, GW_HWNDNEXT)): > yield nd, wnd [...] > > Now it works, but it runs quite slow (compared to the c++ app). I > changed gwl from strait recursion to use a generator and that helped, > but it still takes 0.5-1.0 seconds to populate the tree. Actually the generator could well be the problem here, because of time spent on yield propagation: gwl has worst-case quadratic performance, the worst case being if the tree is unbalanced and deep, because every yielded value must pass through a chain of propagation for-loops. Straight recursion should be faster; I don't know what you did to make it slow, but try something along these lines: def gwl_helper(node, hwnd, collect): if hwnd: collect((node,hwnd)) gwl_helper(node.children[-1], GetWindow(hwnd, GW_CHILD), collect) gwl_helper(node, GetWindow(hwnd, GW_HWNDNEXT), collect) def gwl(node, hwnd): result = [] gwl_helper(node, hwnd, result.append) return result - Anders -- http://mail.python.org/mailman/listinfo/python-list
Re: Python's "only one way to do it" philosophy isn't good?
Alexander Schmolck wrote: > "Anders J. Munch" <[EMAIL PROTECTED]> writes: > >> Like Steven said, tail-call optimisation is not necessary as you can always >> hand-optimise it yourself. > > Care to demonstrate on some code written in CPS (a compiler or parser, say)? I meant tail recursion, not tail-call, sorry, that was just my fingers trying to save typing. - Anders -- http://mail.python.org/mailman/listinfo/python-list
Re: Python's "only one way to do it" philosophy isn't good?
Neil Cerutti wrote: > On 2007-06-12, Anders J. Munch <[EMAIL PROTECTED]> wrote: >> Converting tail-recursion to iteration is trivial, and >> perfectly reasonable for a human to do by hand. > > For simple recursive tail calls, yeah, it can be. Translating a > tail-recursive Factorial function into a while loop is easy. But > tail-call optimization technically works for any tail-call, > including mutual recursion, and non-recursive tail-calls. You > can't reasonably hand-optimize away the stack frame for all > tail-calls. I may have misunderstood, I thought we were talking about tail recursion only. The general tail-call optimisation, where all leaf calls become jumps and the called function usurps the current stack frame, is a different ballgame entirely. There's no pure-Python transformation for that, but that still doesn't mean you need CPS. General tail-call optimisation is of course completely out-of-bounds for Python, because it ruins tracebacks. Unlike tail recursion, which could use recursion counters. - Anders -- http://mail.python.org/mailman/listinfo/python-list
Re: Python's "only one way to do it" philosophy isn't good?
Paul Rubin wrote: > Steven D'Aprano <[EMAIL PROTECTED]> writes: >>> Not tail calls, in general, no. >> Sorry, how does that work? You're suggesting that there is an algorithm >> which the compiler could follow to optimize away tail-recursion, but human >> beings can't follow the same algorithm? >> >> Now I'm confused. > > The usual compiler method is to translate the code into > continuation-passing style and thereby gain tail-recursion > optimization automagically. There's no need to go into CPS just to optimise tail-recursion. After all, compilers were optimising tail-calls decades before Appel's work on SML/NJ. Converting tail-recursion to iteration is trivial, and perfectly reasonable for a human to do by hand. You add an outer "while True"-loop, the recursive call becomes a tuple assignment, and other code paths end with a break out of the loop. Completely mechanical and the resulting code doesn't even look that bad. Like Steven said, tail-call optimisation is not necessary as you can always hand-optimise it yourself. - Anders -- http://mail.python.org/mailman/listinfo/python-list
Re: Where can I suggest an enchantment for Python Zip lib?
durumdara wrote: > Only one way I have to control this: if I modify the ZipFile module. Since you already have the desired feature implemented, why don't you submit a patch. See http://www.python.org/patches/ - Anders -- http://mail.python.org/mailman/listinfo/python-list
Re: PEP 3131: Supporting Non-ASCII Identifiers
Hendrik van Rooyen wrote: > And we have been through the Macro thingy here, and the consensus > seemed to be that we don't want people to write their own dialects. Macros create dialects that are understood only by the three people in your project group. It's unreasonable to compare that to a "dialect" such as Mandarin, which is exclusive to a tiny little clique of one billion people. - Anders -- http://mail.python.org/mailman/listinfo/python-list
Re: PEP 3131: Supporting Non-ASCII Identifiers
Eric Brunel wrote: > You could tell that the rule should be that if the project has the > slightest chance of becoming open-source, or shared with people not > speaking the same language as the original coders, one should not use > non-ASCII identifiers. I'm personnally convinced that *any* industrial > project falls into this category. So accepting non-ASCII identifiers is > just introducing a disaster waiting to happen. Not at all. If the need arises, you just translate the whole thing. Contrary to popular belief, this is a quick and easy thing to do. So YAGNI applies, and even if you find that you do need it, you may still have won on the balance! As the time saved by using your native language just might outweigh the time spent translating. - Anders -- http://mail.python.org/mailman/listinfo/python-list
Re: PEP 3131: Supporting Non-ASCII Identifiers
Alex Martelli wrote: > > Homoglyphic characters _introduced by accident_ should not be discounted > as a risk, as, it seems to me, was done early in this thread after the > issue had been mentioned. In the past, it has happened to me to > erroneously introduce such homoglyphs in a document I was preparing with > a word processor, by a slight error in the use of the system- provided > way for inserting characters not present on the keyboard; I found out > when later I went looking for the name I _thought_ I had input (but I > was looking for it spelled with the "right" glyph, not the one I had > actually used which looked just the same) and just could not find it. There's any number of things to be done about that. 1. # -*- encoding: ascii -*- (I'd like to see you sneak those homoglyphic characters past *that*.) 2. pychecker and pylint - I'm sure you realise what they could do for you. 3. Use a font that doesn't have those characters or deliberately makes them distinct (that could help web browsing safety too). I'm not discounting the problem, I just dont believe it's a big one. Can we chose a codepoint subset that doesn't have these dupes? - Anders -- http://mail.python.org/mailman/listinfo/python-list
Re: PEP 3131: Supporting Non-ASCII Identifiers
Michael Torrie wrote: > > So given that people can already transliterate their language for use as > identifiers, I think avoiding non-ASCII character sets is a good idea. Transliteration makes people choose bad variable names, I see it all the time with Danish programmers. Say e.g. the most descriptive name for a process is "kør forlæns" (run forward). But "koer_forlaens" is ugly, so instead he'll write "run_fremad", combining an English word with a slightly less appropriate Danish word. Sprinkle in some English spelling errors and badly-chosen English words, and you have the sorry state of the art that is today. - Anders -- http://mail.python.org/mailman/listinfo/python-list
Re: PEP 3131: Supporting Non-ASCII Identifiers
Josiah Carlson wrote: > On the other hand, the introduction of some 60k+ valid unicode glyphs > into the set of characters that can be seen as a name in Python would > make any such attempts by anyone who is not a native speaker (and even > native speakers in the case of the more obscure Kanji glyphs) an > exercise in futility. > So you gather up a list of identifiers and and send out for translation. Having actual Kanji glyphs instead a mix of transliterations and bad English will only make that easier. That won't even cost you anything, since you were already having docstrings translated, along with comments and documentation, right? > But this issue isn't limited to different characters sharing glyphs! > It's also about being able to type names to use them in your own code > (generally very difficult if not impossible for many non-Latin > characters), or even be able to display them. For display, tell your editor the utf-8 source file is really latin-1. For entry, copy-paste. - Anders -- http://mail.python.org/mailman/listinfo/python-list
Re: merits of Lisp vs Python
Rob Thorpe wrote: > Anders J. Munch wrote: >> Let u(t) be the actual memory used by the program at time t. >> Let r(t) be the size of reachable memory at time t. >> >> Require that u(t) is a member of O(t -> max{t'<=t: r(t')}) >> >> There. That wasn't so hard, was it? > > That's quite a clever definition actually. > But, let's say I have a lisp machine. It has an unusual architecture, > it's made entirely of SRAM cells of ~9bits. Sometimes these cells are > used as storage, sometimes their contents represent logic circuits and > the routing between them is configured to form them into a processor. > Please tell me what reachable memory is ;). (The above processor is > not science fiction, it could easily be done with FPGAs) Reachable memory is the set of interpreter objects (conses, closures, scopes, atoms and what have you) reachable from from some appropriately defined root set. It can be unambiguously defined with respect to a virtual machine, with no regard to how actual implementations represent these things. For actual memory use, a simple byte count would do fine. If code and data are intermingled, just use the combined size of both of them. If you're worried about comparing incompatible units, don't be: apples and oranges compare just fine under big-Oh. - Anders -- http://mail.python.org/mailman/listinfo/python-list
Re: merits of Lisp vs Python
Rob Thorpe wrote: > Anders J. Munch wrote: >> Really? So how do you write a portable program in CL, that is to >> run for unbounded lengths of time? > > You can't. > > The thing about the spec not defining GC is almost a bit of humour. > No-one would use an implementation with no GC. > > The issue with specifying it is: How would you do it? The memory > used by a program is an aspect of the language implementation and > the system the program is running on, so how can it be defined in a > useful way? Let u(t) be the actual memory used by the program at time t. Let r(t) be the size of reachable memory at time t. Require that u(t) is a member of O(t -> max{t'<=t: r(t')}) There. That wasn't so hard, was it? - Anders -- http://mail.python.org/mailman/listinfo/python-list
Re: merits of Lisp vs Python
jayessay wrote: > Please note: GC is not part of CL's definition. It is likely not part > of any Lisp's definition (for reasons that should be obvious), and for > the same reasons likely not part of any language's definition. Really? So how do you write a portable program in CL, that is to run for unbounded lengths of time? - Anders -- http://mail.python.org/mailman/listinfo/python-list
Re: enumerate improvement proposal
Ben Finney wrote: > > >>> def obstinate_economist_enumerate(items): > ... enum_iter = iter((i+1, x) for (i, x) in enumerate(items)) > ... return enum_iter iter is redundant here. def natural_enumerate_improvement(items, start=0): return ((i+start, x) for (i, x) in enumerate(items)) - Anders -- http://mail.python.org/mailman/listinfo/python-list
Re: QuoteSQL
Lawrence D'Oliveiro wrote: >>> elif Ch == "'" or Ch == "\"" or Ch == "\\" : >>> Ch = "\\" + Ch >> Always sad to see an SQL DBMS willfully violate the SQL standard. > > Why is that a violation of SQL? Taking another look, I might be wrong: Your code uses double quotes, and since SQL uses single quotes for string literals, it just might be a compatible extension. Otherwise I would have taken note of the backslash escapes. E.g. '\\' is a two-character SQL string literal. - Anders -- http://mail.python.org/mailman/listinfo/python-list
Re: QuoteSQL
Robert Kern wrote: > Anders J. Munch wrote: > >> Always sad to see an SQL DBMS willfully violate the SQL standard. > > You must be a constantly depressed person, then. :-) Nah, I just look the other way most of the time *g* - Anders -- http://mail.python.org/mailman/listinfo/python-list
Relative import first impressions
Now 2.5 is out, and we have a syntax for explicit relative imports (PEP 328, http://www.python.org/dev/peps/pep-0328/, in case anyone wasn't paying attention). The long-term plan is that the classical import syntax becomes absolute import only, so that all imports are explicitly one or the other. You can only use relative import from within packages. Trying to import a top-level module relatively from within same directory, produces the exception "ValueError: Relative importpath too deep". There's a certain logic to that: You can just omit "from ." and do a regular absolute import. However, that spells bad news for modules that are both contained within packages, and executed from the top level as well. Accessing the same module both from within a package and outside it may seem like a bad idea, and in many ways, it is. You may get a double import of the same module with subtle, mysterious bugs to follow, when e.g. you suddenly have two copies of the "same" class, and isinstance(obj,mymodule.Cls) fails unexpectedly. But it's quite common all the same: The if __name__ == "__main__": idiom is often used, even within packages. But that is currently incompatible with using relative imports. It seems to me that unless we rethink the main idiom competely (which may not be a bad idea by the way, for the reasons given above), relative imports at the top level will need to be allowed. Another addition I'd like to see it the "import .foo" form. Currently only "from"-imports have a relative form. The argument against is that "import X" binds the name X, and it's not clear which name the relative import binds. I move that it's blindingly obvious: "import .foo" binds "foo", equivalent to "from . import foo". Did anyone really expect the name ".foo" to be bound? It's not a big deal though, as you only need to type "from ." once per module anyway. Using another improvement in 2.5, you can now write: from . import ( this, that, ) - Anders -- http://mail.python.org/mailman/listinfo/python-list
Re: QuoteSQL
Lawrence D'Oliveiro wrote: > Why doesn't MySQLdb provide a function like this: > > def QuoteSQL(Str, DoWild) : > """returns a MySQL string literal which evaluates to Str. Needed > for those times when MySQLdb's automatic quoting isn't good enough.""" Presumably because you're expected to use placeholders. When is that not good enough? > elif Ch == "'" or Ch == "\"" or Ch == "\\" : > Ch = "\\" + Ch Always sad to see an SQL DBMS willfully violate the SQL standard. - Anders -- http://mail.python.org/mailman/listinfo/python-list
Re: Newbie question on code vetting
[EMAIL PROTECTED] wrote: > As it is now, > one is pretty much left to rummage around on project web sites trying to get > a gut feel for what is going on. Asking the higher-ups at work to reach > technology management decisions based on my gut feel is an uphill climb. So what you need is a document that more or less formalises what you already know from rummaging around. The place for such a document would be the meta-PEP section at http://python.org/peps/. If the information you seek is in none of the existing meta-PEPs, that's probably because noone has yet felt the need for such a document bad enough to make the effort and write one. Until you came along, that is. So why don't you write a new PEP (or suggest changes to an existing PEP) with the information you need? You may not have all the answers, but if you have good questions that's a pretty good start. From an earlier post: > Is there any use of tools like BlackDuck ProtexIP or the > competing Palamida product to scan for matches to code that is already > licensed elsewhere? If you have access to such tools, why don't you just scan the CPython sources yourself? And make the results available to the community, of course. - Anders -- http://mail.python.org/mailman/listinfo/python-list
Re: Speed ain't bad
"John Machin" <[EMAIL PROTECTED]> wrote: > 1. Robustness: Both versions will "crash" (in the sense of an unhandled > 2. Efficiency: I don't see the disk I/O inefficiency in calling 3. Don't itemise perceived flaws in other people's postings. It may give off a hostile impression. > 1. Robustness: Both versions will "crash" (in the sense of an unhandled > exception) in the situation where zfdir exists but is not a directory. > The revised version just crashes later than the OP's version :-( > Trapping EnvironmentError seems not very useful -- the result will not > distinguish (on Windows 2000 at least) between the 'existing dir' and > 'existing non-directory' cases. Good point; my version has room for improvement. But at least it fixes the race condition between isdir and makedirs. What I like about EnvironmentError is that it it's easier to use than figuring out which one of IOError or OSError applies (and whether that can be relied on, cross-platform). > 2. Efficiency: I don't see the disk I/O inefficiency in calling > os.path.isdir() before os.makedirs() -- if the relevant part of the > filesystem wasn't already in memory, the isdir() call would make it > so, and makedirs() would get a free ride, yes/no? Perhaps. Looking stuff up in operating system tables and buffers takes time too. And then there's network latency; how much local caching do you get for an NFS mount or SMB share? If you really want to know, measure. - Anders -- http://mail.python.org/mailman/listinfo/python-list
Re: Speed ain't bad
"Bulba!" <[EMAIL PROTECTED]> wrote: > > One of the posters inspired me to do profiling on my newbie script > (pasted below). After measurements I have found that the speed > of Python, at least in the area where my script works, is surprisingly > high. Pretty good code for someone who calls himself a newbie. One line that puzzles me: > sfile=open(sfpath,'rb') You never use sfile again. In any case, you should explicitly close all files that you open. Even if there's an exception: sfile = open(sfpath, 'rb') try: finally: sfile.close() > > The only thing I'm missing in this picture is knowledge if my script > could be further optimised (not that I actually need better > performance, I'm just curious what possible solutions could be). > > Any takers among the experienced guys? Basically the way to optimise these things is to cut down on anything that does I/O: Use as few calls to os.path.is{dir,file}, os.stat, open and such that you can get away with. One way to do that is caching; e.g. storing names of known directories in a set (sets.Set()) and checking that set before calling os.path.isdir. I haven't spotted any obvious opportunities for that in your script, though. Another way is the strategy of "it's easier to ask forgiveness than to ask permission". If you replace: if(not os.path.isdir(zfdir)): os.makedirs(zfdir) with: try: os.makedirs(zfdir) except EnvironmentError: pass then not only will your script become a micron more robust, but assuming zfdir typically does not exist, you will have saved the call to os.path.isdir. - Anders -- http://mail.python.org/mailman/listinfo/python-list