Re: Some syntactic sugar proposals
On 12/02/2010 10:39 AM, Mark Dickinson wrote: On Nov 15, 12:46 pm, Tim Chase wrote: On 11/15/2010 12:39 AM, Dmitry Groshev wrote: x in range optimisation I've often thought this would make a nice O(1)-test lookup on an xrange() generator. An O(1) test for 'x in' is implemented in Python 3.2, at least provided that x has type 'int', 'long' or 'bool'. (If x is an instance of a subclass of int or long, then there's a risk that the semantics of the membership test have been changed by an explicitly overridden __eq__, so Python wimps out and falls back to the O(n) algorithm in that case.) Drat, bested again by the python time-machine. Thanks for bringing that to my attention. -tkc -- http://mail.python.org/mailman/listinfo/python-list
Re: Some syntactic sugar proposals
On Nov 15, 12:46 pm, Tim Chase wrote: > On 11/15/2010 12:39 AM, Dmitry Groshev wrote: > > > x in range optimisation > > I've often thought this would make a nice O(1)-test lookup on an > xrange() generator. An O(1) test for 'x in ' is implemented in Python 3.2, at least provided that x has type 'int', 'long' or 'bool'. (If x is an instance of a subclass of int or long, then there's a risk that the semantics of the membership test have been changed by an explicitly overridden __eq__, so Python wimps out and falls back to the O(n) algorithm in that case.) Python 3.2a4+ (py3k:86635:86636M, Nov 21 2010, 19:22:18) [GCC 4.2.1 (Apple Inc. build 5664)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> -1 in range(10**9) False >>> 5 in range(0, 10**100, 2) False >>> 10**99 in range(0, 10**100, 2) True IIRC, there wasn't sufficient interest to get it backported to Python 2.7 in time for its release. Though as a pure optimization, one could argue that it would still be possible to get this into Python 2.7.2. Mark -- http://mail.python.org/mailman/listinfo/python-list
Re: Some syntactic sugar proposals
On Wed, 01 Dec 2010 15:18:32 -0800, Dmitry Groshev wrote: > Here is a fresh example of what I meant by my first proposal. You need > to build a matrix like this: > 2 1 0 ... > 1 2 1 ... > 0 1 2 ... > ... > ... 1 2 1 > ... 0 1 2 > You could do this by one-liner: > [[(2 - abs(x - y)) if it > 0 else 0 for x in xrange(8)] for y in > xrange(8)] > ...but in reality you should write something like this: [[(lambda t: t > if t > 0 else 0)(2 - abs(x - y)) for x in xrange(8)] for y in xrange(8)] > or this > [[(2 - abs(x - y)) if (2 - abs(x - y)) > 0 else 0 for x in xrange(8)] > for y in xrange(8)] > or even this > def foo(x, y): > if abs(x - y) == 0: > return 2 > elif abs(x - y) == 1: > return 1 > else: > return 0 > [[foo(x, y) for x in xrange(8)] for y in xrange(8)] All those one-liners give me a headache. At least your "foo" solution is understandable. But I'd do it like this: >>> array = [[0]*8 for _ in range(8)] >>> for i in range(8): ... array[i][i] = 2 ... if i > 0: array[i][i-1] = 1 ... if i < 7: array[i][i+1] = 1 ... >>> pprint.pprint(array) [[2, 1, 0, 0, 0, 0, 0, 0], [1, 2, 1, 0, 0, 0, 0, 0], [0, 1, 2, 1, 0, 0, 0, 0], [0, 0, 1, 2, 1, 0, 0, 0], [0, 0, 0, 1, 2, 1, 0, 0], [0, 0, 0, 0, 1, 2, 1, 0], [0, 0, 0, 0, 0, 1, 2, 1], [0, 0, 0, 0, 0, 0, 1, 2]] When you stop trying to make everything a one-liner, it's amazing how readable you can make code :) -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: Some syntactic sugar proposals
On Nov 22, 2:21 pm, Andreas Löscher wrote: > > if x in range(a, b): #wrong! > > it feels so natural to check it that way, but we have to write > > if a <= x <= b > > I understand that it's not a big deal, but it would be awesome to have > > some optimisations - it's clearly possible to detect things like that > > "wrong" one and fix it in a bytecode. > > You can implement it yourself: > > class between(object): > def __init__(self, a,b): > super(crang, self).__init__() > self.a=a > self.b=b > def __contains__(self, value): > return self.a <= value <= self.b > > >>> 12.45 in between(-100,100) > > true > > But do you need > > a < x < b > a <= x < b > a <= x <= b or > a < x <= b ? > > Sure, you could set a new parameter for this, but the normal way is not > broken at all. > > Best Of course there are better ways to do this. Your "between", standart comparisons and so, but expressing this as "i in range(a, b)" is just intuitive and declarative. Here is a fresh example of what I meant by my first proposal. You need to build a matrix like this: 2 1 0 ... 1 2 1 ... 0 1 2 ... ... ... 1 2 1 ... 0 1 2 You could do this by one-liner: [[(2 - abs(x - y)) if it > 0 else 0 for x in xrange(8)] for y in xrange(8)] ...but in reality you should write something like this: [[(lambda t: t if t > 0 else 0)(2 - abs(x - y)) for x in xrange(8)] for y in xrange(8)] or this [[(2 - abs(x - y)) if (2 - abs(x - y)) > 0 else 0 for x in xrange(8)] for y in xrange(8)] or even this def foo(x, y): if abs(x - y) == 0: return 2 elif abs(x - y) == 1: return 1 else: return 0 [[foo(x, y) for x in xrange(8)] for y in xrange(8)] It's not THAT matter, but it's just about readability and shortness in some cases. -- http://mail.python.org/mailman/listinfo/python-list
Re: Some syntactic sugar proposals
> if x in range(a, b): #wrong! > it feels so natural to check it that way, but we have to write > if a <= x <= b > I understand that it's not a big deal, but it would be awesome to have > some optimisations - it's clearly possible to detect things like that > "wrong" one and fix it in a bytecode. You can implement it yourself: class between(object): def __init__(self, a,b): super(crang, self).__init__() self.a=a self.b=b def __contains__(self, value): return self.a <= value <= self.b >>> 12.45 in between(-100,100) true But do you need a < x < b a <= x < b a <= x <= b or a < x <= b ? Sure, you could set a new parameter for this, but the normal way is not broken at all. Best -- http://mail.python.org/mailman/listinfo/python-list
Re: Some syntactic sugar proposals
Steven D'Aprano writes: > >> Not everything needs to be a one liner. If you need this, do it the > >> old- fashioned way: > >> > >> t = foo() > >> if not pred(t): t = default_value > > > > I already explained how to write it as a one-liner: > > > > t = (lambda y: y if pred(y) else default_value)(foo()) > > I didn't say it couldn't be written as a one-liner. I suggested that it > was better not to. Ahh. I misunderstood the first sentence above as dismissing the possibility. Sorry. I agree that it's not a /nice/ one-liner. ;-) > The costs of the one-liner are: > > * reduced readability; > * requires an increased level of knowledge of the reader ("what's lambda > do?"); > * runtime inefficiency (you create a function object, only to use it once > then throw it away). This last can be obviated by a clever compiler (which, in our case, we have not got). The second could be considered an advantage: it's educational! > The advantages? > > * one fewer line of code. > > In my experience, the obsessiveness in which some people look for one- > liners is far from helpful, and goes against the spirit of Python. This > isn't Perl :) Oh, I agree completely. On the other hand, it's just /fun/. Python is a fun language and using its features in playfully unusual ways is enjoyable; like a good pun in a natural language. Just as puns aren't always appropriate in written language, playful code isn't always appropriate either; but that doesn't mean it's never appropriate. (Java has no sense of humour. C++ does have, but it's a bit weird.) -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Some syntactic sugar proposals
On Thu, 18 Nov 2010 09:32:23 +, Mark Wooding wrote: [...] > You're wrong. Python evaluates these left-to-right, as I said. > Parentheses override operator associativity; they don't affect > evaluation order at all. Fair enough. I concede your point. [...] >> Not everything needs to be a one liner. If you need this, do it the >> old- fashioned way: >> >> t = foo() >> if not pred(t): t = default_value > > I already explained how to write it as a one-liner: > > t = (lambda y: y if pred(y) else default_value)(foo()) I didn't say it couldn't be written as a one-liner. I suggested that it was better not to. The costs of the one-liner are: * reduced readability; * requires an increased level of knowledge of the reader ("what's lambda do?"); * runtime inefficiency (you create a function object, only to use it once then throw it away). The advantages? * one fewer line of code. In my experience, the obsessiveness in which some people look for one- liners is far from helpful, and goes against the spirit of Python. This isn't Perl :) -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: Some syntactic sugar proposals
Steven D'Aprano writes: > On Wed, 17 Nov 2010 16:31:40 +, Mark Wooding wrote: > > > But I don't think that's the big problem with this proposal. The real > > problem is that it completely changes the evaluation rule for the > > conditional expression. (The evaluation rule is already pretty screwy: > > Python is consistently left-to-right -- except here.) > > Not quite... > > >>> 1+2*3 > 7 > >>> (1+2)*3 > 9 You're wrong. Python evaluates these left-to-right, as I said. Parentheses override operator associativity; they don't affect evaluation order at all. Consider: def say(x): print 'seen %s' % x return x print say(1) + say(2) * say(3) print (say(1) + say(2)) * say(3) Run this program and you get seen 1 seen 2 seen 3 7 seen 1 seen 2 seen 3 9 So definitely left-to-right. Translating into reverse-Polish, say with Dijkstra's shunting-yard algorithm, is enlightening: you get 1 2 3 * + for the first and 1 2 + 3 * for the second. This preserves evaluation order; indeed, this is a general property of the shunting-yard algorithm. Finally, I quote from the language reference (5.13 of the 2.5 version), just to show that (this time, at least) I'm not trying to impose unfamiliar terminology, and that Python is defined to behave like this and I'm not relying on implementation-specific details. Alas, it also highlights a genuine inconsistency, but one which might be considered tolerable. : 5.13 Evaluation order : = : : Python evaluates expressions from left to right. Notice that while : evaluating an assignment, the right-hand side is evaluated before the : left-hand side. : : In the following lines, expressions will be evaluated in the : arithmetic order of their suffixes: : : expr1, expr2, expr3, expr4 : (expr1, expr2, expr3, expr4) : {expr1: expr2, expr3: expr4} : expr1 + expr2 * (expr3 - expr4) : func(expr1, expr2, *expr3, **expr4) : expr3, expr4 = expr1, expr2 So the above example is /explicitly/ dealt with in the language reference, if only you'd cared to look. > Not everything needs to be a one liner. If you need this, do it the old- > fashioned way: > > t = foo() > if not pred(t): t = default_value I already explained how to write it as a one-liner: t = (lambda y: y if pred(y) else default_value)(foo()) -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Some syntactic sugar proposals
On Wed, 17 Nov 2010 16:31:40 +, Mark Wooding wrote: > But I don't think that's the big problem with this proposal. The real > problem is that it completely changes the evaluation rule for the > conditional expression. (The evaluation rule is already pretty screwy: > Python is consistently left-to-right -- except here.) Not quite... >>> 1+2*3 7 >>> (1+2)*3 9 But other than that, I agree with your analysis for why Python should not be changed to allow: t = foo() as v if pred(v) else default_value Not everything needs to be a one liner. If you need this, do it the old- fashioned way: t = foo() if not pred(t): t = default_value -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: Some syntactic sugar proposals
Christopher writes: > i don't like magic names. what about: > > t = foo() as v if pred(v) else default_value This is an improvement on `it'; anaphorics are useful in their place, but they don't seem to fit well with Python. But I don't think that's the big problem with this proposal. The real problem is that it completely changes the evaluation rule for the conditional expression. (The evaluation rule is already pretty screwy: Python is consistently left-to-right -- except here.) Evaluating a conditional expression starts in the middle, by evaluating the condition. If the condition is true, then it evaluates the consequent (to the left); otherwise it evaluates the alternative (to the right). Screwy, but tolerable. The proposal is to evaluate the /consequent/, stash it somewhere, evaluate the condition, and then either output the consequent which we evaluated earlier or the alternative which we must evaluate now. Of course, the implementation must be able to tell which of these evaluation rules to apply. The marker to look for is either `it' (original anaphoric proposal -- this is the real reason why `it' should be a reserved word: its presence radically alters the evaluation rule, so it ought to be a clear syntactic marker) or `as' (as suggested above). Elsewhere in the language, `as' is pretty consistent in what it does: it provides a name for a thing described elsewhere (a `with' context object, or an imported thing) -- but nothing else. It certainly doesn't suggest a change in the way anything else is evaluated. 1/x if x != 0 else None works for any numeric x; it'd be really surprising to me if 1/x as hunoz if x != 0 else None didn't. -1 on this one. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Some syntactic sugar proposals
On Wed, 17 Nov 2010 10:18:51 -0500 Mel wrote: > Christopher wrote: > > >> ? Of course we can write it as > >> t = foo() if pred(foo()) else default_value > >> but here we have 2 foo() calls instead of one. Why can't we write > >> just something like this: > >> t = foo() if pred(it) else default_value > >> where "it" means "foo() value"? > > > > i don't like magic names. what about: > > > > t = foo() as v if pred(v) else default_value > > !! so: assignment inside an expression. > I like the idea of having an "as ... if" construct, though. :) /W -- To reach me via email, replace INVALID with the country code of my home country. But if you spam me, I'll be one sour Kraut. -- http://mail.python.org/mailman/listinfo/python-list
Re: Some syntactic sugar proposals
Christopher wrote: >> ? Of course we can write it as >> t = foo() if pred(foo()) else default_value >> but here we have 2 foo() calls instead of one. Why can't we write just >> something like this: >> t = foo() if pred(it) else default_value >> where "it" means "foo() value"? > > i don't like magic names. what about: > > t = foo() as v if pred(v) else default_value !! so: assignment inside an expression. Mel. -- http://mail.python.org/mailman/listinfo/python-list
Re: Some syntactic sugar proposals
> ? Of course we can write it as > t = foo() if pred(foo()) else default_value > but here we have 2 foo() calls instead of one. Why can't we write just > something like this: > t = foo() if pred(it) else default_value > where "it" means "foo() value"? i don't like magic names. what about: t = foo() as v if pred(v) else default_value -- http://mail.python.org/mailman/listinfo/python-list
Re: Some syntactic sugar proposals
On Nov 14, 11:30 pm, alex23 wrote: > On Nov 15, 4:39 pm, Dmitry Groshev wrote: > > > if x in range(a, b): #wrong! > > Only in Python 3.x, it's perfectly valid in Python 2.x. To achieve the > same in Python 3.x, try: > > if x in list(range(a, b,)): # BUT SEE MY COMMENT BELOW > > > it feels so natural to check it that way, but we have to write > > if a <= x <= b > > I understand that it's not a big deal, but it would be awesome to have > > some optimisations - it's clearly possible to detect things like that > > "wrong" one and fix it in a bytecode. > > This seems more like a pessimisation to me: your range version > constructs a list just to do a single container check. That's a _lot_ > more cumbersome than two simple comparisons chained together. Also: testing for the membership of x in a set is NOT the same thing as testing using inequality operators. The inequality operators will return True for any FLOATING-POINT value within the range (a...b), but the set test will only return True for set members. -- http://mail.python.org/mailman/listinfo/python-list
Re: Some syntactic sugar proposals
On Nov 15, 2:39 am, Dmitry Groshev wrote: > Here are some proposals. They are quite useful at my opinion and I'm > interested for suggestions. It's all about some common patterns. > First of all: how many times do you write something like > t = foo() > t = t if pred(t) else default_value Never! [snip] > And the third. The more I use python the more I see how "natural" it > can be. By "natural" I mean the statements like this: > [x.strip() for x in reversed(foo)] > which looks almost like a natural language. But there is some > pitfalls: > if x in range(a, b): #wrong! This is true only if x is an integer such that a <= x < b > it feels so natural to check it that way, but we have to write > if a <= x <= b This is true if x is an integer OR a float. Two very different cases, deserving of different notation. André -- http://mail.python.org/mailman/listinfo/python-list
Re: Some syntactic sugar proposals
On 11/16/2010 3:42 AM, Steven D'Aprano wrote: On Mon, 15 Nov 2010 22:40:00 -0700, Ian Kelly wrote: On 11/15/2010 10:26 PM, Steven D'Aprano wrote: t = foo()+bar()+baz() if pred(it) else baz()-foo()-bar() What does "it" mean here? "it" would mean the result of the expression foo()+bar()+baz(). What else could it mean? It could mean the last expression, baz(). Or the entire compound expression, foo()+bar()+baz(). Unless the precedence rules were to change, the three expressions in the example that are operated on by the ternary are these: 1. foo()+bar()+baz() 2. pred(it) 3. baz()-foo()-bar() So the antecedent would have to be one of those in order to make any sense at all, and obviously the only choice of those that would be useful is the first one. There are valid objections to the proposal, but the intended semantics seem perfectly clear. Fair point, my example was terrible and didn't show the point that was clear in my head. Mea culpa. How about this instead? t = foo()+it if pred(it) else bar() Should that be a SyntaxError, or is `it` a variable that holds its value from statement to statement? SyntaxError. Implementing this without making 'it' a keyword would be very sloppy, IMO. Another option would be to use a special variable named '__', similar to the variable '_' that the REPL uses to store the result of the last command. This might break some existing code, but probably not very much. Mostly it would just be confusing. t = (foo() if pred(it) else bar()) if cond(it) else baz() More problematic: t = foo() if pred(bar() if pred2(it) else str(it)) else bar() Does the first 'it' belong to the inner or outer ternary? Probably the inner one. What about the second 'it'? BTW, I frequently use "it" for iterators, and making "it" a reserved word would break a lot of my code. This would make me quite peeved. I do the same, and yes, it would make upgrading a real pain. Cheers, Ian -- http://mail.python.org/mailman/listinfo/python-list
Re: Some syntactic sugar proposals
On Mon, 15 Nov 2010 22:40:00 -0700, Ian Kelly wrote: > On 11/15/2010 10:26 PM, Steven D'Aprano wrote: >> t = foo()+bar()+baz() if pred(it) else baz()-foo()-bar() >> >> What does "it" mean here? > > "it" would mean the result of the expression foo()+bar()+baz(). What > else could it mean? It could mean the last expression, baz(). Or the entire compound expression, foo()+bar()+baz(). > There are valid objections to the proposal, but the > intended semantics seem perfectly clear. Fair point, my example was terrible and didn't show the point that was clear in my head. Mea culpa. How about this instead? t = foo()+it if pred(it) else bar() Should that be a SyntaxError, or is `it` a variable that holds its value from statement to statement? t = it t = (foo() if pred(it) else bar()) if cond(it) else baz() For what it's worth, Apple's defunct Hypertalk language had a couple of syntax elements very much like that. Hypertalk had a special variable, "it", which you used like this: get the number of cards put it into field "Card number" I trust I don't have to explain this? :) Hypertalk also had a special function, "the result", which worked something like this: ask "This is a dialog box. Please type your answer here:" put the result into field "Your answer" (or you could use "result()" instead). Both of these worked quite well with Hypertalk, particularly with it's focus on non-programmers, but they were designed into the language from the beginning. In Python they would be the proverbial round peg in a square hole. BTW, I frequently use "it" for iterators, and making "it" a reserved word would break a lot of my code. This would make me quite peeved. -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: Some syntactic sugar proposals
On 11/15/2010 10:26 PM, Steven D'Aprano wrote: t = foo()+bar()+baz() if pred(it) else baz()-foo()-bar() What does "it" mean here? "it" would mean the result of the expression foo()+bar()+baz(). What else could it mean? There are valid objections to the proposal, but the intended semantics seem perfectly clear. Cheers, Ian -- http://mail.python.org/mailman/listinfo/python-list
Re: Some syntactic sugar proposals
On Sun, 14 Nov 2010 22:39:05 -0800, Dmitry Groshev wrote: > Here are some proposals. They are quite useful at my opinion and I'm > interested for suggestions. It's all about some common patterns. First > of all: how many times do you write something like > t = foo() > t = t if pred(t) else default_value > ? Hardly ever. Not often enough to need special syntax for it. Of course we can write it as > t = foo() if pred(foo()) else default_value > but here we have 2 foo() calls instead of one. Why can't we write just > something like this: > t = foo() if pred(it) else default_value > where "it" means "foo() value"? t = foo()+bar()+baz() if pred(it) else baz()-foo()-bar() What does "it" mean here? > Second, I saw a lot of questions about using dot notation for a > "object-like" dictionaries and a lot of solutions like this: > class dotdict(dict): > def __getattr__(self, attr): > return self.get(attr, None) > __setattr__= dict.__setitem__ > __delattr__= dict.__delitem__ > why there isn't something like this in a standart library? Because dot notation for dictionaries is not something we should encourage. > And the > third. The more I use python the more I see how "natural" it can be. By > "natural" I mean the statements like this: > [x.strip() for x in reversed(foo)] > which looks almost like a natural language. But there is some pitfalls: > if x in range(a, b): #wrong! Why do you say it's wrong? It's perfectly correct: 1 in range(1, 10) => returns True 1.5 in range(1, 10) => returns False 5 in range(1, 10) => returns True 10 in range(1, 10) => returns False exactly as I expect for element testing in a half-open interval. So where's the problem? If you want interval testing, you need to perform an interval test, not an element test. > it feels so natural to check it that way, but we have to write > if a <= x <= b > I understand that it's not a big deal, but it would be awesome to have > some optimisations - it's clearly possible to detect things like that > "wrong" one and fix it in a bytecode. If I write: x in range(1, 10) how do you expect the compiler to read my mind and know if I want the half-open interval or the closed interval? -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: Some syntactic sugar proposals
On 11/14/2010 11:30 PM, alex23 wrote: On Nov 15, 4:39 pm, Dmitry Groshev wrote: First of all: how many times do you write something like Second, I saw a lot of questions about using dot notation for a "object-like" dictionaries and a lot of solutions like this: class dotdict(dict): def __getattr__(self, attr): return self.get(attr, None) __setattr__= dict.__setitem__ __delattr__= dict.__delitem__ why there isn't something like this in a standart library? Personally, I like keeping object attribute references separate from dictionary item references. Right. This isn't JavaScript. If you need a "dict", use a "dict". Don't use attributes as named storage. It leads to problems. Functions and various built-in objects are in the attribute namespace, and this can lead to name clashes. Maybe security holes, if the attribute keys come from external input. There are also some restrictions on the syntax of attribute names, restrictions "dict" does not have. Remember, you can inherit from "dict", which allows you to write obj['abc'] which is almost as short as obj.abc but safer. John Nagle -- http://mail.python.org/mailman/listinfo/python-list
Re: Some syntactic sugar proposals
On Nov 15, 2010, at 1:39 AM, Dmitry Groshev wrote: >if x in range(a, b): #wrong! > it feels so natural to check it that way, but we have to write >if a <= x <= b > I understand that it's not a big deal, but it would be awesome to have > some optimisations - it's clearly possible to detect things like that > "wrong" one and fix it in a bytecode. I don't think anyone has pointed this out, but these are *not* the same thing. observe: x=3 if x in range(1,10): print "yay!" if 1<=x<10: print "yay too!" x=3.2 if x in range(1,10): print "yay!" if 1<=x<10: print "yay too!" output: yay! yay too! yay too! bb -- Brian Blais bbl...@bryant.edu http://web.bryant.edu/~bblais http://bblais.blogspot.com/ -- http://mail.python.org/mailman/listinfo/python-list
Re: Some syntactic sugar proposals
On 11/15/2010 1:39 AM, Dmitry Groshev wrote: Here are some proposals. They are quite useful at my opinion and I'm interested for suggestions. It's all about some common patterns. First of all: how many times do you write something like t = foo() t = t if pred(t) else default_value Never. t=t unbinds and rebinds 't' to the same object. A waste. Only rebind if needed. if not pred(t): t = default_value ? Of course we can write it as t = foo() if pred(foo()) else default_value but here we have 2 foo() calls instead of one. Why can't we write just something like this: t = foo() if pred(it) else default_value where "it" means "foo() value"? Too magical. I agree with most other comments. -- Terry Jan Reedy -- http://mail.python.org/mailman/listinfo/python-list
Re: Some syntactic sugar proposals
On 11/15/2010 12:39 AM, Dmitry Groshev wrote: x in range optimisation I've often thought this would make a nice O(1)-test lookup on an xrange() generator. I don't have strong use-cases for it, but a bit of well-tested code in the standard library would save me from doing the math (along with its potential fenceposting and sign errors) the couple times I've reached for it. Using the x in list(xrange(...)) # or "range()" depending your version ends up with an O(n) lookup, though I suppose one could create a set() for O(1) lookups, but that still requires O(N) storage (where a mathematical lookup would involve O(1) storage *and* time) foo() if foo() else bar() This is usually indicative that you need to cache the object...something like etcc = expensive_to_calculate_constructor() result = foo(etcc) if test(etcc) else bar() That way, you cache the potentially-expensive calculation, indicate to other readers-of-your-code that it's potentially-expensive, and enforce the use of that cache to ensure that you don't duplicate the expensive op. -tkc -- http://mail.python.org/mailman/listinfo/python-list
Re: Some syntactic sugar proposals
Dmitry Groshev writes: > First of all: how many times do you write something like > t = foo() > t = t if pred(t) else default_value > ? Of course we can write it as > t = foo() if pred(foo()) else default_value > but here we have 2 foo() calls instead of one. Why can't we write just > something like this: > t = foo() if pred(it) else default_value > where "it" means "foo() value"? How about t = (lambda y: y if pred(y) else default_value)(foo(x)) You could even package the lambda into a named function if you get bored of typing or your aesthetic senses are offended. > And the third. The more I use python the more I see how "natural" it > can be. By "natural" I mean the statements like this: > [x.strip() for x in reversed(foo)] > which looks almost like a natural language. But there is some > pitfalls: > if x in range(a, b): #wrong! > it feels so natural to check it that way, but we have to write > if a <= x <= b This, I think, is your error. The test `x in range(a, b)' means the same as `a <= x < b' (only in Python 2 it builds a list and then throws it away again). Such half-open intervals turn out to be what you want most of the time, and I think you'll avoid many bugs if you embrace them rather than trying to cling to the fully-closed intervals above. Python very definitely made the right decision to use half-open intervals pervasively, e.g., for `rangeand 'in sequence slicing. It's a bad idea to fight against it. Advantages of half-open intervals [a, b): * The number of elements is exactly b - a; closed intervals contain an extra element which is often forgotten. * They compose and split nicely: if a <= c <= b then [a, b) is exactly the disjoint union of [a, c) and [c, b). * Sums over these intervals are often better behaved; indeed, there's a rather pretty analogy between sums on half-open intervals and definite integrals which is lost if you use closed intervals. (The above two observations are special cases of this one.) See Concrete Mathematics (Graham, Knuth, Patashnik) for more on this. * It's easy to express an empty interval. You can't do that if you work entirely with closed intervals, but empty sets are an important boundary case and it's annoying to have to handle them separately. -- [mdw] -- http://mail.python.org/mailman/listinfo/python-list
Re: Some syntactic sugar proposals
Dmitry Groshev writes: > which looks almost like a natural language. But there is some > pitfalls: > if x in range(a, b): #wrong! > it feels so natural to check it that way, but we have to write > if a <= x <= b For the record, you have to write: if a <= x < b: Ranges are open on the ending side. -- http://mail.python.org/mailman/listinfo/python-list
Re: Some syntactic sugar proposals
On Nov 15, 12:03 pm, alex23 wrote: > On Nov 15, 5:50 pm, Dmitry Groshev wrote: > > > On Nov 15, 10:30 am, alex23 wrote: > > > Personally, I like keeping object attribute references separate from > > > dictionary item references. > > > Your Python doesn't - dot notation is just a sugar for __dict__ lookup > > with default metaclass. > > That's a gross oversimplification that tends towards wrong: > > >>> class C(object): > > ... def __init__(self): > ... self._x = None > ... @property > ... def x(self): return self._x > ... @x.setter > ... def x(self, val): self._x = val > ...>>> c = C() > >>> c.x = 1 > >>> c.x > 1 > >>> c.__dict__['x'] > > Traceback (most recent call last): > File "", line 1, in > KeyError: 'x' > > But my concern has _nothing_ to do with the implementation detail of > how objects hold attributes, it's solely over the clarity that comes > from being able to visually tell that something is an object vs a > dictionary. Oh, now I understand you. But this "dotdict" (or "bunch") things don't break anything. You still need to use it explicitly and it is very useful if you need to serialize some JSON data about some entities. s = """[{"name": "Jhon Doe", "age": "12"}, {"name": "Alice", "age": "23"}]""" t = map(dotdict, json.loads(s)) t[0] #{'age': '12', 'name': 'Jhon Doe'} t[0].age #'12' Of course you can do this with namedtuple, but in fact this isn't a tuple at all. It's a list of entities. > > > This seems more like a pessimisation to me: your range version > > > constructs a list just to do a single container check. That's a _lot_ > > > more cumbersome than two simple comparisons chained together. > > > By "wrong" I meant exactly this. I told about "compiler" optimisation > > of statements like this so it would not construct a list. > > So you want this: > > if x in range(1,10): > > ...to effectively emit the same bytecode as a chained comparison while > this: > > for x in range(1,10): > > ...produces a list/generator? > > Never going to happen. "Special cases aren't special enough to break > the rules." The standard form for chained comparisons can handle far > more complex expressions which your 'in' version could not: 0 <= min > <= max <= 100 I know about chained comparisons, thanks. It's not about them. It's about bytecode optimisation. But maybe you are right about "Special cases aren't special enough to break the rules". I kinda forgot that :) -- http://mail.python.org/mailman/listinfo/python-list
Re: Some syntactic sugar proposals
On Nov 15, 5:50 pm, Dmitry Groshev wrote: > On Nov 15, 10:30 am, alex23 wrote: > > Personally, I like keeping object attribute references separate from > > dictionary item references. > > Your Python doesn't - dot notation is just a sugar for __dict__ lookup > with default metaclass. That's a gross oversimplification that tends towards wrong: >>> class C(object): ... def __init__(self): ... self._x = None ... @property ... def x(self): return self._x ... @x.setter ... def x(self, val): self._x = val ... >>> c = C() >>> c.x = 1 >>> c.x 1 >>> c.__dict__['x'] Traceback (most recent call last): File "", line 1, in KeyError: 'x' But my concern has _nothing_ to do with the implementation detail of how objects hold attributes, it's solely over the clarity that comes from being able to visually tell that something is an object vs a dictionary. > > This seems more like a pessimisation to me: your range version > > constructs a list just to do a single container check. That's a _lot_ > > more cumbersome than two simple comparisons chained together. > > By "wrong" I meant exactly this. I told about "compiler" optimisation > of statements like this so it would not construct a list. So you want this: if x in range(1,10): ...to effectively emit the same bytecode as a chained comparison while this: for x in range(1,10): ...produces a list/generator? Never going to happen. "Special cases aren't special enough to break the rules." The standard form for chained comparisons can handle far more complex expressions which your 'in' version could not: 0 <= min <= max <= 100 -- http://mail.python.org/mailman/listinfo/python-list
Re: Some syntactic sugar proposals
On Nov 15, 10:30 am, alex23 wrote: > On Nov 15, 4:39 pm, Dmitry Groshev wrote: > > > First of all: how many times do you write something like > > t = foo() > > t = t if pred(t) else default_value > > ? Of course we can write it as > > t = foo() if pred(foo()) else default_value > > but here we have 2 foo() calls instead of one. Why can't we write just > > something like this: > > t = foo() if pred(it) else default_value > > where "it" means "foo() value"? > > Could you provide an actual use case for this. This seems weird to me: > you're creating an object, testing the object, then possibly throwing > it away and using a default instead. Are you sure you can't > restructure your code as such: > > t = foo(x) if else default Sure. Let's pretend you have some string foo and compiled regular expression bar. Naive code: t = bar.findall(foo) if len(t) < 3: t = [] Code with proposed syntactic sugar: t = bar.findall(foo) if len(it) > 2 else [] > > Second, I saw a lot of questions about using dot notation for a > > "object-like" dictionaries and a lot of solutions like this: > > class dotdict(dict): > > def __getattr__(self, attr): > > return self.get(attr, None) > > __setattr__= dict.__setitem__ > > __delattr__= dict.__delitem__ > > why there isn't something like this in a standart library? > > Personally, I like keeping object attribute references separate from > dictionary item references. Your Python doesn't - dot notation is just a sugar for __dict__ lookup with default metaclass. > This seems more like a pessimisation to me: your range version > constructs a list just to do a single container check. That's a _lot_ > more cumbersome than two simple comparisons chained together. By "wrong" I meant exactly this. I told about "compiler" optimisation of statements like this so it would not construct a list. -- http://mail.python.org/mailman/listinfo/python-list
Re: Some syntactic sugar proposals
On Nov 15, 5:30 pm, alex23 wrote: > t = foo(x) if else default This should read 'test' instead of 'text', sorry. -- http://mail.python.org/mailman/listinfo/python-list
Re: Some syntactic sugar proposals
On Nov 15, 4:39 pm, Dmitry Groshev wrote: > First of all: how many times do you write something like > t = foo() > t = t if pred(t) else default_value > ? Of course we can write it as > t = foo() if pred(foo()) else default_value > but here we have 2 foo() calls instead of one. Why can't we write just > something like this: > t = foo() if pred(it) else default_value > where "it" means "foo() value"? Could you provide an actual use case for this. This seems weird to me: you're creating an object, testing the object, then possibly throwing it away and using a default instead. Are you sure you can't restructure your code as such: t = foo(x) if else default > Second, I saw a lot of questions about using dot notation for a > "object-like" dictionaries and a lot of solutions like this: > class dotdict(dict): > def __getattr__(self, attr): > return self.get(attr, None) > __setattr__= dict.__setitem__ > __delattr__= dict.__delitem__ > why there isn't something like this in a standart library? Personally, I like keeping object attribute references separate from dictionary item references. If you're someone who doesn't mind muddying that distinction, then - as you've discovered - it's a simple addition to your own code. > if x in range(a, b): #wrong! Only in Python 3.x, it's perfectly valid in Python 2.x. To achieve the same in Python 3.x, try: if x in list(range(a, b,)): # BUT SEE MY COMMENT BELOW > it feels so natural to check it that way, but we have to write > if a <= x <= b > I understand that it's not a big deal, but it would be awesome to have > some optimisations - it's clearly possible to detect things like that > "wrong" one and fix it in a bytecode. This seems more like a pessimisation to me: your range version constructs a list just to do a single container check. That's a _lot_ more cumbersome than two simple comparisons chained together. -- http://mail.python.org/mailman/listinfo/python-list
Re: Some syntactic sugar proposals
On Nov 15, 9:48 am, Chris Rebert wrote: > On Sun, Nov 14, 2010 at 10:39 PM, Dmitry Groshev > wrote: > > Here are some proposals. They are quite useful at my opinion and I'm > > interested for suggestions. It's all about some common patterns. > > > Second, I saw a lot of questions about using dot notation for a > > "object-like" dictionaries and a lot of solutions like this: > > class dotdict(dict): > > def __getattr__(self, attr): > > return self.get(attr, None) > > __setattr__= dict.__setitem__ > > __delattr__= dict.__delitem__ > > why there isn't something like this in a standart library? > > There > is:http://docs.python.org/library/collections.html#collections.namedtuple > > The "bunch" recipe is also fairly well-known; I suppose one could > argue whether it's > std-lib-worthy:http://code.activestate.com/recipes/52308-the-simple-but-handy-collec... > > Cheers, > Chris namedtuple is not a "drop-in" replacement like this "dotdict" thing - you first need to create a new namedtuple instance. As for me it's a bit too complicated. -- http://mail.python.org/mailman/listinfo/python-list
Re: Some syntactic sugar proposals
On Sun, Nov 14, 2010 at 10:39 PM, Dmitry Groshev wrote: > Here are some proposals. They are quite useful at my opinion and I'm > interested for suggestions. It's all about some common patterns. > Second, I saw a lot of questions about using dot notation for a > "object-like" dictionaries and a lot of solutions like this: > class dotdict(dict): > def __getattr__(self, attr): > return self.get(attr, None) > __setattr__= dict.__setitem__ > __delattr__= dict.__delitem__ > why there isn't something like this in a standart library? There is: http://docs.python.org/library/collections.html#collections.namedtuple The "bunch" recipe is also fairly well-known; I suppose one could argue whether it's std-lib-worthy: http://code.activestate.com/recipes/52308-the-simple-but-handy-collector-of-a-bunch-of-named/ Cheers, Chris -- http://mail.python.org/mailman/listinfo/python-list
Re: Some syntactic sugar proposals
On Nov 15, 9:39 am, Dmitry Groshev wrote: > Here are some proposals. They are quite useful at my opinion and I'm > interested for suggestions. It's all about some common patterns. > First of all: how many times do you write something like > t = foo() > t = t if pred(t) else default_value > ? Of course we can write it as > t = foo() if pred(foo()) else default_value > but here we have 2 foo() calls instead of one. Why can't we write just > something like this: > t = foo() if pred(it) else default_value > where "it" means "foo() value"? > Second, I saw a lot of questions about using dot notation for a > "object-like" dictionaries and a lot of solutions like this: > class dotdict(dict): > def __getattr__(self, attr): > return self.get(attr, None) > __setattr__= dict.__setitem__ > __delattr__= dict.__delitem__ > why there isn't something like this in a standart library? > And the third. The more I use python the more I see how "natural" it > can be. By "natural" I mean the statements like this: > [x.strip() for x in reversed(foo)] > which looks almost like a natural language. But there is some > pitfalls: > if x in range(a, b): #wrong! > it feels so natural to check it that way, but we have to write > if a <= x <= b > I understand that it's not a big deal, but it would be awesome to have > some optimisations - it's clearly possible to detect things like that > "wrong" one and fix it in a bytecode. > > x in range optimisation > dot dict access > foo() if foo() else bar() Oh, I'm sorry. I forgot to delete my little notes at the bottom of message. -- http://mail.python.org/mailman/listinfo/python-list
Some syntactic sugar proposals
Here are some proposals. They are quite useful at my opinion and I'm interested for suggestions. It's all about some common patterns. First of all: how many times do you write something like t = foo() t = t if pred(t) else default_value ? Of course we can write it as t = foo() if pred(foo()) else default_value but here we have 2 foo() calls instead of one. Why can't we write just something like this: t = foo() if pred(it) else default_value where "it" means "foo() value"? Second, I saw a lot of questions about using dot notation for a "object-like" dictionaries and a lot of solutions like this: class dotdict(dict): def __getattr__(self, attr): return self.get(attr, None) __setattr__= dict.__setitem__ __delattr__= dict.__delitem__ why there isn't something like this in a standart library? And the third. The more I use python the more I see how "natural" it can be. By "natural" I mean the statements like this: [x.strip() for x in reversed(foo)] which looks almost like a natural language. But there is some pitfalls: if x in range(a, b): #wrong! it feels so natural to check it that way, but we have to write if a <= x <= b I understand that it's not a big deal, but it would be awesome to have some optimisations - it's clearly possible to detect things like that "wrong" one and fix it in a bytecode. x in range optimisation dot dict access foo() if foo() else bar() -- http://mail.python.org/mailman/listinfo/python-list