From bjourne at gmail.com Tue May 1 01:24:25 2007 From: bjourne at gmail.com (=?ISO-8859-1?Q?BJ=F6rn_Lindqvist?=) Date: Mon, 30 Apr 2007 23:24:25 +0000 Subject: [Python-ideas] ordered dict In-Reply-To: <20070426090200.6427.JCARLSON@uci.edu> References: <20070421112051.63AB.JCARLSON@uci.edu> <740c3aec0704260622m46dfd3aav56025918408e3935@mail.gmail.com> <20070426090200.6427.JCARLSON@uci.edu> Message-ID: <740c3aec0704301624x60226147x7bb4c1def423441e@mail.gmail.com> On 4/26/07, Josiah Carlson wrote: > > Similar fuck ups are possible when using dicts. In practice this is > > not a problem. An ordered dict doesn't need any more safeguards than > > Python's already existing data structures. Using the natural order of > > its items are just fine and when you need something more fancy, > > override the __eq__ method or give the collections sort method a > > comparator function argument. > > Except this series of posts is about a "sorted dict", with a key,value > mapping in which the equivalent .items() are sorted() as an ordering > (rather than more or less dependant on hash value as in a standard > dictionary). But as I, and others have stated before, which you should > read once again because you don't seem to get it: > THE EXISTANCE OF A TOTAL ORDERING ON VALUES IN PYTHON TODAY IS A LIE. > IN FUTURE PYTHONS WE ARE REMOVING THE LIE BECAUSE IT DOESN'T HELP ANYONE. > IF YOU DON'T LIKE IT; TOUGH COOKIES. STANDARD PYTHON DICTIONARIES > WILL WORK THE WAY THEY ALWAYS HAVE. ONLY PEOPLE WHO BELIEVE THAT > INCOMPATIBLE TYPES SHOULD BE ORDERED IN A PARTICULAR WAY IN THINGS LIKE > lst.sort() WILL BE AFFECTED. > > If you want an actual reference, please see PEP 3100 which says, > "Comparisons other than == and != between disparate types will raise an > exception unless explicitly supported by the type" > ... and references: > http://mail.python.org/pipermail/python-dev/2004-June/045111.html > > If you don't understand this, please ask again without profanity or > accusing the Python developers of removing the "consenting adults" > requirement. Python is getting smarter. Maybe you just don't > understand why this is the case. I really do not understand what you are talking about. Maybe you have misunderstood something? Lets talk about Java for a moment. Java contains a class called TreeMap which has all the features that the original poster asked for. The Python equivalent to TreeMap would be a "sorted dictionary." Java, just like Python 3k will, forbids comparisions between disparate Comparable types. It follows that Java does not enforce any "total ordering" on disparate types either. The absence of a total ordering does not mean that Java's TreeMap class' constructor needs to be supplied with a list of "allowed key types" as you and Terry Reedy suggested that Python's hypothetical sorted dictionary would need. Try the following Java code: TreeMap tm = new TreeMap(); tm.put(new Integer(3), "moo"); tm.put(new Double(7), "moo"); Java is definitely not designed according to the "we are all consenting adults" philosophy, but it has no problem whatsoever accepting this code. Note that you did NOT have to specify the "allowed key types" and that Integer and Double are incomparable. But when you run it: Exception in thread "main" java.lang.ClassCastException at java.lang.Double.compareTo(Double.java:642) at java.util.TreeMap.compare(TreeMap.java:1085) at java.util.TreeMap.put(TreeMap.java:463) at comp.main(comp.java:9) Which is exactly how I am suggesting that the hypothetical sorted dict class should work too (in py3k). You can read more about these Java classes and interfaces here http://java.sun.com/j2se/1.4.2/docs/api/java/util/TreeMap.html and here http://java.sun.com/j2se/1.4.2/docs/api/java/util/SortedMap.html. I hope you understand now why having to specify or restrict the allowed "key types" is superfluous and why a sorted dict "doesn't need any more safeguards than Python's already existing data structures." -- mvh Bj?rn From jcarlson at uci.edu Tue May 1 05:27:51 2007 From: jcarlson at uci.edu (Josiah Carlson) Date: Mon, 30 Apr 2007 20:27:51 -0700 Subject: [Python-ideas] ordered dict In-Reply-To: <740c3aec0704301624x60226147x7bb4c1def423441e@mail.gmail.com> References: <20070426090200.6427.JCARLSON@uci.edu> <740c3aec0704301624x60226147x7bb4c1def423441e@mail.gmail.com> Message-ID: <20070430194655.6448.JCARLSON@uci.edu> "BJ?rn Lindqvist" wrote: > On 4/26/07, Josiah Carlson wrote: > > > Similar fuck ups are possible when using dicts. In practice this is > > > not a problem. An ordered dict doesn't need any more safeguards than > > > Python's already existing data structures. Using the natural order of > > > its items are just fine and when you need something more fancy, > > > override the __eq__ method or give the collections sort method a > > > comparator function argument. [snip] > I really do not understand what you are talking about. Maybe you have > misunderstood something? In your post with Message-Id: <740c3aec0704202128g6537c5bfv94c0f60a5d883d76 at mail.gmail.com> you state... > >>> l = [(), "moo", 123, []] > >>> l.sort() > >>> l > [123, [], 'moo', ()] > > If it is not a problem for lists it is not a problem for ordered dictionaries. I pointed out in a reply to that message that it would be a problem because the sort will fail in Python 3.x . In your post with Message-Id: <740c3aec0704210817m3e11a9e5lb3325523e2490348 at mail.gmail.com> you offer... > Alternatively, you could require a comparator function to be specified > at creation time. Now you offer Java TreeMap as an example of semantics that you would like to duplicate, from which I now understand the context of offering a 'comparator function'. Your current desired semantics are possible in Python 3.x, as it no longer relies on a total ordering, but merely a "natural ordering" (which should be defined for all a,b pairs both of type c), which list.sort() will rely on in 3.x as well. The question at this point is whether or not we want the equivalent of a Java TreeMap in Python. I'm leaning towards no, as I have found very few uses of such things in my own code. There's also the fact that Daniel Stutzbach's BList implementation (which may make it into Python's collections module), would allow for a more or less equivalent implementation of your desired semantics using bisect, though each operation would suffer an O(logn) slowdown for overall O(nlog^2n) sorting and O(log^2n) insertion/deletion/search per item (O(logn) queries, O(logn) per query*). Would that be sufficient? - Josiah * The BList is at worst log base 64 (at beast 128), so if you are emulating a TreeMap using BList and bisect, then in the worst case of 1 billion items in your TreeMap, you are running at around 1/5 the speed of an equivalent Red-Black tree (1/4 at 16 million, 1/3 at 256k, 1/2 at 4k). From tjreedy at udel.edu Tue May 1 06:08:07 2007 From: tjreedy at udel.edu (Terry Reedy) Date: Tue, 1 May 2007 00:08:07 -0400 Subject: [Python-ideas] ordered dict References: <20070421112051.63AB.JCARLSON@uci.edu><740c3aec0704260622m46dfd3aav56025918408e3935@mail.gmail.com><20070426090200.6427.JCARLSON@uci.edu> <740c3aec0704301624x60226147x7bb4c1def423441e@mail.gmail.com> Message-ID: "BJ?rn Lindqvist" wrote in message news:740c3aec0704301624x60226147x7bb4c1def423441e at mail.gmail.com... >Java, just like Python 3k will, forbids comparisions between disparate >Comparable types. It follows that Java does not enforce any "total >ordering" on disparate types either. The absence of a total ordering >does not mean that Java's TreeMap class' constructor needs to be >supplied with a list of "allowed key types" as you and Terry Reedy >suggested that Python's hypothetical sorted dictionary would need. I don't believe I said 'needs' and I already agreed that such a list would be less helpful than I had suggested. But one would help give better messages from __str__ and exceptions. Also, the first item added does not get compared to anything, so without such a list, it effectively determines the key type. That said, propose what you want and see if it gets enough usage to justify addition to the collections module. Anyone who wants a sorted dict with keytype attibute could get one by subclassing one without. Terry Jan Reedy From jjb5 at cornell.edu Wed May 2 19:55:07 2007 From: jjb5 at cornell.edu (Joel Bender) Date: Wed, 02 May 2007 13:55:07 -0400 Subject: [Python-ideas] fixing mutable default argument values In-Reply-To: <91ad5bf80701181239p1aa710afv4401861257d2eb4f@mail.gmail.com> References: <76fd5acf0701172010j554fa420q38f09151d46883af@mail.gmail.com> <45AF79AC.9090509@cornell.edu> <20070118084035.5974.JCARLSON@uci.edu> <91ad5bf80701181239p1aa710afv4401861257d2eb4f@mail.gmail.com> Message-ID: <4638D07B.9060207@cornell.edu> George Sakkis wrote: >> Sure they have, and they've solved it (under different names) in >> plenty of other languages. In python, the only current solution seems >> to be turning the function into a class (with self) or at least a >> closure. People have griped about this. > > User-defined function attributes is another handy solution. > >> For What Its Worth, my personal opinion is that having to create an >> object instead of a function is annoying, but not so bad (or so >> frequent) that it is worth special syntax. > > Function attributes fit the bill really good if writing a class is too > much overhead. To follow up on this, here is a way to get something pretty close to what I wanted. From this... def foo(x): local history = [] history.append(x) To this... def local(**locals): def _local(fn): fn.__dict__.update(locals) return fn return _local @local(history = []) def foo(x): foo.history.append(x) I like this because it keeps history out of the parameter list, and while it's not part of the local namespace, it's readily accessible. Joel From jjb5 at cornell.edu Wed May 2 21:37:43 2007 From: jjb5 at cornell.edu (Joel Bender) Date: Wed, 02 May 2007 15:37:43 -0400 Subject: [Python-ideas] Should function attributes be properties? Message-ID: <4638E887.4090600@cornell.edu> I was expecting this to work: class myprop(property): def __get__(self, obj, cls): print "get", obj, cls def __set__(self, obj, value): print "set", obj, value def f(x): print 'f' f.p f.p = myprop() So it comes out like this: >>> f(2) f get None Is this a bug? Or was it not in the scope of what properties would be used for? Is this PEP material? Joel From guido at python.org Wed May 2 22:22:06 2007 From: guido at python.org (Guido van Rossum) Date: Wed, 2 May 2007 13:22:06 -0700 Subject: [Python-ideas] Should function attributes be properties? In-Reply-To: <4638E887.4090600@cornell.edu> References: <4638E887.4090600@cornell.edu> Message-ID: You're misunderstanding descriptors. Descriptors only work when placed in a class. On 5/2/07, Joel Bender wrote: > I was expecting this to work: > > class myprop(property): > def __get__(self, obj, cls): print "get", obj, cls > def __set__(self, obj, value): print "set", obj, value > > def f(x): > print 'f' > f.p > > f.p = myprop() > > So it comes out like this: > > >>> f(2) > f > get None > > Is this a bug? Or was it not in the scope of what properties would be > used for? Is this PEP material? > > > Joel > > _______________________________________________ > Python-ideas mailing list > Python-ideas at python.org > http://mail.python.org/mailman/listinfo/python-ideas > -- --Guido van Rossum (home page: http://www.python.org/~guido/) From jimjjewett at gmail.com Thu May 3 00:00:10 2007 From: jimjjewett at gmail.com (Jim Jewett) Date: Wed, 2 May 2007 18:00:10 -0400 Subject: [Python-ideas] fixing mutable default argument values In-Reply-To: <4638D07B.9060207@cornell.edu> References: <76fd5acf0701172010j554fa420q38f09151d46883af@mail.gmail.com> <45AF79AC.9090509@cornell.edu> <20070118084035.5974.JCARLSON@uci.edu> <91ad5bf80701181239p1aa710afv4401861257d2eb4f@mail.gmail.com> <4638D07B.9060207@cornell.edu> Message-ID: On 5/2/07, Joel Bender wrote: > @local(history = []) > def foo(x): > foo.history.append(x) This assumes that the name "foo" won't be rebound underneath you. That is usually, but not always, true. __this_function__ from PEP 3130 would solve that gotcha. > I like this because it keeps history out of the parameter list, and > while it's not part of the local namespace, it's readily accessible. Those are good things. -jJ From greg.ewing at canterbury.ac.nz Thu May 3 02:56:43 2007 From: greg.ewing at canterbury.ac.nz (Greg Ewing) Date: Thu, 03 May 2007 12:56:43 +1200 Subject: [Python-ideas] Should function attributes be properties? In-Reply-To: <4638E887.4090600@cornell.edu> References: <4638E887.4090600@cornell.edu> Message-ID: <4639334B.3090502@canterbury.ac.nz> Joel Bender wrote: > Is this a bug? Or was it not in the scope of what properties would be > used for? The latter. To work, a property has to live in the class of an object, not an attribute of the object itself. -- Greg From grosser.meister.morti at gmx.net Mon May 7 00:13:30 2007 From: grosser.meister.morti at gmx.net (=?ISO-8859-1?Q?Mathias_Panzenb=F6ck?=) Date: Mon, 07 May 2007 00:13:30 +0200 Subject: [Python-ideas] PEP for executing a module in a package containing relative imports In-Reply-To: References: Message-ID: <463E530A.8090200@gmx.net> what about: if __module__ is __main__: ... __module__ is a reference to "this module" and __main__ is a reference to the module which stated execution this would have the sideeffect that: def f(): __module__.x = 42 equals: def f(): global x x = 42 etc. Off Topic: a __func__ would also be nice: def foo(): print __func__.__name__ prints "foo" def foo(): x = 1 def bar(): __func__.parent.x += 1 return __func__.parent.x return bar print bar() prints "2" well, on second thought this is looks a bit cluttered. From brett at python.org Mon May 7 04:54:13 2007 From: brett at python.org (Brett Cannon) Date: Sun, 6 May 2007 19:54:13 -0700 Subject: [Python-ideas] PEP for executing a module in a package containing relative imports In-Reply-To: <463E530A.8090200@gmx.net> References: <463E530A.8090200@gmx.net> Message-ID: On 5/6/07, Mathias Panzenb?ck wrote: > > what about: > > if __module__ is __main__: > ... > > __module__ is a reference to "this module" and > __main__ is a reference to the module which stated execution > > this would have the sideeffect that: > > def f(): > __module__.x = 42 > > equals: > > def f(): > global x > x = 42 > > etc. That's fine, but Guido has killed any attempt to fix this situation. Off Topic: > a __func__ would also be nice: > > def foo(): > print __func__.__name__ > > prints "foo" > > def foo(): > x = 1 > > def bar(): > __func__.parent.x += 1 > return __func__.parent.x > > return bar > > print bar() > > prints "2" See PEP 3130. -Brett -------------- next part -------------- An HTML attachment was scrubbed... URL: From castironpi at comcast.net Wed May 9 04:22:00 2007 From: castironpi at comcast.net (Aaron Brady) Date: Tue, 8 May 2007 21:22:00 -0500 Subject: [Python-ideas] subclassing standard module Message-ID: <20070509022203.E62BC1E4002@bag.python.org> This on module inspect. I'd like to subclass inspect.BlockFinder, but inspect.getblock uses it directly. Should we encapsulate this? -------------- next part -------------- An HTML attachment was scrubbed... URL: From tomerfiliba at gmail.com Wed May 9 18:07:33 2007 From: tomerfiliba at gmail.com (tomer filiba) Date: Wed, 9 May 2007 18:07:33 +0200 Subject: [Python-ideas] the future of the GIL In-Reply-To: <1d85506f0705090147w155c15d3ka61f0f23b435b3a9@mail.gmail.com> References: <1d85506f0705090147w155c15d3ka61f0f23b435b3a9@mail.gmail.com> Message-ID: <1d85506f0705090907l735e007bk6a5f4aa6d4ad7701@mail.gmail.com> [ moved to python-ideas from python-3000 ] On 5/8/07, Thomas Heller wrote: > Wouldn't multiple interpreters (assuming the problems with them would be fixed) > in the same process give the same benefit? A separate GIL for each one? hmm, i find this idea quite interesting really: * builtin immutable objects such as None, small ints, non-heap types, and builtin functions, would become uncollectible by the GC. after all, we can't reclaim their memory anyway, so keeping the accounting info is just a waste of time. the PyObject_HEAD struct would grow an "ob_collectible" field, which would tell the GC to ignore these objects altogether. for efficiency reasons, Py_INCREF/DECREF would still change ob_refcount, only the GC will ignore it for uncollectible objects. * each thread would have a separate interpreter, and all APIs should grow an additional parameter that specifies the interpreter state to use. * for compatibility reasons, we can also have a dict-like object mapping between thread-ids to interpreter states. when you invoke an API, it would get the interpreter state from the currently executing thread id. maybe that could be defined as a macro over the real API function. * the builtin immutable objects would be shared between all instances of the interpreter. other then those, all other objects would be local to the interpreter that created them * extension modules would have to be changed to support per-interpreter initialization. * in order to communicate between interpreters, we would use some kind of IPC mechanism, to serialize access to objects. of course it would be much more efficient, as no context switches are required in the same process. this would make each thread basically as protected as a OS process, so no locks would be required. * in order to support the IPC, a new builtin type, Proxy, would be added to the language. it would be the only object that can hold a cross-reference to objects in different interpreters -- much like today's RPC libs -- only that wouldn't have to work over a socket. * if python would ever have a tracing GC, that would greatly simplify things. also, moving to an atomic incref/decref library could also help. of course i'm not talking about adding that to py3k. it's too immature even for a pre-pep. but continuing to develop that idea more could be the means to removing the GIL, and finally having really parallel python scripts. -tomer From santagada at gmail.com Wed May 9 15:16:26 2007 From: santagada at gmail.com (Leonardo Santagada) Date: Wed, 9 May 2007 10:16:26 -0300 Subject: [Python-ideas] [Python-3000] the future of the GIL In-Reply-To: <9F3AFD78-7C73-4C9F-8CA6-3D10A1468939@fuhm.net> References: <1d85506f0705050629k35ebdf6aj285e8f10489d21d5@mail.gmail.com> <9F3AFD78-7C73-4C9F-8CA6-3D10A1468939@fuhm.net> Message-ID: <15D34974-A1F6-488F-8422-6E0DCAE7BDD3@gmail.com> Em 09/05/2007, ?s 04:26, James Y Knight escreveu: > On May 7, 2007, at 1:58 PM, Guido van Rossum wrote: >> As C doesn't have an atomic increment nor an atomic >> decrement-and-test, the INCREF and DECREF macros sprinkled throughout >> the code (many thousands of them) must be protected by some lock. > > I've been intently ignoring the rest of the thread (and will continue > to do so), but, to respond to this one particular point... > > This just isn't true. Python can do an atomic increment in a fast > platform specific way. It need not restrict itself to what's > available in C. (after all, *threads* aren't available in C....) > > Two implementations of note: > > 1) gcc 4.1 has atomic operation builtins: > http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Atomic- > Builtins.html#Atomic-Builtins > > 2) There's a pretty damn portable library which provides these > functions for what looks to me like pretty much all CPUs anyone would > use, under Linux, Windows, HP/UX, Solaris, and OSX, and has a > fallback to using pthreads mutexes: > > http://www.hpl.hp.com/research/linux/atomic_ops/index.php4 > http://packages.debian.org/stable/libdevel/libatomic-ops-dev > > > It's quite possible the overhead of GIL-less INCREF/DECREF is still > too high even with atomic increment/decrement primitives, but AFAICT > nobody has actually tried it. So saying GIL-less operation for sure > has too high of an overhead unless the refcounting GC is replaced > seems a bit premature. > > James This seems like a good idea... how about moving this discussion to python-ideas? -- Leonardo Santagada santagada at gmail.com From santagada at gmail.com Wed May 9 15:20:15 2007 From: santagada at gmail.com (Leonardo Santagada) Date: Wed, 9 May 2007 10:20:15 -0300 Subject: [Python-ideas] [Python-3000] the future of the GIL In-Reply-To: References: <463E4645.5000503@acm.org> <20070506222840.25B2.JCARLSON@uci.edu> Message-ID: Em 09/05/2007, ?s 06:07, Giovanni Bajo escreveu: > On 07/05/2007 7.36, Josiah Carlson wrote: > >> By going multi-process rather than multi-threaded, one generally >> removes >> shared memory from the equasion. Note that this has the same >> effect as >> using queues with threads, which is generally seen as the only way of >> making threads "easy". If one *needs* shared memory, we can >> certainly >> create an mmap-based shared memory subsystem with fine-grained object >> locking, or emulate it via a server process as the processing package >> has done. >> >> Seriously, give the processing package a try. It's much faster >> than one >> would expect. > > I'm fully +1 with you on everything. > > And part of the fact that we have to advocate this is because > Python has > always had pretty good threading libraries, but not processing > libraries; > actually, Python does have problems at spawning processes: the whole > popen/popen2/subprocess mess isn't even fully solved yet. > > One thing to be said, though, is that using multiple processes > cause some > headaches with frozen distributions (PyInstaller, py2exe, etc.), > like those > usually found on Windows, specifically because Windows does not > have fork(). > > The processing module, for instance, doesn't take this problem into > account at > all, making it worthless for many of my real-world use cases. > -- > Giovanni Bajo Another problem is that althought people like the idea of processing more, the only module on python stdlib is thread and Threading... So why not include processing in stdlib and in both thread and Threading give pointers to its use? This would probably diminish the problem with newcomers on the language that hate the GIL because they don't know better (and also because threading is supported out of the box on python). Yes I know there is fork, but still it is not as useable and pythonic as processing. -- Leonardo Santagada santagada at gmail.com From castironpi at comcast.net Wed May 9 22:22:40 2007 From: castironpi at comcast.net (Aaron Brady) Date: Wed, 9 May 2007 15:22:40 -0500 Subject: [Python-ideas] parameter omit Message-ID: <20070509202544.CC7471E4002@bag.python.org> Is it possible to signal to a parameter to use its default? def f( a, b=None, c='' ):... f( 123, , 'abc' ) f( 123, ObjA, ) Did I miss something, plus did you cover it before? -------------- next part -------------- An HTML attachment was scrubbed... URL: From steven.bethard at gmail.com Wed May 9 22:45:14 2007 From: steven.bethard at gmail.com (Steven Bethard) Date: Wed, 9 May 2007 14:45:14 -0600 Subject: [Python-ideas] parameter omit In-Reply-To: <20070509202544.CC7471E4002@bag.python.org> References: <20070509202544.CC7471E4002@bag.python.org> Message-ID: On 5/9/07, Aaron Brady wrote: > Is it possible to signal to a parameter to use its default? > > def f( a, b=None, c='' ):... > > f( 123, , 'abc' ) > f( 123, ObjA, ) In this case, it's pretty easy:: f(123, c='abc') f(123, ObjA) STeVe -- I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a tiny blip on the distant coast of sanity. --- Bucky Katt, Get Fuzzy From castironpi at comcast.net Wed May 9 23:42:35 2007 From: castironpi at comcast.net (Aaron Brady) Date: Wed, 9 May 2007 16:42:35 -0500 Subject: [Python-ideas] parameter omit In-Reply-To: Message-ID: <20070509214244.086DF1E4009@bag.python.org> Actually, I wanted a uniform way to call f. f(a,b,c) for both cases if b can equal . -----Original Message----- From: Steven Bethard [mailto:steven.bethard at gmail.com] Sent: Wednesday, May 09, 2007 3:45 PM To: Aaron Brady Cc: python-ideas at python.org Subject: Re: [Python-ideas] parameter omit On 5/9/07, Aaron Brady wrote: > Is it possible to signal to a parameter to use its default? > > def f( a, b=None, c='' ):... > > f( 123, , 'abc' ) > f( 123, ObjA, ) In this case, it's pretty easy:: f(123, c='abc') f(123, ObjA) STeVe -- I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a tiny blip on the distant coast of sanity. --- Bucky Katt, Get Fuzzy From jcarlson at uci.edu Wed May 9 23:50:44 2007 From: jcarlson at uci.edu (Josiah Carlson) Date: Wed, 09 May 2007 14:50:44 -0700 Subject: [Python-ideas] parameter omit In-Reply-To: <20070509214244.086DF1E4009@bag.python.org> References: <20070509214244.086DF1E4009@bag.python.org> Message-ID: <20070509145008.25EB.JCARLSON@uci.edu> "Aaron Brady" wrote: > > Actually, I wanted a uniform way to call f. f(a,b,c) for both cases if b > can equal . f(a, b=...) #default c f(a, c=...) #default b - Josiah > -----Original Message----- > From: Steven Bethard [mailto:steven.bethard at gmail.com] > Sent: Wednesday, May 09, 2007 3:45 PM > To: Aaron Brady > Cc: python-ideas at python.org > Subject: Re: [Python-ideas] parameter omit > > On 5/9/07, Aaron Brady wrote: > > Is it possible to signal to a parameter to use its default? > > > > def f( a, b=None, c='' ):... > > > > f( 123, , 'abc' ) > > f( 123, ObjA, ) > > In this case, it's pretty easy:: > > f(123, c='abc') > f(123, ObjA) > > STeVe > -- > I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a > tiny blip on the distant coast of sanity. > --- Bucky Katt, Get Fuzzy > > _______________________________________________ > Python-ideas mailing list > Python-ideas at python.org > http://mail.python.org/mailman/listinfo/python-ideas From castironpi at comcast.net Wed May 9 23:50:10 2007 From: castironpi at comcast.net (Aaron Brady) Date: Wed, 9 May 2007 16:50:10 -0500 Subject: [Python-ideas] parameter omit In-Reply-To: <20070509145008.25EB.JCARLSON@uci.edu> Message-ID: <20070509215017.B047C1E4004@bag.python.org> No, still not uniform. Cases might be rare, even syntactic sugar maybe. if something huge: b= more huge if something else: b=mything still more f(a,b,c). -----Original Message----- From: Josiah Carlson [mailto:jcarlson at uci.edu] Sent: Wednesday, May 09, 2007 4:51 PM To: Aaron Brady; python-ideas at python.org Subject: Re: [Python-ideas] parameter omit "Aaron Brady" wrote: > > Actually, I wanted a uniform way to call f. f(a,b,c) for both cases if b > can equal . f(a, b=...) #default c f(a, c=...) #default b - Josiah > -----Original Message----- > From: Steven Bethard [mailto:steven.bethard at gmail.com] > Sent: Wednesday, May 09, 2007 3:45 PM > To: Aaron Brady > Cc: python-ideas at python.org > Subject: Re: [Python-ideas] parameter omit > > On 5/9/07, Aaron Brady wrote: > > Is it possible to signal to a parameter to use its default? > > > > def f( a, b=None, c='' ):... > > > > f( 123, , 'abc' ) > > f( 123, ObjA, ) > > In this case, it's pretty easy:: > > f(123, c='abc') > f(123, ObjA) > > STeVe > -- > I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a > tiny blip on the distant coast of sanity. > --- Bucky Katt, Get Fuzzy > > _______________________________________________ > Python-ideas mailing list > Python-ideas at python.org > http://mail.python.org/mailman/listinfo/python-ideas From castironpi at comcast.net Wed May 9 23:55:33 2007 From: castironpi at comcast.net (Aaron Brady) Date: Wed, 9 May 2007 16:55:33 -0500 Subject: [Python-ideas] parameter omit In-Reply-To: <20070509215017.B047C1E4004@bag.python.org> Message-ID: <20070509215540.9025E1E4002@bag.python.org> You can almost do, b=f.func_defaults[1], but you still have to know where the defaults start. Very small what I'm missing. -----Original Message----- From: python-ideas-bounces at python.org [mailto:python-ideas-bounces at python.org] On Behalf Of Aaron Brady Sent: Wednesday, May 09, 2007 4:50 PM To: 'Josiah Carlson'; python-ideas at python.org Subject: Re: [Python-ideas] parameter omit No, still not uniform. Cases might be rare, even syntactic sugar maybe. if something huge: b= more huge if something else: b=mything still more f(a,b,c). -----Original Message----- From: Josiah Carlson [mailto:jcarlson at uci.edu] Sent: Wednesday, May 09, 2007 4:51 PM To: Aaron Brady; python-ideas at python.org Subject: Re: [Python-ideas] parameter omit "Aaron Brady" wrote: > > Actually, I wanted a uniform way to call f. f(a,b,c) for both cases if b > can equal . f(a, b=...) #default c f(a, c=...) #default b - Josiah > -----Original Message----- > From: Steven Bethard [mailto:steven.bethard at gmail.com] > Sent: Wednesday, May 09, 2007 3:45 PM > To: Aaron Brady > Cc: python-ideas at python.org > Subject: Re: [Python-ideas] parameter omit > > On 5/9/07, Aaron Brady wrote: > > Is it possible to signal to a parameter to use its default? > > > > def f( a, b=None, c='' ):... > > > > f( 123, , 'abc' ) > > f( 123, ObjA, ) > > In this case, it's pretty easy:: > > f(123, c='abc') > f(123, ObjA) > > STeVe > -- > I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a > tiny blip on the distant coast of sanity. > --- Bucky Katt, Get Fuzzy > > _______________________________________________ > Python-ideas mailing list > Python-ideas at python.org > http://mail.python.org/mailman/listinfo/python-ideas _______________________________________________ Python-ideas mailing list Python-ideas at python.org http://mail.python.org/mailman/listinfo/python-ideas From castironpi at comcast.net Thu May 10 00:35:24 2007 From: castironpi at comcast.net (Aaron Brady) Date: Wed, 9 May 2007 17:35:24 -0500 Subject: [Python-ideas] parameter omit Message-ID: <20070509223534.D58C11E4002@bag.python.org> Could easily incorporate, as shown here. #sample function with default args def f( a,b=None,c='abc' ): print a,b,c #customizer default= object() def call_wrapper( callable, *args, **kwargs ): args=list(args) for i,j in enumerate( args ): if j is default: offset= callable.func_code.co_argcount-\ len(callable.func_defaults) args[i]= callable.func_defaults[i-offset] return callable( *args,**kwargs ) #the uniform calls call_wrapper( f,0,default,'def' ) call_wrapper( f,0,'somebody',default ) -----Original Message----- From: Aaron Brady [mailto:castironpi at comcast.net] Sent: Wednesday, May 09, 2007 4:56 PM To: 'Aaron Brady'; 'Josiah Carlson'; 'python-ideas at python.org' Subject: RE: [Python-ideas] parameter omit You can almost do, b=f.func_defaults[1], but you still have to know where the defaults start. Very small what I'm missing. -----Original Message----- From: python-ideas-bounces at python.org [mailto:python-ideas-bounces at python.org] On Behalf Of Aaron Brady Sent: Wednesday, May 09, 2007 4:50 PM To: 'Josiah Carlson'; python-ideas at python.org Subject: Re: [Python-ideas] parameter omit No, still not uniform. Cases might be rare, even syntactic sugar maybe. if something huge: b= more huge if something else: b=mything still more f(a,b,c). -----Original Message----- From: Josiah Carlson [mailto:jcarlson at uci.edu] Sent: Wednesday, May 09, 2007 4:51 PM To: Aaron Brady; python-ideas at python.org Subject: Re: [Python-ideas] parameter omit "Aaron Brady" wrote: > > Actually, I wanted a uniform way to call f. f(a,b,c) for both cases if b > can equal . f(a, b=...) #default c f(a, c=...) #default b - Josiah > -----Original Message----- > From: Steven Bethard [mailto:steven.bethard at gmail.com] > Sent: Wednesday, May 09, 2007 3:45 PM > To: Aaron Brady > Cc: python-ideas at python.org > Subject: Re: [Python-ideas] parameter omit > > On 5/9/07, Aaron Brady wrote: > > Is it possible to signal to a parameter to use its default? > > > > def f( a, b=None, c='' ):... > > > > f( 123, , 'abc' ) > > f( 123, ObjA, ) > > In this case, it's pretty easy:: > > f(123, c='abc') > f(123, ObjA) > > STeVe > -- > I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a > tiny blip on the distant coast of sanity. > --- Bucky Katt, Get Fuzzy > > _______________________________________________ > Python-ideas mailing list > Python-ideas at python.org > http://mail.python.org/mailman/listinfo/python-ideas _______________________________________________ Python-ideas mailing list Python-ideas at python.org http://mail.python.org/mailman/listinfo/python-ideas From scott+python-ideas at scottdial.com Thu May 10 00:15:42 2007 From: scott+python-ideas at scottdial.com (Scott Dial) Date: Wed, 09 May 2007 18:15:42 -0400 Subject: [Python-ideas] parameter omit In-Reply-To: <20070509215540.9025E1E4002@bag.python.org> References: <20070509215540.9025E1E4002@bag.python.org> Message-ID: <4642480E.9070006@scottdial.com> Aaron Brady wrote: > You can almost do, > b=f.func_defaults[1], > but you still have to know where the defaults start. Very small what I'm > missing. > > -----Original Message----- > From: python-ideas-bounces at python.org > [mailto:python-ideas-bounces at python.org] On Behalf Of Aaron Brady > Sent: Wednesday, May 09, 2007 4:50 PM > To: 'Josiah Carlson'; python-ideas at python.org > Subject: Re: [Python-ideas] parameter omit > > No, still not uniform. Cases might be rare, even syntactic sugar maybe. > if something huge: > b= > more huge > if something else: > b=mything > still more > f(a,b,c). > I've never wanted to do this in my life.. args = {} if foo: args['b'] = b if bar: args['c'] = c f(a, **kwargs) -Scott -- Scott Dial scott at scottdial.com scodial at cs.indiana.edu From castironpi at comcast.net Thu May 10 23:34:40 2007 From: castironpi at comcast.net (Aaron Brady) Date: Thu, 10 May 2007 16:34:40 -0500 Subject: [Python-ideas] parser in stdlib Message-ID: <20070510213449.099CC1E4003@bag.python.org> Is it possible to get `profile' into the stdlib? Currently just tinkering, and it might not be advisable either, subject to abuse, per GvR: "Programmable syntax is not in Python's future -- or at least it's not for Python 3000. The problem IMO is that everybody will abuse it to define their own language. And the problem with that is that it will fracture the Python community because nobody can read each other's code any more." - http://mail.python.org/pipermail/python-3000/2006-April/000286.html What do you think? Same reason apply? -------------- next part -------------- An HTML attachment was scrubbed... URL: From adam at atlas.st Thu May 10 23:45:36 2007 From: adam at atlas.st (Adam Atlas) Date: Thu, 10 May 2007 17:45:36 -0400 Subject: [Python-ideas] parser in stdlib In-Reply-To: <20070510213449.099CC1E4003@bag.python.org> References: <20070510213449.099CC1E4003@bag.python.org> Message-ID: <311252E3-C7A0-4D03-BA14-310F84635D00@atlas.st> On 10 May 2007, at 17.34, Aaron Brady wrote: > Is it possible to get `profile? into the stdlib? Currently just > tinkering, and it might not be advisable either, subject to abuse, > per GvR: What are you referring to here as `profile`? You're obviously (I think?) not talking about the existing stdlib module called `profile`. From castironpi at comcast.net Fri May 11 00:26:01 2007 From: castironpi at comcast.net (Aaron Brady) Date: Thu, 10 May 2007 17:26:01 -0500 Subject: [Python-ideas] parser in stdlib In-Reply-To: <311252E3-C7A0-4D03-BA14-310F84635D00@atlas.st> Message-ID: <20070510222612.4322C1E4003@bag.python.org> >From: Adam Atlas [mailto:adam at atlas.st] >Sent: Thursday, May 10, 2007 4:46 PM > >On 10 May 2007, at 17.34, Aaron Brady wrote: >> Is it possible to get `profile' into the stdlib? Currently just >> tinkering, and it might not be advisable either, subject to abuse, >> per GvR: > >What are you referring to here as `profile`? You're obviously (I >think?) not talking about the existing stdlib module called `profile`.= Right. Pretend I said `parser' instead. From collinw at gmail.com Fri May 11 00:38:46 2007 From: collinw at gmail.com (Collin Winter) Date: Thu, 10 May 2007 15:38:46 -0700 Subject: [Python-ideas] parser in stdlib In-Reply-To: <20070510222612.4322C1E4003@bag.python.org> References: <311252E3-C7A0-4D03-BA14-310F84635D00@atlas.st> <20070510222612.4322C1E4003@bag.python.org> Message-ID: <43aa6ff70705101538j62ad47a3oc650dd7b2393a520@mail.gmail.com> On 5/10/07, Aaron Brady wrote: > >From: Adam Atlas [mailto:adam at atlas.st] > >Sent: Thursday, May 10, 2007 4:46 PM > > > >On 10 May 2007, at 17.34, Aaron Brady wrote: > >> Is it possible to get `profile' into the stdlib? Currently just > >> tinkering, and it might not be advisable either, subject to abuse, > >> per GvR: > > > >What are you referring to here as `profile`? You're obviously (I > >think?) not talking about the existing stdlib module called `profile`.= > > Right. Pretend I said `parser' instead. Your request still doesn't make any sense: http://docs.python.org/lib/module-parser.html Collin Winter From castironpi at comcast.net Fri May 11 00:39:20 2007 From: castironpi at comcast.net (Aaron Brady) Date: Thu, 10 May 2007 17:39:20 -0500 Subject: [Python-ideas] parser in stdlib In-Reply-To: Message-ID: <20070510223928.60CCB1E4003@bag.python.org> > -----Original Message----- > From: Steven Bethard [mailto:steven.bethard at gmail.com] > Sent: Thursday, May 10, 2007 5:32 PM > > On 10 May 2007, at 17.34, Aaron Brady wrote: > > Is it possible to get `profile' into the stdlib? > > From: Adam Atlas [mailto:adam at atlas.st] > > What are you referring to here as `profile`? You're obviously (I > > think?) not talking about the existing stdlib module called `profile`.= > > On 5/10/07, Aaron Brady wrote: > > Right. Pretend I said `parser' instead. > > I'm afraid that's not any clearer. There's also already a parser module: > > >>> import parser > >>> parser.__doc__ > "This is an interface to Python's internal parser." > > STeVe > -- > I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a > tiny blip on the distant coast of sanity. > --- Bucky Katt, Get Fuzzy > There is, but I want access to it. >>> import parser >>> parser.__file__ Traceback (most recent call last): File "", line 1, in AttributeError: 'module' object has no attribute '__file__' From castironpi at comcast.net Fri May 11 00:45:41 2007 From: castironpi at comcast.net (Aaron Brady) Date: Thu, 10 May 2007 17:45:41 -0500 Subject: [Python-ideas] parser in stdlib In-Reply-To: <43aa6ff70705101538j62ad47a3oc650dd7b2393a520@mail.gmail.com> Message-ID: <20070510224549.4C18E1E4003@bag.python.org> > -----Original Message----- > From: Collin Winter [mailto:collinw at gmail.com] > Sent: Thursday, May 10, 2007 5:39 PM > > On 5/10/07, Aaron Brady wrote: > > >From: Adam Atlas [mailto:adam at atlas.st] > > >Sent: Thursday, May 10, 2007 4:46 PM > > > > > >On 10 May 2007, at 17.34, Aaron Brady wrote: > > >> Is it possible to get `profile' into the stdlib? Currently just > > >> tinkering, and it might not be advisable either, subject to abuse, > > >> per GvR: > > > > > >What are you referring to here as `profile`? You're obviously (I > > >think?) not talking about the existing stdlib module called `profile`.= > > > > Right. Pretend I said `parser' instead. > > Your request still doesn't make any sense: > http://docs.python.org/lib/module-parser.html > > Collin Winter Very well; I wasn't close to clear. I want to do a custom compile, say by overriding one of the methods in `parser'. Where are they? C:\Python25\Lib>dir p*.py Volume in drive C is C Local Disk Volume Serial Number is E849-EE50 Directory of C:\Python25\Lib 04/04/2007 06:17 PM 43,532 pdb.py 10/28/2005 08:07 PM 46,183 pickle.py parser.py is not to be found. From adam at atlas.st Fri May 11 00:47:01 2007 From: adam at atlas.st (Adam Atlas) Date: Thu, 10 May 2007 18:47:01 -0400 Subject: [Python-ideas] parser in stdlib In-Reply-To: References: <20070510223928.60CCB1E4003@bag.python.org> Message-ID: <194B3690-3D8F-4D45-9D07-D1E537F292EF@atlas.st> On 10 May 2007, at 18.39, Aaron Brady wrote: > There is, but I want access to it. >>>> import parser >>>> parser.__file__ > Traceback (most recent call last): > File "", line 1, in > AttributeError: 'module' object has no attribute '__file__' That's because it's a builtin module, written in C. It's Python/ parsermodule.c in the source distributions. What exactly are you suggesting should be possible? Are you trying to programmatically change the parser? From castironpi at comcast.net Fri May 11 00:50:28 2007 From: castironpi at comcast.net (Aaron Brady) Date: Thu, 10 May 2007 17:50:28 -0500 Subject: [Python-ideas] parser in stdlib In-Reply-To: <194B3690-3D8F-4D45-9D07-D1E537F292EF@atlas.st> Message-ID: <20070510225036.52FA81E400C@bag.python.org> > -----Original Message----- > From: python-ideas-bounces at python.org [mailto:python-ideas- > bounces at python.org] On Behalf Of Adam Atlas > Sent: Thursday, May 10, 2007 5:47 PM > > On 10 May 2007, at 18.39, Aaron Brady wrote: > > There is, but I want access to it. > >>>> import parser > >>>> parser.__file__ > > Traceback (most recent call last): > > File "", line 1, in > > AttributeError: 'module' object has no attribute '__file__' > > That's because it's a builtin module, written in C. It's Python/ > parsermodule.c in the source distributions. > > What exactly are you suggesting should be possible? Are you trying to > programmatically change the parser? Yes. The relevant code snippet: class Transformer: def parsesuite(self, text): """Return a modified parse tree for the given suite text.""" return self.transform(parser.suite(text)) Hence to allusion to Van Rossum's note, for the record. From collinw at gmail.com Fri May 11 00:56:30 2007 From: collinw at gmail.com (Collin Winter) Date: Thu, 10 May 2007 15:56:30 -0700 Subject: [Python-ideas] parser in stdlib In-Reply-To: <20070510225036.52FA81E400C@bag.python.org> References: <194B3690-3D8F-4D45-9D07-D1E537F292EF@atlas.st> <20070510225036.52FA81E400C@bag.python.org> Message-ID: <43aa6ff70705101556q5ec76666geb7984978ceef3b1@mail.gmail.com> On 5/10/07, Aaron Brady wrote: > > -----Original Message----- > > From: python-ideas-bounces at python.org [mailto:python-ideas- > > bounces at python.org] On Behalf Of Adam Atlas > > Sent: Thursday, May 10, 2007 5:47 PM > > > > On 10 May 2007, at 18.39, Aaron Brady wrote: > > > There is, but I want access to it. > > >>>> import parser > > >>>> parser.__file__ > > > Traceback (most recent call last): > > > File "", line 1, in > > > AttributeError: 'module' object has no attribute '__file__' > > > > That's because it's a builtin module, written in C. It's Python/ > > parsermodule.c in the source distributions. > > > > What exactly are you suggesting should be possible? Are you trying to > > programmatically change the parser? > > Yes. The relevant code snippet: > > class Transformer: > > def parsesuite(self, text): > """Return a modified parse tree for the given suite text.""" > return self.transform(parser.suite(text)) > > Hence to allusion to Van Rossum's note, for the record. That is not and will not be possible using Python's built-in parser. Collin Winter From castironpi at comcast.net Fri May 11 01:00:42 2007 From: castironpi at comcast.net (Aaron Brady) Date: Thu, 10 May 2007 18:00:42 -0500 Subject: [Python-ideas] parser in stdlib In-Reply-To: <43aa6ff70705101556q5ec76666geb7984978ceef3b1@mail.gmail.com> Message-ID: <20070510230051.3B4ED1E4003@bag.python.org> > -----Original Message----- > From: Collin Winter [mailto:collinw at gmail.com] > Sent: Thursday, May 10, 2007 5:57 PM > > On 5/10/07, Aaron Brady wrote: > > > -----Original Message----- > > > From: python-ideas-bounces at python.org [mailto:python-ideas- > > > bounces at python.org] On Behalf Of Adam Atlas > > > Sent: Thursday, May 10, 2007 5:47 PM > > > > > > On 10 May 2007, at 18.39, Aaron Brady wrote: > > > > There is, but I want access to it. > > > >>>> import parser > > > >>>> parser.__file__ > > > > Traceback (most recent call last): > > > > File "", line 1, in > > > > AttributeError: 'module' object has no attribute '__file__' > > > > > > That's because it's a builtin module, written in C. It's Python/ > > > parsermodule.c in the source distributions. > > > > > > What exactly are you suggesting should be possible? Are you trying to > > > programmatically change the parser? > > > > Yes. The relevant code snippet: > > > > class Transformer: > > > > def parsesuite(self, text): > > """Return a modified parse tree for the given suite text.""" > > return self.transform(parser.suite(text)) > > > > Hence to allusion to Van Rossum's note, for the record. > > That is not and will not be possible using Python's built-in parser. > > Collin Winter I'm 25, FTR, heavy experience. Why not? PEP or FAQ if there is one. Aaron Brady From collinw at gmail.com Fri May 11 01:07:56 2007 From: collinw at gmail.com (Collin Winter) Date: Thu, 10 May 2007 16:07:56 -0700 Subject: [Python-ideas] parser in stdlib In-Reply-To: <4643a431.03d79cb4.6461.fffff2ccSMTPIN_ADDED@mx.google.com> References: <43aa6ff70705101556q5ec76666geb7984978ceef3b1@mail.gmail.com> <4643a431.03d79cb4.6461.fffff2ccSMTPIN_ADDED@mx.google.com> Message-ID: <43aa6ff70705101607p266dcee3o4c79214ac0fdf937@mail.gmail.com> On 5/10/07, Aaron Brady wrote: > > -----Original Message----- > > From: Collin Winter [mailto:collinw at gmail.com] > > Sent: Thursday, May 10, 2007 5:57 PM > > > > On 5/10/07, Aaron Brady wrote: > > > > -----Original Message----- > > > > From: python-ideas-bounces at python.org [mailto:python-ideas- > > > > bounces at python.org] On Behalf Of Adam Atlas > > > > Sent: Thursday, May 10, 2007 5:47 PM > > > > > > > > On 10 May 2007, at 18.39, Aaron Brady wrote: > > > > > There is, but I want access to it. > > > > >>>> import parser > > > > >>>> parser.__file__ > > > > > Traceback (most recent call last): > > > > > File "", line 1, in > > > > > AttributeError: 'module' object has no attribute '__file__' > > > > > > > > That's because it's a builtin module, written in C. It's Python/ > > > > parsermodule.c in the source distributions. > > > > > > > > What exactly are you suggesting should be possible? Are you trying to > > > > programmatically change the parser? > > > > > > Yes. The relevant code snippet: > > > > > > class Transformer: > > > > > > def parsesuite(self, text): > > > """Return a modified parse tree for the given suite text.""" > > > return self.transform(parser.suite(text)) > > > > > > Hence to allusion to Van Rossum's note, for the record. > > > > That is not and will not be possible using Python's built-in parser. > > > > Collin Winter > > I'm 25, FTR, heavy experience. I have no idea why that's relevant. > Why not? PEP or FAQ if there is one. Because programmable syntax isn't something we want in Python; you yourself quoted an email from Guido explaining why. If you like the idea of allowing every module to define its own syntactic constructs -- at runtime or otherwise -- Perl 6, Haskell and others are more than happy to help you. Collin Winter From castironpi at comcast.net Fri May 11 01:11:47 2007 From: castironpi at comcast.net (Aaron Brady) Date: Thu, 10 May 2007 18:11:47 -0500 Subject: [Python-ideas] parser in stdlib In-Reply-To: <20070510230051.3B4ED1E4003@bag.python.org> Message-ID: <20070510231155.2EAAE1E4003@bag.python.org> > -----Original Message----- > From: python-ideas-bounces at python.org [mailto:python-ideas- > bounces at python.org] On Behalf Of Aaron Brady > Sent: Thursday, May 10, 2007 6:01 PM > > > -----Original Message----- > > From: Collin Winter [mailto:collinw at gmail.com] > > Sent: Thursday, May 10, 2007 5:57 PM > > > > On 5/10/07, Aaron Brady wrote: > > > > -----Original Message----- > > > > From: python-ideas-bounces at python.org [mailto:python-ideas- > > > > bounces at python.org] On Behalf Of Adam Atlas > > > > Sent: Thursday, May 10, 2007 5:47 PM > > > > > > > > On 10 May 2007, at 18.39, Aaron Brady wrote: > > > > > There is, but I want access to it. > > > > >>>> import parser > > > > >>>> parser.__file__ > > > > > Traceback (most recent call last): > > > > > File "", line 1, in > > > > > AttributeError: 'module' object has no attribute '__file__' > > > > > > > > That's because it's a builtin module, written in C. It's Python/ > > > > parsermodule.c in the source distributions. > > > > > > > > What exactly are you suggesting should be possible? Are you trying > to > > > > programmatically change the parser? > > > > > > Yes. The relevant code snippet: > > > > > > class Transformer: > > > > > > def parsesuite(self, text): > > > """Return a modified parse tree for the given suite text.""" > > > return self.transform(parser.suite(text)) > > > > > > Hence to allusion to Van Rossum's note, for the record. > > > > That is not and will not be possible using Python's built-in parser. > > > > Collin Winter > > I'm 25, FTR, heavy experience. Why not? PEP or FAQ if there is one. > > Aaron Brady > I'd also like to get an attribute in class objects containing the first line number, and can't see why not. Code objects have them; new.code() requires them. I've treated dynamic creation on the newsgroup, and inspect.findsource(object): if isclass(object): name = object.__name__ pat = re.compile(r'^(\s*)class\s*' + name + r'\b') # make some effort to find the best matching class definition: # use the one with the least indentation, which is the one # that's most probably not inside a function definition. candidates = [] cleans up quite a bit. Aaron Brady From castironpi at comcast.net Fri May 11 01:14:11 2007 From: castironpi at comcast.net (Aaron Brady) Date: Thu, 10 May 2007 18:14:11 -0500 Subject: [Python-ideas] parameter omit Message-ID: <20070510231419.2DC891E4003@bag.python.org> > -----Original Message----- > From: Aaron Brady [mailto:castironpi at comcast.net] > Sent: Wednesday, May 09, 2007 5:35 PM > > Could easily incorporate, as shown here. > #sample function with default args > def f( a,b=None,c='abc' ): > print a,b,c > > #customizer > default= object() > def call_wrapper( callable, *args, **kwargs ): > args=list(args) > for i,j in enumerate( args ): > if j is default: > offset= callable.func_code.co_argcount-\ > len(callable.func_defaults) > args[i]= callable.func_defaults[i-offset] > return callable( *args,**kwargs ) > > #the uniform calls > call_wrapper( f,0,default,'def' ) > call_wrapper( f,0,'somebody',default ) > > -----Original Message----- > From: Aaron Brady [mailto:castironpi at comcast.net] > Sent: Wednesday, May 09, 2007 4:56 PM > To: 'Aaron Brady'; 'Josiah Carlson'; 'python-ideas at python.org' > Subject: RE: [Python-ideas] parameter omit > > You can almost do, > b=f.func_defaults[1], > but you still have to know where the defaults start. Very small what I'm > missing. > > -----Original Message----- > From: python-ideas-bounces at python.org > [mailto:python-ideas-bounces at python.org] On Behalf Of Aaron Brady > Sent: Wednesday, May 09, 2007 4:50 PM > To: 'Josiah Carlson'; python-ideas at python.org > Subject: Re: [Python-ideas] parameter omit > > No, still not uniform. Cases might be rare, even syntactic sugar maybe. > if something huge: > b= > more huge > if something else: > b=mything > still more > f(a,b,c). > > -----Original Message----- > From: Josiah Carlson [mailto:jcarlson at uci.edu] > Sent: Wednesday, May 09, 2007 4:51 PM > To: Aaron Brady; python-ideas at python.org > Subject: Re: [Python-ideas] parameter omit > > > "Aaron Brady" wrote: > > > > Actually, I wanted a uniform way to call f. f(a,b,c) for both cases if > b > > can equal . > > f(a, b=...) #default c > f(a, c=...) #default b > > > - Josiah > > > -----Original Message----- > > From: Steven Bethard [mailto:steven.bethard at gmail.com] > > Sent: Wednesday, May 09, 2007 3:45 PM > > To: Aaron Brady > > Cc: python-ideas at python.org > > Subject: Re: [Python-ideas] parameter omit > > > > On 5/9/07, Aaron Brady wrote: > > > Is it possible to signal to a parameter to use its default? > > > > > > def f( a, b=None, c='' ):... > > > > > > f( 123, , 'abc' ) > > > f( 123, ObjA, ) > > > > In this case, it's pretty easy:: > > > > f(123, c='abc') > > f(123, ObjA) > > > > STeVe > > -- > > I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a > > tiny blip on the distant coast of sanity. > > --- Bucky Katt, Get Fuzzy Also, any follow-up on this? (I posted at top.) From castironpi at comcast.net Fri May 11 01:23:50 2007 From: castironpi at comcast.net (Aaron Brady) Date: Thu, 10 May 2007 18:23:50 -0500 Subject: [Python-ideas] parser in stdlib In-Reply-To: <43aa6ff70705101607p266dcee3o4c79214ac0fdf937@mail.gmail.com> Message-ID: <20070510232357.9A2071E4003@bag.python.org> > -----Original Message----- > From: Collin Winter [mailto:collinw at gmail.com] > Sent: Thursday, May 10, 2007 6:08 PM > > On 5/10/07, Aaron Brady wrote: > > > -----Original Message----- > > > From: Collin Winter [mailto:collinw at gmail.com] > > > Sent: Thursday, May 10, 2007 5:57 PM > > > > > > On 5/10/07, Aaron Brady wrote: > > > > > -----Original Message----- > > > > > From: python-ideas-bounces at python.org [mailto:python-ideas- > > > > > bounces at python.org] On Behalf Of Adam Atlas > > > > > Sent: Thursday, May 10, 2007 5:47 PM > > > > > > > > > > On 10 May 2007, at 18.39, Aaron Brady wrote: > > > > > > There is, but I want access to it. > > > > > >>>> import parser > > > > > >>>> parser.__file__ > > > > > > Traceback (most recent call last): > > > > > > File "", line 1, in > > > > > > AttributeError: 'module' object has no attribute '__file__' > > > > > > > > > > That's because it's a builtin module, written in C. It's Python/ > > > > > parsermodule.c in the source distributions. > > > > > > > > > > What exactly are you suggesting should be possible? Are you trying > to > > > > > programmatically change the parser? > > > > > > > > Yes. The relevant code snippet: > > > > > > > > class Transformer: > > > > > > > > def parsesuite(self, text): > > > > """Return a modified parse tree for the given suite text.""" > > > > return self.transform(parser.suite(text)) > > > > > > > > Hence to allusion to Van Rossum's note, for the record. > > > > > > That is not and will not be possible using Python's built-in parser. > > > > > > Collin Winter > > > > I'm 25, FTR, heavy experience. > > I have no idea why that's relevant. > > > Why not? PEP or FAQ if there is one. > > Because programmable syntax isn't something we want in Python; you > yourself quoted an email from Guido explaining why. If you like the > idea of allowing every module to define its own syntactic constructs > -- at runtime or otherwise -- Perl 6, Haskell and others are more than > happy to help you. > > Collin Winter Huge bag of worms, I see now. I was tinkering for hobby Python use. I hadn't proposed a syntax change, not there yet. I was wanting to intercept parser somewhere after it's started parsing source, but before it gets to the rules. The particular change I'm tinkering with was replacing an equal sign with a natural word. 1, 2 to a, c -and- to a, c 1, 2 map to: a, c = 1, 2 Like I said, trivial, but I was hoping a small change to parser would work. (It's not always unambiguous either.) But here's the idea. From jcarlson at uci.edu Fri May 11 02:59:39 2007 From: jcarlson at uci.edu (Josiah Carlson) Date: Thu, 10 May 2007 17:59:39 -0700 Subject: [Python-ideas] parser in stdlib In-Reply-To: <20070510232357.9A2071E4003@bag.python.org> References: <43aa6ff70705101607p266dcee3o4c79214ac0fdf937@mail.gmail.com> <20070510232357.9A2071E4003@bag.python.org> Message-ID: <20070510175916.2606.JCARLSON@uci.edu> "Aaron Brady" wrote: > Huge bag of worms, I see now. I was tinkering for hobby Python use. I > hadn't proposed a syntax change, not there yet. I was wanting to intercept > parser somewhere after it's started parsing source, but before it gets to > the rules. The particular change I'm tinkering with was replacing an equal > sign with a natural word. Use Logix: http://www.livelogix.net/logix/ - Josiah From jcarlson at uci.edu Fri May 11 03:03:35 2007 From: jcarlson at uci.edu (Josiah Carlson) Date: Thu, 10 May 2007 18:03:35 -0700 Subject: [Python-ideas] parameter omit In-Reply-To: <200705102321.l4ANLgaV021115@mx3.service.uci.edu> References: <200705102321.l4ANLgaV021115@mx3.service.uci.edu> Message-ID: <20070510175956.2609.JCARLSON@uci.edu> "Aaron Brady" wrote: > Also, any follow-up on this? (I posted at top.) I don't like it. The current calling semantics are sufficient for the vast majority of cases. For those cases that are not covered by the current calling semantics, there is a PEP for allowing variations in optional arguments, keyword arguments, etc. I can't remember the number, but the PEP index has it. As for signaling "use the default", there is a standard method: omit the argument. If you want the argument to always be required to be a keyword argument, you can use... def foo(arg1, **kwargs): arg2 = kwargs.get('arg2', 1.2325) arg3 = kwargs.get('arg3', 'hello') ... - Josiah From terry at jon.es Fri May 11 03:00:32 2007 From: terry at jon.es (Terry Jones) Date: Fri, 11 May 2007 03:00:32 +0200 Subject: [Python-ideas] parser in stdlib In-Reply-To: Your message at 17:59:39 on Thursday, 10 May 2007 References: <43aa6ff70705101607p266dcee3o4c79214ac0fdf937@mail.gmail.com> <20070510232357.9A2071E4003@bag.python.org> <20070510175916.2606.JCARLSON@uci.edu> Message-ID: <17987.49200.291234.235644@terry-jones-computer.local> >>>>> "Josiah" == Josiah Carlson writes: Josiah> "Aaron Brady" wrote: >> Huge bag of worms, I see now. I was tinkering for hobby Python use. I >> hadn't proposed a syntax change, not there yet. I was wanting to intercept >> parser somewhere after it's started parsing source, but before it gets to >> the rules. The particular change I'm tinkering with was replacing an equal >> sign with a natural word. Josiah> Use Logix: http://www.livelogix.net/logix/ Use sed: http://www.gnu.org/software/sed/ :-) Terry From castironpi at comcast.net Fri May 11 04:11:40 2007 From: castironpi at comcast.net (Aaron Brady) Date: Thu, 10 May 2007 21:11:40 -0500 Subject: [Python-ideas] parameter omit In-Reply-To: <20070510175956.2609.JCARLSON@uci.edu> Message-ID: <20070511021148.F22EB1E4003@bag.python.org> > -----Original Message----- > From: Josiah Carlson [mailto:jcarlson at uci.edu] > Sent: Thursday, May 10, 2007 8:04 PM > > "Aaron Brady" wrote: > > Also, any follow-up on this? (I posted at top.) > > I don't like it. The current calling semantics are sufficient for the > vast majority of cases. For those cases that are not covered by the > current calling semantics, there is a PEP for allowing variations in > optional arguments, keyword arguments, etc. I can't remember the number, > but the PEP index has it. > > As for signaling "use the default", there is a standard method: omit the > argument. If you want the argument to always be required to be a > keyword argument, you can use... > > def foo(arg1, **kwargs): > arg2 = kwargs.get('arg2', 1.2325) > arg3 = kwargs.get('arg3', 'hello') > ... > > - Josiah I don't like it. Cobol is sufficient. Python is very cool. > def foo(arg1, **kwargs): > arg2 = kwargs.get('arg2', 1.2325) > arg3 = kwargs.get('arg3', 'hello') > ... Library functions have many parameters, and huge if statements are hard to read. My solution costs only a single built-in object, not even a keyword or syntax modification. Your solution takes a three-line function definition. Compare to mine: def foo(arg1, argFoo=1.2325, argBree='hello'): ... Specific and concise. Clearly better, by all measures I read. From jcarlson at uci.edu Fri May 11 04:35:58 2007 From: jcarlson at uci.edu (Josiah Carlson) Date: Thu, 10 May 2007 19:35:58 -0700 Subject: [Python-ideas] parameter omit In-Reply-To: <200705110211.l4B2BpRk023341@mx2.service.uci.edu> References: <20070510175956.2609.JCARLSON@uci.edu> <200705110211.l4B2BpRk023341@mx2.service.uci.edu> Message-ID: <20070510193316.260F.JCARLSON@uci.edu> "Aaron Brady" wrote: > Library functions have many parameters, and huge if statements are hard to > read. My solution costs only a single built-in object, not even a keyword > or syntax modification. Your solution takes a three-line function > definition. Compare to mine: > > def foo(arg1, argFoo=1.2325, argBree='hello'): > ... > > Specific and concise. Clearly better, by all measures I read. Except that it has no support from anyone with any pull. Feel free to wait for it, and/or keep pestering people to offer their opinions. Note that not everyone has the desire for such (arguably unnecessary) consistency as you seem to. - Josiah From castironpi at comcast.net Fri May 11 04:35:29 2007 From: castironpi at comcast.net (Aaron Brady) Date: Thu, 10 May 2007 21:35:29 -0500 Subject: [Python-ideas] parameter omit In-Reply-To: <20070510193316.260F.JCARLSON@uci.edu> Message-ID: <20070511023536.EB37C1E4003@bag.python.org> > -----Original Message----- > From: Josiah Carlson [mailto:jcarlson at uci.edu] > Sent: Thursday, May 10, 2007 9:36 PM > > > "Aaron Brady" wrote: > > Library functions have many parameters, and huge if statements are hard > to > > read. My solution costs only a single built-in object, not even a > keyword > > or syntax modification. Your solution takes a three-line function > > definition. Compare to mine: > > > > def foo(arg1, argFoo=1.2325, argBree='hello'): > > ... > > > > Specific and concise. Clearly better, by all measures I read. > > Except that it has no support from anyone with any pull. Feel free to > wait for it, and/or keep pestering people to offer their opinions. > > Note that not everyone has the desire for such (arguably unnecessary) > consistency as you seem to. > > > - Josiah Copy Houston. Have to be someone to be right. It's a good idea and I'll wait if it suits to. I'll quote Guido in the future. From castironpi at comcast.net Fri May 11 05:47:10 2007 From: castironpi at comcast.net (Aaron Brady) Date: Thu, 10 May 2007 22:47:10 -0500 Subject: [Python-ideas] parser in stdlib In-Reply-To: <91ad5bf80705102036l436e0cbewc32a2eb4b9edbabb@mail.gmail.com> Message-ID: <20070511034722.0E65F1E4003@bag.python.org> > -----Original Message----- > From: george.sakkis at gmail.com [mailto:george.sakkis at gmail.com] On Behalf > Of George Sakkis > Sent: Thursday, May 10, 2007 10:36 PM > To: Aaron Brady > Subject: Re: [Python-ideas] parser in stdlib > > On 5/10/07, Aaron Brady wrote: > > > Huge bag of worms, I see now. I was tinkering for hobby Python use. I > > hadn't proposed a syntax change, not there yet. I was wanting to > intercept > > parser somewhere after it's started parsing source, but before it gets > to > > the rules. The particular change I'm tinkering with was replacing an > equal > > sign with a natural word. > > > > 1, 2 to a, c > > -and- > > to a, c 1, 2 > > > > map to: > > > > a, c = 1, 2 > > A perfect example of why programmable syntax is out of question for > Python. > > George Hence the quote. First thing I said was, "...it might not be advisable either, subject to abuse, per GvR...." But that doesn't preclude exposing `parser'. It is the extent of my question, no more. Can we expose the module? Do I take the powers that be to have said, "No, that would open too many doors and give the programmers too much freedom?" If so, that's straight-forward and honest, and presents the next problem for solutions. Can we expose that and still keep programs up to standard? From castironpi at comcast.net Fri May 11 05:51:48 2007 From: castironpi at comcast.net (Aaron Brady) Date: Thu, 10 May 2007 22:51:48 -0500 Subject: [Python-ideas] parameter omit In-Reply-To: <20070511023536.EB37C1E4003@bag.python.org> Message-ID: <20070511035157.388981E4003@bag.python.org> > -----Original Message----- > From: python-ideas-bounces at python.org [mailto:python-ideas- > bounces at python.org] On Behalf Of Aaron Brady > Sent: Thursday, May 10, 2007 9:35 PM > To: 'Josiah Carlson'; python-ideas at python.org > Subject: Re: [Python-ideas] parameter omit > > > -----Original Message----- > > From: Josiah Carlson [mailto:jcarlson at uci.edu] > > Sent: Thursday, May 10, 2007 9:36 PM > > > > > > "Aaron Brady" wrote: > > > Library functions have many parameters, and huge if statements are > hard > > to > > > read. My solution costs only a single built-in object, not even a > > keyword > > > or syntax modification. Your solution takes a three-line function > > > definition. Compare to mine: > > > > > > def foo(arg1, argFoo=1.2325, argBree='hello'): > > > ... > > > > > > Specific and concise. Clearly better, by all measures I read. > > > > Except that it has no support from anyone with any pull. Feel free to > > wait for it, and/or keep pestering people to offer their opinions. > > > > Note that not everyone has the desire for such (arguably unnecessary) > > consistency as you seem to. > > > > > > - Josiah > > Copy Houston. Have to be someone to be right. It's a good idea and I'll > wait if it suits to. I'll quote Guido in the future. To finish up, I, the newcomer, have a solution that encompasses more situations at very small cost. No compatibility issues either. What should I expect? From tjreedy at udel.edu Fri May 11 06:02:22 2007 From: tjreedy at udel.edu (Terry Reedy) Date: Fri, 11 May 2007 00:02:22 -0400 Subject: [Python-ideas] parser in stdlib References: <194B3690-3D8F-4D45-9D07-D1E537F292EF@atlas.st><20070510225036.52FA81E400C@bag.python.org> <43aa6ff70705101556q5ec76666geb7984978ceef3b1@mail.gmail.com> Message-ID: "Collin Winter" | That is not and will not be possible using Python's built-in parser. One can manipulate the AST that the parser produces. (This is how the 2to3 converter tool will work.) Perhaps this will at least partially meet the OP's needs. Beats head-butting a wall. tjr From jcarlson at uci.edu Fri May 11 06:26:50 2007 From: jcarlson at uci.edu (Josiah Carlson) Date: Thu, 10 May 2007 21:26:50 -0700 Subject: [Python-ideas] parameter omit In-Reply-To: <200705110245.l4B2jeYq008970@mx1.service.uci.edu> References: <20070510193316.260F.JCARLSON@uci.edu> <200705110245.l4B2jeYq008970@mx1.service.uci.edu> Message-ID: <20070510205525.2612.JCARLSON@uci.edu> Adding python-ideas in as a CC, because I'm a jerk. "Aaron Brady" wrote: > On a personal note, Josiah, you strike first. "Pestering" is pejorative. > My statements do not merit it. Keep it off the newsgroup. You insult me > without grounds; and in fact -after- my abilities are demonstrated. Quote > me instead, as I do, to disagree. > > The discussion reads as follows. "Better except that it has no support." > So support it. Who's to blame: myself, or those with pull? > > I have a good idea by newsgroup standards. You reveal bias to summarily > dismiss. I urge you to reconsider; practice diplomacy here. Post what you want. If people aren't offering +1 or -1, it could be for any number of reasons; from being busy (it is in the middle of the week), to just not caring enough either way, believing that their opinions and interests are already being expressed, etc. But when you post something, then 24 hours and 40 minutes later you ask, "Also, any follow-up on this? (I posted at top.)" at the bottom of a 95 line quote of your own last post without cutting out the unimportant parts, it is pestering, and a very low signal to noise ratio 1:95. Never mind that you only recently seemed to learn that we don't top post in Python mailing lists, but you still haven't realized that we trim unimportant parts of quoted posts. Had you top posted or failed to trim either in python-list (or the equivalent comp.lang.python), any number of people would have told you as much. But hey, you are being such the good usenet poster, you couldn't have made a mistake, of course not. Get over yourself. With that said, I don't particularly like the addition of syntax for something that can already be done other ways (TOOWTDI), or the addition of a new builtin to signal something that I've never heard *anyone* ask about before. Really, the only *reasonable* name is 'default', which is used at least 146 times in the Python standard library (according to my regular expression of default\s*=), and I'm sure thousands of times in 3rd party code. It would necessitate a huge change for a feature that no one (but you) as asked for so that you can use... foo(a, b=default, c=1234) foo(a, b=253463, c=default) rather than... foo(a, c=1234) foo(a, b=253463) Personally, I find the latter more consistant (only pass arguments that you care to change). If you don't, that's fine. The burdon of proof isn't on me, or anyone else in python-ideas to prove to you that your idea sucks; it's on you to prove to everyone else that your idea *doesn't* suck. Good luck on that. Local jerk, - Josiah From castironpi at comcast.net Fri May 11 06:25:11 2007 From: castironpi at comcast.net (Aaron Brady) Date: Thu, 10 May 2007 23:25:11 -0500 Subject: [Python-ideas] parser in stdlib In-Reply-To: Message-ID: <20070511042520.19A5E1E4003@bag.python.org> > -----Original Message----- > From: python-ideas-bounces at python.org [mailto:python-ideas- > bounces at python.org] On Behalf Of Terry Reedy > Sent: Thursday, May 10, 2007 11:02 PM > > "Collin Winter" | That is > not and will not be possible using Python's built-in parser. > > One can manipulate the AST that the parser produces. (This is how the > 2to3 > converter tool will work.) Perhaps this will at least partially meet the > OP's needs. Beats head-butting a wall. > > tjr I've very much looked into it. In fact, it gave rise to the follow-up idea of attaching a `firstlineno' attribute to class objects. (18:12 American Central Time.) Rather costly, 50% of the attributes, but stepping through the InteractiveCodeGenerator class hasn't failed yet. From gsakkis at rutgers.edu Fri May 11 06:26:13 2007 From: gsakkis at rutgers.edu (George Sakkis) Date: Fri, 11 May 2007 00:26:13 -0400 Subject: [Python-ideas] parser in stdlib In-Reply-To: <20070511034722.0E65F1E4003@bag.python.org> References: <91ad5bf80705102036l436e0cbewc32a2eb4b9edbabb@mail.gmail.com> <20070511034722.0E65F1E4003@bag.python.org> Message-ID: <91ad5bf80705102126we788898i4211797869e80192@mail.gmail.com> On 5/10/07, Aaron Brady wrote: > > -----Original Message----- > > From: george.sakkis at gmail.com [mailto:george.sakkis at gmail.com] On Behalf > > Of George Sakkis > > Sent: Thursday, May 10, 2007 10:36 PM > > To: Aaron Brady > > Subject: Re: [Python-ideas] parser in stdlib > > > > On 5/10/07, Aaron Brady wrote: > > > > > Huge bag of worms, I see now. I was tinkering for hobby Python use. I > > > hadn't proposed a syntax change, not there yet. I was wanting to > > intercept > > > parser somewhere after it's started parsing source, but before it gets > > to > > > the rules. The particular change I'm tinkering with was replacing an > > equal > > > sign with a natural word. > > > > > > 1, 2 to a, c > > > -and- > > > to a, c 1, 2 > > > > > > map to: > > > > > > a, c = 1, 2 > > > > A perfect example of why programmable syntax is out of question for > > Python. > > > > George > > Hence the quote. First thing I said was, "...it might not be advisable > either, subject to abuse, per GvR...." > > But that doesn't preclude exposing `parser'. It is the extent of my > question, no more. Can we expose the module? > > Do I take the powers that be to have said, "No, that would open too many > doors and give the programmers too much freedom?" If so, that's > straight-forward and honest, and presents the next problem for solutions. > Can we expose that and still keep programs up to standard? There is no universally accepted answer to this question. Each language positions itself (deliberately or by accident) somewhere in the spectrum between total bondage and total freedom. Static typing proponents find that dynamic typing is already "too much freedom", let alone programmable syntax. Those that don't believe there is such a thing as "too much freedom" tend to climb their way up in the language ecosystem, until they discover Lisp and reach nirvana. Python keeps a happy medium by accepting that programmers are neither clueless drones that need a static compiler to babysit them all the time, nor omnipotent gods; they are just humans. George -- "If I have been able to see further, it was only because I stood on the shoulders of million monkeys." From jcarlson at uci.edu Fri May 11 06:37:02 2007 From: jcarlson at uci.edu (Josiah Carlson) Date: Thu, 10 May 2007 21:37:02 -0700 Subject: [Python-ideas] parameter omit In-Reply-To: <200705110352.l4B3q3ta004354@mx1.service.uci.edu> References: <20070511023536.EB37C1E4003@bag.python.org> <200705110352.l4B3q3ta004354@mx1.service.uci.edu> Message-ID: <20070510212720.2615.JCARLSON@uci.edu> "Aaron Brady" wrote: > To finish up, I, the newcomer, have a solution that encompasses more > situations at very small cost. No compatibility issues either. What should > I expect? Is this the same idea or something different? If it's the same, wait a few days for responses. If it is something different, post the current situation, what's wrong with the current situation, and what you think would be better. When people disagree with you (there is always at least one :) ), don't reply with "but that doesn't do *exactly* what I want". Instead understand that no matter how much you post, no matter how much people like your idea, no matter how much Guido likes your idea, or even if you have a working implementation, it can be tossed in the trash (see the February "New syntax for 'dynamic' attribute access" postings here and the related python-dev thread for an example). - Josiah From castironpi at comcast.net Fri May 11 06:55:52 2007 From: castironpi at comcast.net (Aaron Brady) Date: Thu, 10 May 2007 23:55:52 -0500 Subject: [Python-ideas] parameter omit In-Reply-To: <20070510205525.2612.JCARLSON@uci.edu> Message-ID: <20070511045600.95C791E4003@bag.python.org> > -----Original Message----- > From: Josiah Carlson [mailto:jcarlson at uci.edu] > Sent: Thursday, May 10, 2007 11:27 PM > > "Aaron Brady" wrote: > > Post what you want. If people aren't offering +1 or -1, it could be for > any number of reasons; from being busy (it is in the middle of the week), > to just not caring enough either way, believing that their opinions and > interests are already being expressed, etc. > > But when you post something, then 24 hours and 40 minutes later you ask, > "Also, any follow-up on this? (I posted at top.)" at the bottom of a 95 > line quote of your own last post without cutting out the unimportant > parts, it is pestering, and a very low signal to noise ratio 1:95. Never > mind that you only recently seemed to learn that we don't top post in > Python mailing lists, but you still haven't realized that we trim > unimportant parts of quoted posts. Had you top posted or failed to trim > either in python-list (or the equivalent comp.lang.python), any number > of people would have told you as much. > > But hey, you are being such the good usenet poster, you couldn't have > made a mistake, of course not. Get over yourself. > > > With that said, I don't particularly like the addition of syntax for > something that can already be done other ways (TOOWTDI), or the addition > of a new builtin to signal something that I've never heard *anyone* ask > about before. Really, the only *reasonable* name is 'default', which is > used at least 146 times in the Python standard library (according to my > regular expression of default\s*=), and I'm sure thousands of times in 3rd > party code. It would necessitate a huge change for a feature that no > one (but you) as asked for so that you can use... > > foo(a, b=default, c=1234) > foo(a, b=253463, c=default) > > rather than... > > foo(a, c=1234) > foo(a, b=253463) > > Personally, I find the latter more consistant (only pass arguments that > you care to change). If you don't, that's fine. The burdon of proof > isn't on me, or anyone else in python-ideas to prove to you that your > idea sucks; it's on you to prove to everyone else that your idea > *doesn't* suck. Good luck on that. > > Local jerk, > - Josiah Correct, signal to noise, content to form. My idea came in a slightly unconventional format. Not posting in Hebrew or something. Besides, that problem cleared itself up on its own. I noticed I wasn't blending in. Within a full 24 hours, I expect an, "I like this, may be good. Here's my personal e-mail address, get back to me in a week if you haven't heard anything." No elaboration is necessary at this point. It only takes one day to write this. But that's just where I come from. So instead, I pursue and follow-up on my own initiative. Does need a reply of some sort or another. Lastly, most importantly, you misunderstand the issue. The example says it all, but I'm willing to explain, just for the asking. Don't misquote me, but the trade-off follows. Three-line function definition [Carlson 19:59 American Central Time] versus one. More than three lines if you have more than three parameters: one line per parameter. Cobol is another way to do it, so be careful with acronyms. No new syntax in this one. The old ways: [code to assign my_b and my_c] if use_default_b and use_defualt_c: foo(a) elif use_default_b: foo(a, c=my_c) elif use_default_c: foo(a, my_b) -or- def foo(arg1, **kwargs): arg2 = kwargs.get('arg2', 1.2325) arg3 = kwargs.get('arg3', 'hello') The new way: my_b, my_c= paramdefault, paramdefault [code to assign my_b and my_c] foo(a, my_b, my_c) And don't get me started on `d'. ParamDefault is like True, False, and None. Not traditional, in truth, Pythonic. Looking far into the future, however, I suppose it could start to get abused, like putting None in dictionaries, for example. Perhaps it was None's original intent. Fellow jerk, - Aaron [p.s. { 'akey': ParamDefault }, ha] From steven.bethard at gmail.com Fri May 11 07:13:24 2007 From: steven.bethard at gmail.com (Steven Bethard) Date: Thu, 10 May 2007 23:13:24 -0600 Subject: [Python-ideas] parameter omit In-Reply-To: <20070511045600.95C791E4003@bag.python.org> References: <20070510205525.2612.JCARLSON@uci.edu> <20070511045600.95C791E4003@bag.python.org> Message-ID: On 5/10/07, Aaron Brady wrote: > The old ways: > > [code to assign my_b and my_c] > if use_default_b and use_defualt_c: > foo(a) > elif use_default_b: > foo(a, c=my_c) > elif use_default_c: > foo(a, my_b) [snip] > The new way: > > my_b, my_c= paramdefault, paramdefault > [code to assign my_b and my_c] > foo(a, my_b, my_c) As another poster mentioned, the normal way to write this is:: kwargs = {} if use_default_b: kwargs['b'] = my_b if use_default_c: kwargs['c'] = my_c foo(a, **kwargs) It is so extremely uncommon to need to do such a thing that I'm firmly against adding any additional syntax. Syntax should only be introduced for common things that many people need. STeVe -- I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a tiny blip on the distant coast of sanity. --- Bucky Katt, Get Fuzzy From castironpi at comcast.net Fri May 11 07:22:55 2007 From: castironpi at comcast.net (Aaron Brady) Date: Fri, 11 May 2007 00:22:55 -0500 Subject: [Python-ideas] parameter omit In-Reply-To: Message-ID: <20070511052310.1F2B71E4003@bag.python.org> > -----Original Message----- > From: Steven Bethard [mailto:steven.bethard at gmail.com] > Sent: Friday, May 11, 2007 12:13 AM > > On 5/10/07, Aaron Brady wrote: > > The old ways: > > > > [code to assign my_b and my_c] > > if use_default_b and use_defualt_c: > > foo(a) > > elif use_default_b: > > foo(a, c=my_c) > > elif use_default_c: > > foo(a, my_b) > [snip] > > The new way: > > > > my_b, my_c= paramdefault, paramdefault > > [code to assign my_b and my_c] > > foo(a, my_b, my_c) > > As another poster mentioned, the normal way to write this is:: > > kwargs = {} > if use_default_b: > kwargs['b'] = my_b > if use_default_c: > kwargs['c'] = my_c > foo(a, **kwargs) > > It is so extremely uncommon to need to do such a thing that I'm firmly > against adding any additional syntax. Syntax should only be introduced > for common things that many people need. > > STeVe Mr. Bethard, I am not adding syntax. Don't put words in my mouth. This is another one- observe the subject line. Tell me you always make a call with the same parameters, every time you make the call. My thinking can't be that backwards. A use case could take some time, but sure. > > Cobol is another way to do it, so be careful with acronyms. > > No new syntax in this one. > > > > The old ways: ... From talin at acm.org Fri May 11 07:38:39 2007 From: talin at acm.org (Talin) Date: Thu, 10 May 2007 22:38:39 -0700 Subject: [Python-ideas] parameter omit In-Reply-To: <20070511021148.F22EB1E4003@bag.python.org> References: <20070511021148.F22EB1E4003@bag.python.org> Message-ID: <4644015F.80100@acm.org> Aaron Brady wrote: >> -----Original Message----- >> From: Josiah Carlson [mailto:jcarlson at uci.edu] >> Sent: Thursday, May 10, 2007 8:04 PM >> >> "Aaron Brady" wrote: >>> Also, any follow-up on this? (I posted at top.) >> I don't like it. The current calling semantics are sufficient for the >> vast majority of cases. For those cases that are not covered by the >> current calling semantics, there is a PEP for allowing variations in >> optional arguments, keyword arguments, etc. I can't remember the number, >> but the PEP index has it. >> >> As for signaling "use the default", there is a standard method: omit the >> argument. If you want the argument to always be required to be a >> keyword argument, you can use... >> >> def foo(arg1, **kwargs): >> arg2 = kwargs.get('arg2', 1.2325) >> arg3 = kwargs.get('arg3', 'hello') >> ... >> >> - Josiah > > I don't like it. Cobol is sufficient. Python is very cool. > >> def foo(arg1, **kwargs): >> arg2 = kwargs.get('arg2', 1.2325) >> arg3 = kwargs.get('arg3', 'hello') >> ... > > Library functions have many parameters, and huge if statements are hard to > read. My solution costs only a single built-in object, not even a keyword > or syntax modification. Your solution takes a three-line function > definition. Compare to mine: > > def foo(arg1, argFoo=1.2325, argBree='hello'): > ... > > Specific and concise. Clearly better, by all measures I read. With PEP 3102 in place you don't even need the **kwargs: http://www.python.org/dev/peps/pep-3102/ -- Talin From steven.bethard at gmail.com Fri May 11 07:41:51 2007 From: steven.bethard at gmail.com (Steven Bethard) Date: Thu, 10 May 2007 23:41:51 -0600 Subject: [Python-ideas] parameter omit In-Reply-To: <4643fdbb.6d47eccd.14ef.ffffbc16SMTPIN_ADDED@mx.google.com> References: <4643fdbb.6d47eccd.14ef.ffffbc16SMTPIN_ADDED@mx.google.com> Message-ID: On 5/10/07, Aaron Brady wrote: > From: Steven Bethard [mailto:steven.bethard at gmail.com] > > On 5/10/07, Aaron Brady wrote: > > > The new way: > > > > > > my_b, my_c= paramdefault, paramdefault > > > [code to assign my_b and my_c] > > > foo(a, my_b, my_c) [snip] > > It is so extremely uncommon to need to do such a thing that I'm firmly > > against adding any additional syntax. Syntax should only be introduced > > for common things that many people need. > > Mr. Bethard, I am not adding syntax. Don't put words in my mouth. This is > another one- observe the subject line. Tell me you always make a call with > the same parameters, every time you make the call. My thinking can't be > that backwards. A use case could take some time, but sure. Hmm... If ``paramdefault`` isn't syntax, then how are you proposing to implement it? STeVe -- I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a tiny blip on the distant coast of sanity. --- Bucky Katt, Get Fuzzy From castironpi at comcast.net Fri May 11 07:51:32 2007 From: castironpi at comcast.net (Aaron Brady) Date: Fri, 11 May 2007 00:51:32 -0500 Subject: [Python-ideas] parameter omit In-Reply-To: <4644015F.80100@acm.org> Message-ID: <20070511055143.091031E4003@bag.python.org> > -----Original Message----- > From: Talin [mailto:talin at acm.org] > Sent: Friday, May 11, 2007 12:39 AM > > Aaron Brady wrote: > >> -----Original Message----- > >> From: Josiah Carlson [mailto:jcarlson at uci.edu] > >> Sent: Thursday, May 10, 2007 8:04 PM > >> > >> "Aaron Brady" wrote: > >> [snip] > > I don't like it. Cobol is sufficient. Python is very cool. > > > >> def foo(arg1, **kwargs): > >> arg2 = kwargs.get('arg2', 1.2325) > >> arg3 = kwargs.get('arg3', 'hello') > >> ... > > > > Library functions have many parameters, and huge if statements are hard > to > > read. My solution costs only a single built-in object, not even a > keyword > > or syntax modification. Your solution takes a three-line function > > definition. Compare to mine: > > > > def foo(arg1, argFoo=1.2325, argBree='hello'): > > ... > > > > Specific and concise. Clearly better, by all measures I read. > > With PEP 3102 in place you don't even need the **kwargs: > > http://www.python.org/dev/peps/pep-3102/ > > -- Talin I'm not adding restrictions. I'm simplifying. The subject solution is general. Less code in all cases, meaning still as clear or clearer. From castironpi at comcast.net Fri May 11 07:59:16 2007 From: castironpi at comcast.net (Aaron Brady) Date: Fri, 11 May 2007 00:59:16 -0500 Subject: [Python-ideas] parser in stdlib In-Reply-To: <91ad5bf80705102126we788898i4211797869e80192@mail.gmail.com> Message-ID: <20070511055925.77C861E4003@bag.python.org> > -----Original Message----- > From: python-ideas-bounces at python.org [mailto:python-ideas- > bounces at python.org] On Behalf Of George Sakkis > Sent: Thursday, May 10, 2007 11:26 PM > > On 5/10/07, Aaron Brady wrote: > > > > -----Original Message----- > > > From: george.sakkis at gmail.com [mailto:george.sakkis at gmail.com] On > Behalf > > > Of George Sakkis > > > Sent: Thursday, May 10, 2007 10:36 PM > > > To: Aaron Brady > > > Subject: Re: [Python-ideas] parser in stdlib > > > > > > On 5/10/07, Aaron Brady wrote: > > > > > > > [snip] > > > A perfect example of why programmable syntax is out of question for > > > Python. > > > > > > George > > > > Hence the quote. First thing I said was, "...it might not be advisable > > either, subject to abuse, per GvR...." > > > > But that doesn't preclude exposing `parser'. It is the extent of my > > question, no more. Can we expose the module? > > > > Do I take the powers that be to have said, "No, that would open too many > > doors and give the programmers too much freedom?" If so, that's > > straight-forward and honest, and presents the next problem for > solutions. > > Can we expose that and still keep programs up to standard? > > There is no universally accepted answer to this question. Each > language positions itself (deliberately or by accident) somewhere in > the spectrum between total bondage and total freedom. Static typing > proponents find that dynamic typing is already "too much freedom", let > alone programmable syntax. Those that don't believe there is such a > thing as "too much freedom" tend to climb their way up in the language > ecosystem, until they discover Lisp and reach nirvana. Python keeps a > happy medium by accepting that programmers are neither clueless drones > that need a static compiler to babysit them all the time, nor > omnipotent gods; they are just humans. > > George You mean static like ML? Python's very acceptable. It's why I continue to choose it (and Logix does!). Free form yet structured. It strikes very good balances. The problem is, white-space doesn't mean anything. I addressed M. Santagada about it. I was trying to, but hit the absence of parser. So what do we make it mean? Can't do this: if exists fname... Because of that: loptosize self.graphic They must both map to: if fname.exists() #wrong and self.graphic.loptosize() -or- if exists( fname ) and loptosize( self.graphic ) #wrong instead I'm shooting for: if exists( fname ) and self.graphic.loptosize() Can't have both. Possibilities, silliest first: - Rule that functions that end in `s' are predicates not imperatives (-is- this not -do- this). No. - Rule that functions in Boolean expressions are the former form, and otherwise the latter. It sort of works, but unfortunately, loptosize() might return a value, and you get: if loptosize self.graphic: -mapping to- if loptosize( self.graphic ), which is not what you mean. - Only permit mapping on one, not both. if fname exists: -map to- if exists( fname ): -or- loptosize self.graphic -map to- self.graphic.loptosize() In other words, take whitespace to mean -either- membership retrievals -or- global function references; and don't permit the other. Last but not least, - Actively check which interpretation is "valid," and if uniquely determined, use that. This takes us well past the realm of syntax, however, into semantics. (Language does too, after all.) In the case where fname has an exists() attribute -and- the user does `from os.path import exist', raise an AmbiguityException at run-time. The fully-qualified call is still available to writer; this is an optional change of scenery, good for the eyes and fingers. Don't use it if it's ambiguous. Don't use it if you have too much to keep track of, either. Even still, we need not delay evaluation until run-time completely. Rather, parse to AmbiguousStmt( Tok1, Tok2 ), check for colliding tokens later, and have both FuncCall objects ready in bytecode. While languages move away from ambiguity [1], let's meet them half way and begin to accomodate it. It's what we speak. acb [1] The Lojban language. http://www.lojban.org/tiki/tiki-index.php?page=Home+Page&bl From talin at acm.org Fri May 11 08:24:32 2007 From: talin at acm.org (Talin) Date: Thu, 10 May 2007 23:24:32 -0700 Subject: [Python-ideas] parameter omit In-Reply-To: References: Message-ID: <46440C20.2010101@acm.org> Aaron Brady wrote: >>> Specific and concise. Clearly better, by all measures I read. >> With PEP 3102 in place you don't even need the **kwargs: >> >> http://www.python.org/dev/peps/pep-3102/ >> >> -- Talin > > I'm not adding restrictions. I'm simplifying. The subject solution is > general. Less code in all cases, meaning still as clear or clearer. Non-sequitur? How does that relate to what I said? Let me state in different words what others have already stated: There are already ways to accomplish most what you are trying to do. In Python, any argument will have its default value if you omit it from the argument list when calling the function. There's no need to explicitly tell it to use the default value, it just does this naturally. Now, the only case where this might be a problem is a fairly rare and odd case where you are specifying arguments positionally and not by keyword, where you want to specify the value of argument N+1 but want argument N to be its default. But the language should not make a special cases to support this particular case, for 3 reasons: 1) The case is rare. 2) There are easy ways around it: Simply supply the value of argument N+1 by keyword instead of by position. 3) If your function has lots of positional arguments, each of which has a different meaning, then your function probably needs to be refactored anyway. Using keywords is much safer in such cases, and if you use keywords, then the whole problem you raise goes away. -- Talin From castironpi at comcast.net Fri May 11 08:28:59 2007 From: castironpi at comcast.net (Aaron Brady) Date: Fri, 11 May 2007 01:28:59 -0500 Subject: [Python-ideas] parameter omit In-Reply-To: <20070511052310.1F2B71E4003@bag.python.org> Message-ID: <20070511062909.7D1A01E4003@bag.python.org> > -----Original Message----- > From: python-ideas-bounces at python.org [mailto:python-ideas- > bounces at python.org] On Behalf Of Aaron Brady > Sent: Friday, May 11, 2007 12:23 AM > > > -----Original Message----- > > From: Steven Bethard [mailto:steven.bethard at gmail.com] > > Sent: Friday, May 11, 2007 12:13 AM > > > > On 5/10/07, Aaron Brady wrote: > > [snip] > > > The new way: > > > > > > my_b, my_c= paramdefault, paramdefault > > > [code to assign my_b and my_c] > > > foo(a, my_b, my_c) > > > > As another poster mentioned, the normal way to write this is:: > > > > kwargs = {} > > if use_default_b: > > kwargs['b'] = my_b > > if use_default_c: > > kwargs['c'] = my_c > > foo(a, **kwargs) > > > > It is so extremely uncommon to need to do such a thing that I'm firmly > > against adding any additional syntax. Syntax should only be introduced > > for common things that many people need. > > > > STeVe Steve, Take a shot at this one. class WebRetrieveElement: def netretrieveOld( self ): if hasattr( self,'hook' ) and self.filename: urlretrieve( self.url, self.filename, self.hook ) elif hashook: urlretrieve( self.url, reporthook= self.hook ) else: urlretrieve( self.url, self.filename ) def netretrieveNew( self ): filename= self.filename or ParamDefault hook= hasattr( self,'hook' ) and self.hook or ParamDefault urlretrieve( self.url, filename, hook ) What is the default parameter for the function? Problem is, the docs don't say what it is. Does it pick its own filename to use for empty inputs? From castironpi at comcast.net Fri May 11 08:33:25 2007 From: castironpi at comcast.net (Aaron Brady) Date: Fri, 11 May 2007 01:33:25 -0500 Subject: [Python-ideas] parameter omit In-Reply-To: <46440C20.2010101@acm.org> Message-ID: <20070511063334.68C741E4003@bag.python.org> > -----Original Message----- > From: Talin [mailto:talin at acm.org] > Sent: Friday, May 11, 2007 1:25 AM > > Aaron Brady wrote: > [snip] > Non-sequitur? How does that relate to what I said? > > Let me state in different words what others have already stated: There > are already ways to accomplish most what you are trying to do. > > In Python, any argument will have its default value if you omit it from > the argument list when calling the function. There's no need to > explicitly tell it to use the default value, it just does this naturally. > > Now, the only case where this might be a problem is a fairly rare and > odd case where you are specifying arguments positionally and not by > keyword, where you want to specify the value of argument N+1 but want > argument N to be its default. > > But the language should not make a special cases to support this > particular case, for 3 reasons: > > 1) The case is rare. > > 2) There are easy ways around it: Simply supply the value of argument > N+1 by keyword instead of by position. > > 3) If your function has lots of positional arguments, each of which has > a different meaning, then your function probably needs to be refactored > anyway. Using keywords is much safer in such cases, and if you use > keywords, then the whole problem you raise goes away. > > -- Talin Alert me if my post [Brady 01:25 U.S. Central] doesn't illuminate your concerns, and I will treat them. From jcarlson at uci.edu Fri May 11 08:46:27 2007 From: jcarlson at uci.edu (Josiah Carlson) Date: Thu, 10 May 2007 23:46:27 -0700 Subject: [Python-ideas] parameter omit In-Reply-To: <20070511062909.7D1A01E4003@bag.python.org> References: <20070511052310.1F2B71E4003@bag.python.org> <20070511062909.7D1A01E4003@bag.python.org> Message-ID: <20070510234449.2618.JCARLSON@uci.edu> "Aaron Brady" wrote: > What is the default parameter for the function? Problem is, the docs don't > say what it is. Does it pick its own filename to use for empty inputs? >>> import urllib >>> help(urllib.urlretrieve) Help on function urlretrieve in module urllib: urlretrieve(url, filename=None, reporthook=None, data=None) >>> - Josiah From castironpi at comcast.net Fri May 11 08:46:14 2007 From: castironpi at comcast.net (Aaron Brady) Date: Fri, 11 May 2007 01:46:14 -0500 Subject: [Python-ideas] parameter omit In-Reply-To: <20070510234449.2618.JCARLSON@uci.edu> Message-ID: <20070511064622.D8FA51E4003@bag.python.org> > -----Original Message----- > From: Josiah Carlson [mailto:jcarlson at uci.edu] > Sent: Friday, May 11, 2007 1:46 AM > To: Aaron Brady; python-ideas at python.org > Subject: Re: [Python-ideas] parameter omit > > > "Aaron Brady" wrote: > > What is the default parameter for the function? Problem is, the docs > don't > > say what it is. Does it pick its own filename to use for empty inputs? > > >>> import urllib > >>> help(urllib.urlretrieve) > Help on function urlretrieve in module urllib: > > urlretrieve(url, filename=None, reporthook=None, data=None) > > >>> > > > - Josiah No nitpicking, Mr. Carlson. These pieces of information are -not- always available. From steven.bethard at gmail.com Fri May 11 08:50:08 2007 From: steven.bethard at gmail.com (Steven Bethard) Date: Fri, 11 May 2007 00:50:08 -0600 Subject: [Python-ideas] parameter omit In-Reply-To: <46440d38.4521e763.55c9.4ab6SMTPIN_ADDED@mx.google.com> References: <20070511052310.1F2B71E4003@bag.python.org> <46440d38.4521e763.55c9.4ab6SMTPIN_ADDED@mx.google.com> Message-ID: On 5/11/07, Aaron Brady wrote: > Take a shot at this one. > > class WebRetrieveElement: > def netretrieveOld( self ): > if hasattr( self,'hook' ) and self.filename: > urlretrieve( self.url, self.filename, self.hook ) > elif hashook: > urlretrieve( self.url, reporthook= self.hook ) > else: > urlretrieve( self.url, self.filename ) def netretrieve(self): kwargs = {} if self.filename: kwargs['filename'] = self.filename if hasattr(self, 'hook'): kwargs['reporthook'] = self.hook urlretrieve(self.url, **kwargs) STeVe -- I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a tiny blip on the distant coast of sanity. --- Bucky Katt, Get Fuzzy From castironpi at comcast.net Fri May 11 08:57:43 2007 From: castironpi at comcast.net (Aaron Brady) Date: Fri, 11 May 2007 01:57:43 -0500 Subject: [Python-ideas] parameter omit In-Reply-To: Message-ID: <20070511065752.6C9B71E4003@bag.python.org> > -----Original Message----- > From: Steven Bethard [mailto:steven.bethard at gmail.com] > Sent: Friday, May 11, 2007 1:50 AM > > On 5/11/07, Aaron Brady wrote: > > Take a shot at this one. > > > > class WebRetrieveElement: > > def netretrieveOld( self ): > > if hasattr( self,'hook' ) and self.filename: > > urlretrieve( self.url, self.filename, self.hook > ) > > elif hashook: > > urlretrieve( self.url, reporthook= self.hook ) > > else: > > urlretrieve( self.url, self.filename ) > > def netretrieve(self): > kwargs = {} > if self.filename: > kwargs['filename'] = self.filename > if hasattr(self, 'hook'): > kwargs['reporthook'] = self.hook > urlretrieve(self.url, **kwargs) Right. That's the alternative, -as- I keep bringing up. Now let's compare, and judge if X is worth Y. My solution, 3 lines. Yours, 6. X = 50% profit, -plus- the attention you save. Y = a built-in, unobtrusive variable, a trivial cost. `None' doesn't get in your way, does it? As you can see, X -is- worth Y. Therefore, my proposal is better. From steven.bethard at gmail.com Fri May 11 09:06:23 2007 From: steven.bethard at gmail.com (Steven Bethard) Date: Fri, 11 May 2007 01:06:23 -0600 Subject: [Python-ideas] parameter omit In-Reply-To: <46441517.798dd6a1.4277.5638SMTPIN_ADDED@mx.google.com> References: <46441517.798dd6a1.4277.5638SMTPIN_ADDED@mx.google.com> Message-ID: Steven Bethard [mailto:steven.bethard at gmail.com] > Can you show me code that would make your new "morpheme" work? All > the implementations I can imagine involve making it some sort of > special keyword. On 5/11/07, Aaron Brady wrote: > Nope, routine object. I defined it earlier: > > paramdefault= object() Yes, but how is it going to *work*? Say I wrote the function:: def foo(bar=1, baz=2): print bar, baz Now if I call that like:: foo(bar=paramdefault, baz=paramdefault) I'm going to see something like:: Is that really what you want? I thought you wanted this to work for all functions... STeve -- I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a tiny blip on the distant coast of sanity. --- Bucky Katt, Get Fuzzy From steven.bethard at gmail.com Fri May 11 09:11:01 2007 From: steven.bethard at gmail.com (Steven Bethard) Date: Fri, 11 May 2007 01:11:01 -0600 Subject: [Python-ideas] parameter omit In-Reply-To: <464413ef.4faba5d4.7bd2.1544SMTPIN_ADDED@mx.google.com> References: <464413ef.4faba5d4.7bd2.1544SMTPIN_ADDED@mx.google.com> Message-ID: On 5/11/07, Aaron Brady wrote: > > -----Original Message----- > > From: Steven Bethard [mailto:steven.bethard at gmail.com] > > Sent: Friday, May 11, 2007 1:50 AM > > > > On 5/11/07, Aaron Brady wrote: > > > Take a shot at this one. > > > > > > class WebRetrieveElement: > > > def netretrieveOld( self ): > > > if hasattr( self,'hook' ) and self.filename: > > > urlretrieve( self.url, self.filename, self.hook > > ) > > > elif hashook: > > > urlretrieve( self.url, reporthook= self.hook ) > > > else: > > > urlretrieve( self.url, self.filename ) > > > > def netretrieve(self): > > kwargs = {} > > if self.filename: > > kwargs['filename'] = self.filename > > if hasattr(self, 'hook'): > > kwargs['reporthook'] = self.hook > > urlretrieve(self.url, **kwargs) > > Right. That's the alternative, -as- I keep bringing up. > > Now let's compare, and judge if X is worth Y. > > My solution, 3 lines. Yours, 6. If you really care about lines and characters, you can write:: k = {} if self.filename: k['filename'] = self.filename if hasattr(self, 'hook'): k['reporthook'] = self.hook urlretrieve(self.url, **k) That's 4 lines, 132 characters, compared to your 3 lines, 133 characters. But the fact that you're drawing the "lets count lines of code" card suggests that there's no point discussing this any further. Good luck with your proposal. STeVe -- I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a tiny blip on the distant coast of sanity. --- Bucky Katt, Get Fuzzy From castironpi at comcast.net Fri May 11 09:15:37 2007 From: castironpi at comcast.net (Aaron Brady) Date: Fri, 11 May 2007 02:15:37 -0500 Subject: [Python-ideas] parameter omit In-Reply-To: Message-ID: <20070511071546.76D421E4003@bag.python.org> > -----Original Message----- > From: Steven Bethard [mailto:steven.bethard at gmail.com] > Sent: Friday, May 11, 2007 2:06 AM > > Steven Bethard [mailto:steven.bethard at gmail.com] > > Can you show me code that would make your new "morpheme" work? All > > the implementations I can imagine involve making it some sort of > > special keyword. > > On 5/11/07, Aaron Brady wrote: > > Nope, routine object. I defined it earlier: > > > > paramdefault= object() > > Yes, but how is it going to *work*? Say I wrote the function:: > > def foo(bar=1, baz=2): > print bar, baz > > Now if I call that like:: > > foo(bar=paramdefault, baz=paramdefault) > > I'm going to see something like:: > > > > Is that really what you want? I thought you wanted this to work for > all functions... > > STeve You want to see the worked example again. Voila. def f( a,b=None,c='abc' ): print a,b,c default= object() def call_wrapper( callable, *args, **kwargs ): args=list(args) for i,j in enumerate( args ): if j is default: offset= callable.func_code.co_argcount-\ len(callable.func_defaults) args[i]= callable.func_defaults[i-offset] return callable( *args,**kwargs ) call_wrapper( f,0,default,'def' ) call_wrapper( f,0,'somebody',default ) #and output is: 0 None def 0 somebody abc From castironpi at comcast.net Fri May 11 09:16:46 2007 From: castironpi at comcast.net (Aaron Brady) Date: Fri, 11 May 2007 02:16:46 -0500 Subject: [Python-ideas] parameter omit In-Reply-To: Message-ID: <20070511071654.969D81E4003@bag.python.org> > -----Original Message----- > From: Steven Bethard [mailto:steven.bethard at gmail.com] > Sent: Friday, May 11, 2007 2:11 AM > > On 5/11/07, Aaron Brady wrote: > > > -----Original Message----- > > > From: Steven Bethard [mailto:steven.bethard at gmail.com] > > > Sent: Friday, May 11, 2007 1:50 AM > > > > > > On 5/11/07, Aaron Brady wrote: > > > > [snip] > > > > > > def netretrieve(self): > > > kwargs = {} > > > if self.filename: > > > kwargs['filename'] = self.filename > > > if hasattr(self, 'hook'): > > > kwargs['reporthook'] = self.hook > > > urlretrieve(self.url, **kwargs) > > > > Right. That's the alternative, -as- I keep bringing up. > > > > Now let's compare, and judge if X is worth Y. > > > > My solution, 3 lines. Yours, 6. > > If you really care about lines and characters, you can write:: > > k = {} > if self.filename: k['filename'] = self.filename > if hasattr(self, 'hook'): k['reporthook'] = self.hook > urlretrieve(self.url, **k) > > That's 4 lines, 132 characters, compared to your 3 lines, 133 characters. > > But the fact that you're drawing the "lets count lines of code" card > suggests that there's no point discussing this any further. > > Good luck with your proposal. > > STeVe Fine. No dice on lines of code alone. We talk readability. Tell me yours is easier to read, compressed or no. From g.brandl at gmx.net Fri May 11 09:24:57 2007 From: g.brandl at gmx.net (Georg Brandl) Date: Fri, 11 May 2007 09:24:57 +0200 Subject: [Python-ideas] parameter omit In-Reply-To: <20070511071546.76D421E4003@bag.python.org> References: <20070511071546.76D421E4003@bag.python.org> Message-ID: Aaron Brady schrieb: >> Is that really what you want? I thought you wanted this to work for >> all functions... >> >> STeve > > You want to see the worked example again. Voila. > > def f( a,b=None,c='abc' ): > print a,b,c > > default= object() > def call_wrapper( callable, *args, **kwargs ): > args=list(args) > for i,j in enumerate( args ): > if j is default: > offset= callable.func_code.co_argcount-\ > len(callable.func_defaults) > args[i]= callable.func_defaults[i-offset] > return callable( *args,**kwargs ) > > call_wrapper( f,0,default,'def' ) > call_wrapper( f,0,'somebody',default ) > > #and output is: > 0 None def > 0 somebody abc Fine, and now go ahead and patch this into the interpreter. I fear that if you don't, nobody will. IMHO this proposal is not completely bad, and as we can see there are cases where it can help (albeit rare cases -- try to find one in the standard library). But to assign a special meaning to a regular object in this way (you can use it all the way you want, but once you call something with it, it will be magically replaced) is a precedent in Python, and I wouldn't have much hope for it. But let this not hinder you to write a patch and bring it up on python-dev. Georg From g.brandl at gmx.net Fri May 11 09:29:22 2007 From: g.brandl at gmx.net (Georg Brandl) Date: Fri, 11 May 2007 09:29:22 +0200 Subject: [Python-ideas] parser in stdlib In-Reply-To: <20070511034722.0E65F1E4003@bag.python.org> References: <91ad5bf80705102036l436e0cbewc32a2eb4b9edbabb@mail.gmail.com> <20070511034722.0E65F1E4003@bag.python.org> Message-ID: Aaron Brady schrieb: >> A perfect example of why programmable syntax is out of question for >> Python. >> >> George > > Hence the quote. First thing I said was, "...it might not be advisable > either, subject to abuse, per GvR...." > > But that doesn't preclude exposing `parser'. It is the extent of my > question, no more. Can we expose the module? If you tell us what you mean with "expose"... the module is written in C and is not much more than a wrapper around Python's own parser, which is written in C too. If you are looking for a Python parser written in Python, you may want to look at the PyPy project's implementation. Georg From jcarlson at uci.edu Fri May 11 09:59:35 2007 From: jcarlson at uci.edu (Josiah Carlson) Date: Fri, 11 May 2007 00:59:35 -0700 Subject: [Python-ideas] parameter omit In-Reply-To: <200705110646.l4B6kQ2Z014168@mx2.service.uci.edu> References: <20070510234449.2618.JCARLSON@uci.edu> <200705110646.l4B6kQ2Z014168@mx2.service.uci.edu> Message-ID: <20070511001240.261B.JCARLSON@uci.edu> "Aaron Brady" wrote: > > From: Josiah Carlson [mailto:jcarlson at uci.edu] > > "Aaron Brady" wrote: > > > What is the default parameter for the function? Problem is, the docs > > don't > > > say what it is. Does it pick its own filename to use for empty inputs? > > > > >>> import urllib > > >>> help(urllib.urlretrieve) > > Help on function urlretrieve in module urllib: > > > > urlretrieve(url, filename=None, reporthook=None, data=None) > > > > >>> > > No nitpicking, Mr. Carlson. These pieces of information are -not- always > available. Should I send you my 486 laptop so that you can have access to a Python interpreter? Because I really can't see how you being ignorant of the arguments to a standard library function in any way supports your case. Further, if you always use 'None' as the default for functions being called, then you can get things like this... class WebRetrieveElement: hook = None filename = None def netretrieveNew( self ): filename= self.filename or ParamDefault hook= hasattr( self,'hook' ) and self.hook or ParamDefault urlretrieve( self.url, filename, hook ) def netretrieveBest(self): urlretrieve(self.url, self.filename, self.hook) And look at that. I define two class level variables and all of a sudden the implementation of netretrieveBest gets a trivial implementation (though it breaks netretrieveNew, which uses a generally frowned upon mechanism that fails when filename and hook are None). But no, lets add a completely useless instance of object so that people can pass silly default arguments like ParamDefault that is a bazillion times more confusing than what Python users have been using for 15 years; None. - Josiah From castironpi at comcast.net Fri May 11 10:20:27 2007 From: castironpi at comcast.net (Aaron Brady) Date: Fri, 11 May 2007 03:20:27 -0500 Subject: [Python-ideas] parameter omit In-Reply-To: <20070511001240.261B.JCARLSON@uci.edu> Message-ID: <20070511082036.EFDB91E4004@bag.python.org> > -----Original Message----- > From: Josiah Carlson [mailto:jcarlson at uci.edu] > > "Aaron Brady" wrote: > > [snip] > > > > Should I send you my 486 laptop so that you can have access to a Python > interpreter? Because I really can't see how you being ignorant of the > arguments to a standard library function in any way supports your case. > > Further, if you always use 'None' as the default for functions being > called, then you can get things like this... > > class WebRetrieveElement: > hook = None > filename = None > > def netretrieveNew( self ): > filename= self.filename or ParamDefault > hook= hasattr( self,'hook' ) and self.hook or ParamDefault > urlretrieve( self.url, filename, hook ) > > def netretrieveBest(self): > urlretrieve(self.url, self.filename, self.hook) > > And look at that. I define two class level variables and all of a > sudden the implementation of netretrieveBest gets a trivial > implementation (though it breaks netretrieveNew, which uses a generally > frowned upon mechanism that fails when filename and hook are None). > > But no, lets add a completely useless instance of object so that people > can pass silly default arguments like ParamDefault that is a bazillion > times more confusing than what Python users have been using for 15 > years; None. > > - Josiah No thank you. Your example is sufficient. Well-crafted at that. Good example. Imagine with me if you will. Say I -am- "ignorant of the arguments to a standard library function". But say they aren't published in help(). Then that breaks yours and we have two broken examples. Great lot of good that did you. Say the default is not None; but a class callback. Say it is a default string for a join delimiter somewhere. Fine examples are imaginary numbers, the function string.split, file([bufsize]), int([radix]), list.sort([cmp]), etc. Pretty much anywhere you see the [] brackets in the documentation. These default values are obvious, and further, None is always a good guess. Answer this one carefully: Have you asserted that defaults are -always- available and published, in the standard library as well as elsewhere? Could one extra value in __builtins__ already be worth all our third-parties' time who could relax and get along? It'll bring world peace. But sure. Send your laptop on over. I'll pay on delivery. Sincerely, That Newsgroup Jerk From castironpi at comcast.net Fri May 11 10:43:18 2007 From: castironpi at comcast.net (Aaron Brady) Date: Fri, 11 May 2007 03:43:18 -0500 Subject: [Python-ideas] parameter omit In-Reply-To: <20070511082036.EFDB91E4004@bag.python.org> Message-ID: <20070511084328.14F781E4004@bag.python.org> > -----Original Message----- > From: python-ideas-bounces at python.org [mailto:python-ideas- > bounces at python.org] On Behalf Of Aaron Brady > > > [snip] Your stewardship is remarkable. But in the case I mention, the costs aren't worth mention. It's an outstanding case, for clear, cost-free, net benefit. Say the parameter is required to be callable. `None' will not suffice. The strongest case against me is that I enable lazy programmers to make assignments in the function declaration. That's worth bringing up. OTOH, what if None is the wrong default? 2.4 Built-in Constants A small number of constants live in the built-in namespace. They are: False - The false value of the bool type. New in version 2.3. True - The true value of the bool type. New in version 2.3. None - The sole value of types.NoneType. None is frequently used to represent the absence of a value, as when default arguments are not passed to a function. NotImplemented - Special value which can be returned by the ``rich comparison'' special methods (__eq__(), __lt__(), and friends), to indicate that the comparison is not implemented with respect to the other type. Ellipsis - Special value used in conjunction with extended slicing syntax. DefaultArgument - Special value used in remaining cases of default arguments where None is not what is intended. Does one complain about Ellipsis? No, it's useful. Comes in handy at just the right times. And furthermore, this proposal isn't entirely without precedent. From santagada at gmail.com Fri May 11 12:14:48 2007 From: santagada at gmail.com (Leonardo Santagada) Date: Fri, 11 May 2007 07:14:48 -0300 Subject: [Python-ideas] parameter omit In-Reply-To: <20070511084328.14F781E4004@bag.python.org> References: <20070511084328.14F781E4004@bag.python.org> Message-ID: <450DAC26-940F-4BCD-834F-4AC48DAEDAB2@gmail.com> Em 11/05/2007, ?s 05:43, Aaron Brady escreveu: > > And furthermore, this proposal isn't entirely without precedent. Ok, we got the idea so let's start voting then :) i'm like -1000 on it... or def vote(who, value=-1000): ... i'm like: vote(santagada at gmail.com) :) -- Leonardo Santagada santagada at gmail.com From aurelien.campeas at logilab.fr Fri May 11 12:57:23 2007 From: aurelien.campeas at logilab.fr (=?iso-8859-1?Q?Aur=E9lien_Camp=E9as?=) Date: Fri, 11 May 2007 12:57:23 +0200 Subject: [Python-ideas] parser in stdlib In-Reply-To: References: <91ad5bf80705102036l436e0cbewc32a2eb4b9edbabb@mail.gmail.com> <20070511034722.0E65F1E4003@bag.python.org> Message-ID: <20070511105723.GB24761@crater.logilab.fr> On Fri, May 11, 2007 at 09:29:22AM +0200, Georg Brandl wrote: > Aaron Brady schrieb: > > >> A perfect example of why programmable syntax is out of question for > >> Python. > >> > >> George > > > > Hence the quote. First thing I said was, "...it might not be advisable > > either, subject to abuse, per GvR...." > > > > But that doesn't preclude exposing `parser'. It is the extent of my > > question, no more. Can we expose the module? > > If you tell us what you mean with "expose"... the module is written in C > and is not much more than a wrapper around Python's own parser, which > is written in C too. > > If you are looking for a Python parser written in Python, you may want > to look at the PyPy project's implementation. or this : http://www.fiber-space.de/EasyExtend/doc/EE.html > > Georg > > _______________________________________________ > Python-ideas mailing list > Python-ideas at python.org > http://mail.python.org/mailman/listinfo/python-ideas From jan.kanis at phil.uu.nl Fri May 11 13:58:56 2007 From: jan.kanis at phil.uu.nl (Jan Kanis) Date: Fri, 11 May 2007 13:58:56 +0200 Subject: [Python-ideas] parameter omit In-Reply-To: <20070511084328.14F781E4004@bag.python.org> References: <20070511084328.14F781E4004@bag.python.org> Message-ID: On Fri, 11 May 2007 10:43:18 +0200, Aaron Brady wrote: >> -----Original Message----- >> From: python-ideas-bounces at python.org [mailto:python-ideas- >> bounces at python.org] On Behalf Of Aaron Brady >> >> > [snip] > > Your stewardship is remarkable. But in the case I mention, the costs > aren't > worth mention. It's an outstanding case, for clear, cost-free, net > benefit. > Say the parameter is required to be callable. `None' will not suffice. > The > strongest case against me is that I enable lazy programmers to make > assignments in the function declaration. That's worth bringing up. > OTOH, > what if None is the wrong default? > > 2.4 Built-in Constants > A small number of constants live in the built-in namespace. They are: > > False - The false value of the bool type. New in version 2.3. > > True - The true value of the bool type. New in version 2.3. > > None - The sole value of types.NoneType. None is frequently used to > represent the absence of a value, as when default arguments are not > passed > to a function. > > NotImplemented - Special value which can be returned by the ``rich > comparison'' special methods (__eq__(), __lt__(), and friends), to > indicate > that the comparison is not implemented with respect to the other type. > > Ellipsis - Special value used in conjunction with extended slicing > syntax. > > DefaultArgument - Special value used in remaining cases of default > arguments > where None is not what is intended. > > Does one complain about Ellipsis? No, it's useful. Comes in handy at > just > the right times. > > And furthermore, this proposal isn't entirely without precedent. > There are some hidden costs you haven't mentioned yet: 1) It's another paragraph in the manual. 2) If DefaultArgument is just a normal object in the builtin namespace, without any interpreter magic every function using default values would have to use some logic to recognize DefaultArgument and do the right thing. If there is interpreter magic that'll be more magic, and another section in the manual to explain that. (apart from magic in itself being bad) A small manual addition wouldn't be a problem on its own, but proposals that easily fix some use case with just a single paragraph manual addition pass by every other week. If they'd all be accepted we'd be saving ourselves a lot of trouble by switching to Perl immediately. More manual means more language complexity, another little step for people learning python, and another page of brain cell usage for anyone using Python. In short, any new addition has to have a *lot* of utility to be acceptable, or else it wil lead to the way of the Perl side. - Jan Oh, and having jerks around is an unfortunate & unintended side effect of having people in the mailing list. I'd be interested if you had any ideas to diminish the problem, though. From jimjjewett at gmail.com Fri May 11 17:00:18 2007 From: jimjjewett at gmail.com (Jim Jewett) Date: Fri, 11 May 2007 11:00:18 -0400 Subject: [Python-ideas] parameter omit In-Reply-To: <20070511082036.EFDB91E4004@bag.python.org> References: <20070511001240.261B.JCARLSON@uci.edu> <20070511082036.EFDB91E4004@bag.python.org> Message-ID: On 5/11/07, Aaron Brady wrote: > carefully: Have you asserted that defaults are -always- available and > published, in the standard library as well as elsewhere? Of course not. Sometimes the real default value doesn't really exist yet, because it is constructed after the function gets called with 'None'. Your proposal doesn't change this. When the default should be introspectable and isn't, this is usually because the function was written in C, and the author wasn't careful to add the proper docstring tagging. If they aren't supporting docstrings yet, they won't bother to support your new object either -- so it has to be done either at the interpreter level or with a wrapper function. The costs in the interpreter would be significant, both in complexity (a special case) and in speed (that particular loop is tight enough that any change can have unexpected results by changing cache performance). The wrapper solution seems good enough to me; it doesn't slow things down unless you use it. You can even automate it with monkey-patching if you like. > Within a full 24 hours, I expect an, "I like this, may be good. Here's my > personal e-mail address, get back to me in a week if you haven't heard > anything." I am pleasantly surprised to get 24 hour response from a vendor, even when I (or, rather, my employer) has paid for that support. But in this case, you actually did get a fairly quick response; it just wasn't what you wanted, because the responders did *not* think it was likely to be a good idea, and you weren't willing to listen to the alternative solutions they proposed. > Could one extra value in __builtins__ already be worth all our third-parties' > time who could relax and get along? If you compile your own local copy, then sure. If you want it in the worldwide distribution, then probably not; backwards compatibility means that it will change only at a bureaucratic pace. As a point of comparison, your proposal would actually be a larger change than decorators, for a less frequent use case. Decorators were agreed to in theory for 2.3 (around 2002/2003), but concerns about how to do it right kept them out until 2.4. Class decorators were still not included (despite a working implementation which was actually a bit simpler) because there was a chance they wouldn't be needed, and adding things is easier than taking them back out. Class decorators have now been approved for Python 2.6, which will probably be available some time next year. -jJ From castironpi at comcast.net Fri May 11 20:09:39 2007 From: castironpi at comcast.net (Aaron Brady) Date: Fri, 11 May 2007 13:09:39 -0500 Subject: [Python-ideas] parameter omit In-Reply-To: Message-ID: <20070511180950.AA6391E4005@bag.python.org> > -----Original Message----- > From: Jan Kanis [mailto:jan.kanis at phil.uu.nl] > Sent: Friday, May 11, 2007 6:59 AM > > On Fri, 11 May 2007 10:43:18 +0200, Aaron Brady > wrote: > > >> -----Original Message----- > >> From: python-ideas-bounces at python.org [mailto:python-ideas- > >> bounces at python.org] On Behalf Of Aaron Brady > >> > >> > [snip] > > > > Your stewardship is remarkable. But in the case I mention, the costs > > aren't > > worth mention. It's an outstanding case, for clear, cost-free, net > > benefit. > > Say the parameter is required to be callable. `None' will not suffice. > > The > > strongest case against me is that I enable lazy programmers to make > > assignments in the function declaration. That's worth bringing up. > > OTOH, > > what if None is the wrong default? > > > > 2.4 Built-in Constants > > A small number of constants live in the built-in namespace. They are: > > > > False - The false value of the bool type. New in version 2.3. > > > > True - The true value of the bool type. New in version 2.3. > > > > None - The sole value of types.NoneType. None is frequently used to > > represent the absence of a value, as when default arguments are not > > passed > > to a function. > > > > NotImplemented - Special value which can be returned by the ``rich > > comparison'' special methods (__eq__(), __lt__(), and friends), to > > indicate > > that the comparison is not implemented with respect to the other type. > > > > Ellipsis - Special value used in conjunction with extended slicing > > syntax. > > > > DefaultArgument - Special value used in remaining cases of default > > arguments > > where None is not what is intended. > > > > Does one complain about Ellipsis? No, it's useful. Comes in handy at > > just > > the right times. > > > > And furthermore, this proposal isn't entirely without precedent. > > > > There are some hidden costs you haven't mentioned yet: > 1) It's another paragraph in the manual. > 2) If DefaultArgument is just a normal object in the builtin namespace, > without any interpreter magic every function using default values would > have to use some logic to recognize DefaultArgument and do the right > thing. If there is interpreter magic that'll be more magic, and another > section in the manual to explain that. (apart from magic in itself being > bad) > > A small manual addition wouldn't be a problem on its own, but proposals > that easily fix some use case with just a single paragraph manual addition > pass by every other week. If they'd all be accepted we'd be saving > ourselves a lot of trouble by switching to Perl immediately. More manual > means more language complexity, another little step for people learning > python, and another page of brain cell usage for anyone using Python. > > In short, any new addition has to have a *lot* of utility to be > acceptable, or else it wil lead to the way of the Perl side. > > - Jan > > Oh, and having jerks around is an unfortunate & unintended side effect of > having people in the mailing list. I'd be interested if you had any ideas > to diminish the problem, though. Not only does the OP's proposal (me) exonerate programmers who have screwed up before, those who have neglected to use None for defaults, and who chose meaningful ones instead, but encourages them to continue to choose it, and frees them from checking the parameter later. > From: Leonardo Santagada > i'm like -1000 on it... or > > def vote(who, value=-1000): -1000: well within expected parameters. Note DefaultArg needs never get referenced literally in declarations, only in calls. def ghi( j=None, k=None, l=None ): if j is None: j= Something if k is None: k= Something2 if l is None: l= Something3 No. Here, I do it all at once. def ghi( j=Something, k=Something2, l=Something3 ): Calls like ghi( MyThing ) still work, as does: ghi( MyThing, l=MyThing3 ). Everybody's on board so far and nothing's changed. Omissions, positional, and keyword arguments still work as we've grown to know and love. What we can do, is always know the parameter. The change is to know the default value in every situation. It's always DefaultArg. ghi( MyThing, DefaultArg, Mything3 ) as well as ghi( DefaultArg, MyThing2 ) Nothing breaks; everything that used to work still does. There's no magic in my proposal, no more than defaults create in the first place. Functions get the assignments done for them; they take no extra logic on their own. It's completely backwards compatible. No question there! But you get new abilities too, for the price of something that's unobtrusive and blends right in. To address Jewett, default arguments -are- built into bytecode. The wrapper takes a single memory address comparison on a per-argument basis. It could get expensive, but at least compare it to looking up values in dictionaries, which is quite common. > > DefaultArgument - Special value used in remaining cases of default > > arguments > > where None is otherwise meaningful. New in version 2.6. If they're not defined, as in C code, then they're always last, or couldn't be called like you guys want to anyway. Raise the usual exception anyway. > In short, any new addition has to have a *lot* of utility to be > acceptable, or else it wil lead to the way of the Perl side. Agreed entirely. You mean, like this? Who brings up the manual? Good. Document something. Your names in lights, I can see it now. I'll write the PEP, but first stop pointing out drawbacks and motivate me. Wink( DefaultArg ). P.S. > Oh, and having jerks around is an unfortunate & unintended side effect of > having people in the mailing list. I'd be interested if you had any ideas > to diminish the problem, though. Nonsense. I'll have my people call my people immediately re: mailing list people. A little louder and stronger could suffice. "Let me hear it son. Costs and benefits. Bottom line. Assets or liabilities?" Then put your feet up. From taleinat at gmail.com Fri May 11 22:02:27 2007 From: taleinat at gmail.com (Tal Einat) Date: Fri, 11 May 2007 23:02:27 +0300 Subject: [Python-ideas] parameter omit In-Reply-To: <20070511180950.AA6391E4005@bag.python.org> References: <20070511180950.AA6391E4005@bag.python.org> Message-ID: <7afdee2f0705111302r26afeef5h4f688889adcaa095@mail.gmail.com> On 5/11/07, Aaron Brady wrote: > > Note DefaultArg needs never get referenced literally in declarations, only > in calls. > > def ghi( j=None, k=None, l=None ): > if j is None: j= Something > if k is None: k= Something2 > if l is None: l= Something3 > > No. Here, I do it all at once. > def ghi( j=Something, k=Something2, l=Something3 ): Maybe I'm missing something here... But why would someone not use the latter syntax unless the value must be calculated when the function is called, as opposed to when the function is defined? In such cases, None fits the bill. (Default arguments are evaluated at function definition.) Calls like ghi( MyThing ) still work, as does: > ghi( MyThing, l=MyThing3 ). > > Everybody's on board so far and nothing's changed. Omissions, positional, > and keyword arguments still work as we've grown to know and love. > > What we can do, is always know the parameter. The change is to know the > default value in every situation. It's always DefaultArg. > > ghi( MyThing, DefaultArg, Mything3 ) > as well as > ghi( DefaultArg, MyThing2 ) IMHO this is far less readable than using keyword arguments and omitting those arguments for which you'd like to use the default value. I personally like the "keyword-only arguments" PEP (3102) because it could help make function calls more readable. Perhaps we could learn from experience? I've recently had to automate Excel with Python and used the COM interface. In COM, there is a value called "Missing" which is passed to functions when no value should be passed for an argument - similar to your DefaultArg. This leads to code like this (C# code examples): http://msdn2.microsoft.com/en-us/library/aa168343(office.11).aspx (straight from the online MSDN) MenuBarItem = MainMenuBar.Controls.Add( Office.MsoControlType.msoControlPopup, Type.Missing, Type.Missing, Type.Missing, true); And that was not a far-fetched example - here is an extreme example: http://blogs.ittoolbox.com/visualbasic/evolution/archives/importing-unformatted-excel-sheets-into-sql-server-2000-using-net-part-i-7501 Excel.Application excelApp = new Excel.ApplicationClass(); Excel.Workbook thisWorkbook = excelApp.Workbooks.Open(strFileName, Type.Missing, Type.Missing, Type.Missing, Type.Missing,Type.Missing, Type.Missing, Type.Missing, Type.Missing,Type.Missing, Type.Missing, Type.Missing, Type.Missing,Type.Missing, Type.Missing); IMO this is horrendous. Horrible. Eye-gouging. I'd rather write machine code in hex. - Tal -------------- next part -------------- An HTML attachment was scrubbed... URL: From castironpi at comcast.net Fri May 11 22:26:27 2007 From: castironpi at comcast.net (Aaron Brady) Date: Fri, 11 May 2007 15:26:27 -0500 Subject: [Python-ideas] parameter omit In-Reply-To: <7afdee2f0705111302r26afeef5h4f688889adcaa095@mail.gmail.com> Message-ID: <20070511202639.13B871E4005@bag.python.org> _____ From: Tal Einat [mailto:taleinat at gmail.com] Sent: Friday, May 11, 2007 3:02 PM To: python-ideas at python.org Cc: Aaron Brady Subject: Re: [Python-ideas] parameter omit On 5/11/07, Aaron Brady wrote: Note DefaultArg needs never get referenced literally in declarations, only in calls. def ghi( j=None, k=None, l=None ): if j is None: j= Something if k is None: k= Something2 if l is None: l= Something3 No. Here, I do it all at once. def ghi( j=Something, k=Something2, l=Something3 ): Maybe I'm missing something here... But why would someone not use the latter syntax unless the value must be calculated when the function is called, as opposed to when the function is defined? In such cases, None fits the bill. (Default arguments are evaluated at function definition.) Calls like ghi( MyThing ) still work, as does: ghi( MyThing, l=MyThing3 ). Everybody's on board so far and nothing's changed. Omissions, positional, and keyword arguments still work as we've grown to know and love. What we can do, is always know the parameter. The change is to know the default value in every situation. It's always DefaultArg. ghi( MyThing, DefaultArg, Mything3 ) as well as ghi( DefaultArg, MyThing2 ) IMHO this is far less readable than using keyword arguments and omitting those arguments for which you'd like to use the default value. I personally like the "keyword-only arguments" PEP (3102) because it could help make function calls more readable. Perhaps we could learn from experience? I've recently had to automate Excel with Python and used the COM interface. In COM, there is a value called "Missing" which is passed to functions when no value should be passed for an argument - similar to your DefaultArg. This leads to code like this (C# code examples): http://msdn2.microsoft.com/en-us/library/aa168343(office.11).aspx (straight from the online MSDN) MenuBarItem = MainMenuBar.Controls.Add( Office.MsoControlType.msoControlPopup, Type.Missing, Type.Missing, Type.Missing, true); And that was not a far-fetched example - here is an extreme example: http://blogs.ittoolbox.com/visualbasic/evolution/archives/importing-unformat ted-excel-sheets-into-sql-server-2000-using-net-part-i-7501 Excel.Application excelApp = new Excel.ApplicationClass(); Excel.Workbook thisWorkbook = excelApp.Workbooks.Open(strFileName,Type.Missing, Type.Missing, Type.Missing, Type.Missing,Type.Missing, Type.Missing, Type.Missing, Type.Missing,Type.Missing, Type.Missing, Type.Missing, Type.Missing,Type.Missing, Type.Missing); IMO this is horrendous. Horrible. Eye-gouging. I'd rather write machine code in hex. - Tal -------------- next part -------------- An HTML attachment was scrubbed... URL: From castironpi at comcast.net Fri May 11 22:40:46 2007 From: castironpi at comcast.net (Aaron Brady) Date: Fri, 11 May 2007 15:40:46 -0500 Subject: [Python-ideas] parameter omit In-Reply-To: <7afdee2f0705111302r26afeef5h4f688889adcaa095@mail.gmail.com> Message-ID: <20070511204058.840F61E400F@bag.python.org> > -----Original Message----- > From: Tal Einat [mailto:taleinat at gmail.com] > Sent: Friday, May 11, 2007 3:02 PM > > On 5/11/07, Aaron Brady wrote: > > Note DefaultArg needs never get referenced literally in > declarations, only > in calls. > > def ghi( j=None, k=None, l=None ): > if j is None: j= Something > if k is None: k= Something2 > if l is None: l= Something3 > > No. Here, I do it all at once. > def ghi( j=Something, k=Something2, l=Something3 ): > > > Maybe I'm missing something here... But why would someone not use the > latter syntax unless the value must be calculated when the function is > called, as opposed to when the function is defined? In such cases, None > fits the bill. (Default arguments are evaluated at function definition.) > > > > Calls like ghi( MyThing ) still work, as does: > ghi( MyThing, l=MyThing3 ). > > Everybody's on board so far and nothing's changed. Omissions, > positional, > and keyword arguments still work as we've grown to know and love. > > What we can do, is always know the parameter. The change is to know > the > default value in every situation. It's always DefaultArg. > > ghi( MyThing, DefaultArg, Mything3 ) > as well as > ghi( DefaultArg, MyThing2 ) > > > IMHO this is far less readable than using keyword arguments and omitting > those arguments for which you'd like to use the default value. I > personally like the "keyword-only arguments" PEP (3102) because it could > help make function calls more readable. > > > Perhaps we could learn from experience? > > I've recently had to automate Excel with Python and used the COM > interface. In COM, there is a value called "Missing" which is passed to > functions when no value should be passed for an argument - similar to your > DefaultArg. This leads to code like this (C# code examples): > > http://msdn2.microsoft.com/en-us/library/aa168343(office.11).aspx > (straight from the online MSDN) > > MenuBarItem = MainMenuBar.Controls.Add( > Office.MsoControlType.msoControlPopup, > Type.Missing, Type.Missing, Type.Missing, true); > > And that was not a far-fetched example - here is an extreme example: > > http://blogs.ittoolbox.com/visualbasic/evolution/archives/importing- > unformatted-excel-sheets-into-sql-server-2000-using-net-part-i-7501 > unformatted-excel-sheets-into-sql-server-2000-using-net-part-i-7501> > > Excel.Application excelApp = new Excel.ApplicationClass(); > Excel.Workbook thisWorkbook = > excelApp.Workbooks.Open(strFileName,Type.Missing, Type.Missing, > Type.Missing, Type.Missing,Type.Missing, Type.Missing, Type.Missing, > Type.Missing,Type.Missing, Type.Missing, Type.Missing, > Type.Missing,Type.Missing, Type.Missing); > > > IMO this is horrendous. Horrible. Eye-gouging. > > I'd rather write machine code in hex. > > > - Tal Ok, this isn't working to get my idea over. There's something wrong with somebody, and it's simplest to assume its me. Probably inexperience in posting. Not to mention, I have no idea who I'm talking to, or what the local dialect is. (Sorry about the blank message too... wrong keystroke.) Tal's examples don't contradict me. In his, I call: > MenuBarItem = MainMenuBar.Controls.Add( > Office.MsoControlType.msoControlPopup, thenamedarg= true); and > Excel.Workbook thisWorkbook = excelApp.Workbooks.Open(strFileName) Traditional function call. Calls still will work the way they do today. You have -extra- flexibility, not less, sir. I add zero requirements. Please let me repeat. Nothing breaks. From rrr at ronadam.com Fri May 11 22:54:35 2007 From: rrr at ronadam.com (Ron Adam) Date: Fri, 11 May 2007 15:54:35 -0500 Subject: [Python-ideas] Alternate quote delimiters Message-ID: <4644D80B.4080806@ronadam.com> While watching the various issues about raw strings and quotes being discussed, I decided look into other ways to resolve string delimiter collisions that might also improve pythons string handling in general. And I'd figure I'd let it get shot full of holes here first. ;-) Here's a nice overview of the issue with various examples. http://en.wikipedia.org/wiki/String_literal *Note: The wiki python raw string example has a trailing backslash which would cause an error. r"The Windows path is C:\Foo\Bar\Baz\" In the case of raw strings, the escaped quotes are only needed in order for tokenize.c to locate the end of the string. The back slashes remain in the string. The end of the string is the first unescaped quote of the same type as the starting quote. >>> s = r"\"Hello World\"" >>> print s \"Hello World\" This allows you to enter, back-slash + quote, pairs into a string, but ... - This doesn't help in entering only quotes. You still need to either use a different quotes than what is in the string or not use raw strings. - A minor side effect is that you can't have a raw string end with a single slash as in the incorrect wiki example above. Other languages which use escape characters in raw strings have the same issue. - If you have a long string with multiple quotes as you can in regular expressions the increased number of \ characters can make the regular expression more difficult to read and can add up to be more characters than needed. - Another minor issue I've found is doctest that do test on quoted strings may have multiple nested doc strings which may require careful selection of quote characters. The problem arises because the start and end delimiters are the same. The start of the nested string ends the top level string. The current solution is to pick different quote characters or escape quote characters in the nested strings. So how about a multiple quoting solution? The examples of this in the wiki page are of the form... qq^I said, "Can you hear me?"^ qq at I said, "Can you hear me?"@ qq?I said, "Can you hear me?"? But that doesn't fit well with pythons use of quotes. But a variation of this would. Add a 'q' string prefix similar to the 'u' and 'r' prefix's that takes the first character inside the quotes as an additional delimiter. Then ending quote will then need to have that same character proceeding it. q"^I said, "Can you hear me?"^" q"""|I said, "Can you hear me?"|""" The vertical bar is part of the quote here, not part of the string. rq"^The Windows path is C:\Foo\Bar\Baz\^" This example will work as expected. Because the beginning and ending of the strings are not identical, it's possible that they can allow nesting. rq"""^ rq"""^ This is a nested string. ^""" """ Another nested string. """ ^""" The most useful feature of this would be in temporarily commenting out large blocks of python code. Currently this doesn't work well if the block that contain triple quoted doc strings. Another option might be to designate certain quote delimiters for special purposes. Dedented strings. q"""< This is a Dedented Paragraph. <""" Commented out source code. q"""# def foo(bar): """ A bar checker. """ return bar is True #""" ReST formatted strings. rq""": Bullet lists: - This is item 1 - This is item 2 - Bullets are "-", "*" or "+". Continuing text must be aligned after the bullet and whitespace. Note that a blank line is required before the first item and after the last, but is optional between items. :""" This use would require some way to preserve it's quoting type so it can later be used to render the text. (Any ideas?) Cheers, Ron From castironpi at comcast.net Sat May 12 00:02:08 2007 From: castironpi at comcast.net (Aaron Brady) Date: Fri, 11 May 2007 17:02:08 -0500 Subject: [Python-ideas] parameter omit In-Reply-To: <20070511001240.261B.JCARLSON@uci.edu> Message-ID: <20070511220225.216BE1E4006@bag.python.org> > -----Original Message----- > From: Josiah Carlson [mailto:jcarlson at uci.edu] > Sent: Friday, May 11, 2007 3:00 AM > > "Aaron Brady" wrote: > [snip] > > class WebRetrieveElement: > hook = None > filename = None > > def netretrieveNew( self ): > filename= self.filename or ParamDefault > hook= hasattr( self,'hook' ) and self.hook or ParamDefault > urlretrieve( self.url, filename, hook ) > > def netretrieveBest(self): > urlretrieve(self.url, self.filename, self.hook) class WebRetrieveElement: url= None filename= None hook= None def netretrieveOld( self ): urlretrieve( self.url, self.filename, self.hook ) def netretrieveNew( self ): urlretrieve( self.url, self.filename, self.hook ) From castironpi at comcast.net Sat May 12 00:15:11 2007 From: castironpi at comcast.net (Aaron Brady) Date: Fri, 11 May 2007 17:15:11 -0500 Subject: [Python-ideas] parser in stdlib In-Reply-To: Message-ID: <20070511221523.D36331E4005@bag.python.org> Hi, I see: def parsesuite(self, text): """Return a modified parse tree for the given suite text.""" return self.transform(parser.suite(text)) in https://codespeak.net/viewvc/pypy/dist/lib-python/2.4.1/compiler/transformer .py?revision=39456&view=markup and ...future.py 39456 misc.py 39456 pyassem.py 39456 pycodegen.py 39456... in https://codespeak.net/viewvc/pypy/dist/lib-python/2.4.1/compiler/ as well as os.py 39456 os2emxpath.py 39456 pdb.doc 39456 pdb.py 39456 in https://codespeak.net/viewvc/pypy/dist/lib-python/2.4.1/ . Where, exactly? > -----Original Message----- > From: python-ideas-bounces at python.org [mailto:python-ideas- > bounces at python.org] On Behalf Of Georg Brandl > Sent: Friday, May 11, 2007 2:29 AM > To: python-ideas at python.org > Subject: Re: [Python-ideas] parser in stdlib > > Aaron Brady schrieb: > > >> A perfect example of why programmable syntax is out of question for > >> Python. > >> > >> George > > > > Hence the quote. First thing I said was, "...it might not be advisable > > either, subject to abuse, per GvR...." > > > > But that doesn't preclude exposing `parser'. It is the extent of my > > question, no more. Can we expose the module? > > If you tell us what you mean with "expose"... the module is written in C > and is not much more than a wrapper around Python's own parser, which > is written in C too. > > If you are looking for a Python parser written in Python, you may want > to look at the PyPy project's implementation. > > Georg > > _______________________________________________ > Python-ideas mailing list > Python-ideas at python.org > http://mail.python.org/mailman/listinfo/python-ideas From cvrebert at gmail.com Sat May 12 01:09:33 2007 From: cvrebert at gmail.com (Chris Rebert) Date: Fri, 11 May 2007 16:09:33 -0700 Subject: [Python-ideas] Alternate quote delimiters In-Reply-To: <4644D80B.4080806@ronadam.com> References: <4644D80B.4080806@ronadam.com> Message-ID: <47c890dc0705111609m490ef42cva79ba7d32a4182c7@mail.gmail.com> On 5/11/07, Ron Adam wrote: > > While watching the various issues about raw strings and quotes being > discussed, I decided look into other ways to resolve string delimiter > collisions that might also improve pythons string handling in general. > > And I'd figure I'd let it get shot full of holes here first. ;-) Here come the first shots. ;-) > So how about a multiple quoting solution? The examples of this in the wiki > page are of the form... > > qq^I said, "Can you hear me?"^ > > qq at I said, "Can you hear me?"@ > > qq?I said, "Can you hear me?"? > > > But that doesn't fit well with pythons use of quotes. But a variation of > this would. Add a 'q' string prefix similar to the 'u' and 'r' prefix's > that takes the first character inside the quotes as an additional > delimiter. Then ending quote will then need to have that same character > proceeding it. > > q"^I said, "Can you hear me?"^" > > q"""|I said, "Can you hear me?"|""" > > The vertical bar is part of the quote here, not part of the string. Ick. This will make python code harder to parse (I wonder whether the current parser even do what you propose), and isn't that much of an improvement in ease of expression. Also, this seems way too perlish for my tastes. There should be only one way to do quoting, but practicality beat purity for quotes and regexes. However, allowing arbitrary quoting characters seems like overkill. > Because the beginning and ending of the strings are not identical, it's > possible that they can allow nesting. > > rq"""^ > rq"""^ > This is a nested string. > ^""" > """ > Another nested string. > """ > ^""" > > > The most useful feature of this would be in temporarily commenting out > large blocks of python code. Currently this doesn't work well if the block > that contain triple quoted doc strings. A block commenting syntax may be useful, however I don't like this proposal because of the previous point. Also, most python editors let you block comment out stuff with a command to add the appropriate #s pretty easily. > Another option might be to designate certain quote delimiters for special > purposes. > > Dedented strings. > > q"""< > This is a > Dedented > Paragraph. > <""" > > > Commented out source code. > > q"""# > def foo(bar): > """ > A bar checker. > """ > return bar is True > #""" I'm neutral on these. > ReST formatted strings. > > rq""": > Bullet lists: > > - This is item 1 > - This is item 2 > > - Bullets are "-", "*" or "+". > Continuing text must be aligned > after the bullet and whitespace. > > Note that a blank line is required > before the first item and after the > last, but is optional between items. > :""" Seems like a little much to have syntax for ReST. Is it used frequently enough to justify adding this? - Chris Rebert From scott+python-ideas at scottdial.com Sat May 12 01:25:27 2007 From: scott+python-ideas at scottdial.com (Scott Dial) Date: Fri, 11 May 2007 19:25:27 -0400 Subject: [Python-ideas] parser in stdlib In-Reply-To: <20070511221523.D36331E4005@bag.python.org> References: <20070511221523.D36331E4005@bag.python.org> Message-ID: <4644FB67.8080607@scottdial.com> Aaron Brady wrote: > Georg Brandl wrote: >> If you are looking for a Python parser written in Python, you may want >> to look at the PyPy project's implementation. >> > Where, exactly? > First of all, stop top posting, it makes it hard to reply to you. Second of all, I doubt this will at all aide you in whatever quest you are on, but the place you are looking for is: /pypy/interpreter/pyparser/pythonparse.py I think the link to EasyExtend was the most logical one.. -Scott -- Scott Dial scott at scottdial.com scodial at cs.indiana.edu From greg.ewing at canterbury.ac.nz Sat May 12 01:49:43 2007 From: greg.ewing at canterbury.ac.nz (Greg Ewing) Date: Sat, 12 May 2007 11:49:43 +1200 Subject: [Python-ideas] parser in stdlib In-Reply-To: <20070511034722.0E65F1E4003@bag.python.org> References: <20070511034722.0E65F1E4003@bag.python.org> Message-ID: <46450117.40407@canterbury.ac.nz> Aaron Brady wrote: > But that doesn't preclude exposing `parser'. It is the extent of my > question, no more. Can we expose the module? I can understand there being reluctance to expose what are currently internal details of this module, thereby effectively freezing them. -- Greg From rrr at ronadam.com Sat May 12 01:56:07 2007 From: rrr at ronadam.com (Ron Adam) Date: Fri, 11 May 2007 18:56:07 -0500 Subject: [Python-ideas] Alternate quote delimiters In-Reply-To: <47c890dc0705111609m490ef42cva79ba7d32a4182c7@mail.gmail.com> References: <4644D80B.4080806@ronadam.com> <47c890dc0705111609m490ef42cva79ba7d32a4182c7@mail.gmail.com> Message-ID: <46450297.3090307@ronadam.com> Chris Rebert wrote: > On 5/11/07, Ron Adam wrote: >> >> While watching the various issues about raw strings and quotes being >> discussed, I decided look into other ways to resolve string delimiter >> collisions that might also improve pythons string handling in general. >> >> And I'd figure I'd let it get shot full of holes here first. ;-) > > Here come the first shots. ;-) Great! ;-) >> So how about a multiple quoting solution? The examples of this in the >> wiki >> page are of the form... >> >> qq^I said, "Can you hear me?"^ >> >> qq at I said, "Can you hear me?"@ >> >> qq?I said, "Can you hear me?"? >> >> >> But that doesn't fit well with pythons use of quotes. But a variation of >> this would. Add a 'q' string prefix similar to the 'u' and 'r' prefix's >> that takes the first character inside the quotes as an additional >> delimiter. Then ending quote will then need to have that same character >> proceeding it. >> >> q"^I said, "Can you hear me?"^" >> >> q"""|I said, "Can you hear me?"|""" >> >> The vertical bar is part of the quote here, not part of the string. > > Ick. This will make python code harder to parse (I wonder whether the > current parser even do what you propose), and isn't that much of an > improvement in ease of expression. The tokanizer can be modified to convert any of these to standard or raw strings accordingly. It just needs to find the beginning and the end. I haven't looked into what will be needed to pass the delimiter to the compiler yet. So in it's simplest form, it's just a bit of preprocessing. > Also, this seems way too perlish > for my tastes. There should be only one way to do quoting, but > practicality beat purity for quotes and regexes. However, allowing > arbitrary quoting characters seems like overkill. Then limit it to just a smaller set of characters. Which ones do you suggest. Perl uses the forms above I didn't choose. Those don't even look like strings to me, which is why id didn't even consider them. Almost every other solution has problems of some sort. This is the only solution I liked that did not have any problems. Like anything new it may take a little getting used to before it seems like python rather than something tacked on. >> Because the beginning and ending of the strings are not identical, it's >> possible that they can allow nesting. >> >> rq"""^ >> rq"""^ >> This is a nested string. >> ^""" >> """ >> Another nested string. >> """ >> ^""" >> >> >> The most useful feature of this would be in temporarily commenting out >> large blocks of python code. Currently this doesn't work well if the >> block >> that contain triple quoted doc strings. > > A block commenting syntax may be useful, however I don't like this > proposal because of the previous point. Also, most python editors let > you block comment out stuff with a command to add the appropriate #s > pretty easily. True, and that is what I do. However, most non-python editors need macros programed into them if they have them, if they don't, you must fall back to manually adding #'s to each line. >> Another option might be to designate certain quote delimiters for special >> purposes. >> >> Dedented strings. >> >> q"""< >> This is a >> Dedented >> Paragraph. >> <""" >> >> >> Commented out source code. >> >> q"""# >> def foo(bar): >> """ >> A bar checker. >> """ >> return bar is True >> #""" > > I'm neutral on these. The choices of delimiters in these cases need not be carved in stone. It can be an informal standard as well. >> ReST formatted strings. >> >> rq""": >> Bullet lists: >> >> - This is item 1 >> - This is item 2 >> >> - Bullets are "-", "*" or "+". >> Continuing text must be aligned >> after the bullet and whitespace. >> >> Note that a blank line is required >> before the first item and after the >> last, but is optional between items. >> :""" > > Seems like a little much to have syntax for ReST. Is it used > frequently enough to justify adding this? It's not really syntax for reST in this case. It's more of a very general method to notate or tag a string. There may be other uses for that as well. > - Chris Rebert Cheers, Ron From castironpi at comcast.net Sat May 12 02:17:25 2007 From: castironpi at comcast.net (Aaron Brady) Date: Fri, 11 May 2007 19:17:25 -0500 Subject: [Python-ideas] parser in stdlib In-Reply-To: <46450117.40407@canterbury.ac.nz> Message-ID: <20070512001737.BC6F31E4005@bag.python.org> > -----Original Message----- > From: Greg Ewing [mailto:greg.ewing at canterbury.ac.nz] > Sent: Friday, May 11, 2007 6:50 PM > > Aaron Brady wrote: > > > But that doesn't preclude exposing `parser'. It is the extent of my > > question, no more. Can we expose the module? > > I can understand there being reluctance to expose > what are currently internal details of this module, > thereby effectively freezing them. > > -- > Greg I didn't realize they were changing so dynamically. But then, plenty of the modules have parallel Python and C implementations. I suspect the true reason lies more with Sakkis' post [5/10 23:26 us central]. A mimetic structure such as Python will sit somewhere between restriction and liberty. Best to be deliberate in choosing a place on the continuum. But where, exactly? Discouraging customized syntax is one thing. Prohibiting it altogether is another extreme. The current positioning lies with the latter. Put `parser' in to encourage the adventurous explorer, -while- keeping native dynamic constructs disabled in order to keep up unity. I do not hold that we lift all restrictions. Rather, merely -reduce- the number of hoops you must jump through to get at Python internals. If you think that everybody will jump-to and create their own Python the very first day you let a second ray of light shine in, you've underestimated Python. For one thing, we -want- to stick together, and will on our own. Present the option, and you'll only get better suggestions, thenceforth. The current state is too restrictive. From taleinat at gmail.com Sat May 12 02:14:33 2007 From: taleinat at gmail.com (Tal Einat) Date: Sat, 12 May 2007 03:14:33 +0300 Subject: [Python-ideas] parameter omit In-Reply-To: <4644d502.4a2a05fb.048d.ffffabfeSMTPIN_ADDED@mx.google.com> References: <7afdee2f0705111302r26afeef5h4f688889adcaa095@mail.gmail.com> <4644d502.4a2a05fb.048d.ffffabfeSMTPIN_ADDED@mx.google.com> Message-ID: <7afdee2f0705111714s60118d8cuc219765830b3f59f@mail.gmail.com> On 5/11/07, Aaron Brady wrote: > > > > Perhaps we could learn from experience? > > > > I've recently had to automate Excel with Python and used the COM > > interface. In COM, there is a value called "Missing" which is passed to > > functions when no value should be passed for an argument - similar to > your > > DefaultArg. This leads to code like this (C# code examples): > > > > http://msdn2.microsoft.com/en-us/library/aa168343(office.11).aspx > > (straight from the online MSDN) > > > > MenuBarItem = MainMenuBar.Controls.Add( > > Office.MsoControlType.msoControlPopup, > > Type.Missing, Type.Missing, Type.Missing, true); > > > > And that was not a far-fetched example - here is an extreme example: > > > > http://blogs.ittoolbox.com/visualbasic/evolution/archives/importing- > > unformatted-excel-sheets-into-sql-server-2000-using-net-part-i-7501 > > > unformatted-excel-sheets-into-sql-server-2000-using-net-part-i-7501> > > > > Excel.Application excelApp = new Excel.ApplicationClass(); > > Excel.Workbook thisWorkbook = > > excelApp.Workbooks.Open(strFileName,Type.Missing, Type.Missing, > > Type.Missing, Type.Missing,Type.Missing, Type.Missing, Type.Missing, > > Type.Missing,Type.Missing, Type.Missing, Type.Missing, > > Type.Missing,Type.Missing, Type.Missing); > > > > > > IMO this is horrendous. Horrible. Eye-gouging. > > > > I'd rather write machine code in hex. > > > > > > - Tal > > Ok, this isn't working to get my idea over. There's something wrong with > somebody, and it's simplest to assume its me. Probably inexperience in > posting. Not to mention, I have no idea who I'm talking to, or what the > local dialect is. (Sorry about the blank message too... wrong keystroke.) > > Tal's examples don't contradict me. In his, I call: > > > MenuBarItem = MainMenuBar.Controls.Add( > > Office.MsoControlType.msoControlPopup, thenamedarg= true); > and > > Excel.Workbook thisWorkbook = excelApp.Workbooks.Open(strFileName) > > Traditional function call. Calls still will work the way they do today. > You have -extra- flexibility, not less, sir. I add zero requirements. > Please let me repeat. Nothing breaks. These are simply the examples I could find with several minutes of Googling, admittedly not great examples, as you pointed out. I was just trying to show real world ugly code which was written as a result of an infrastructure adopting a concept which is very similar to the one which you propose. The point was to show that adopting your suggestion could result in even less readable function calls. Yes, nothing breaks. I really get it. I'm against this because it is, IMHO, not Pythonic. I'm not saying it won't be possible to write readable code. I'm saying it -would- be possible to write even less readable code. Specifically, I might be forced to write such ugly function calls when calling functions written by others, therefore adopting this feature could lead to my being forced to write uglier code. Not to mention reading others' uglier code... - Tal (P.S. in the first example, a keyword argument could not be used, because all of the arguments were positional.) -------------- next part -------------- An HTML attachment was scrubbed... URL: From castironpi at comcast.net Sat May 12 02:56:03 2007 From: castironpi at comcast.net (Aaron Brady) Date: Fri, 11 May 2007 19:56:03 -0500 Subject: [Python-ideas] parameter omit In-Reply-To: <20070511220225.216BE1E4006@bag.python.org> Message-ID: <20070512005615.EB6681E4005@bag.python.org> > -----Original Message----- > From: python-ideas-bounces at python.org [mailto:python-ideas- > bounces at python.org] On Behalf Of Aaron Brady > > -----Original Message----- > > From: Josiah Carlson [mailto:jcarlson at uci.edu] > > Sent: Friday, May 11, 2007 3:00 AM > > [snip] > > class WebRetrieveElement: > url= None > filename= None > hook= None > > def netretrieveOld( self ): > urlretrieve( self.url, self.filename, self.hook ) > > def netretrieveNew( self ): > urlretrieve( self.url, self.filename, self.hook ) And while I'm at it and thinking clearly, with cool weather and open doors, the basic problem here, underlying and distilled, is that None is serving double-duty. I've had a feeling so since month two. It's used to signal an absence of a value. But there are two distinct situations in which it's needed. One for values, two for function calls. You could always require all parameter defaults to equal `None'. But since they're not, take this. DefaultArg = object() From guido at python.org Sat May 12 04:29:33 2007 From: guido at python.org (Guido van Rossum) Date: Fri, 11 May 2007 19:29:33 -0700 Subject: [Python-ideas] parser in stdlib In-Reply-To: <20070512001737.BC6F31E4005@bag.python.org> References: <46450117.40407@canterbury.ac.nz> <20070512001737.BC6F31E4005@bag.python.org> Message-ID: On 5/11/07, Aaron Brady wrote: > I suspect the true reason lies more with Sakkis' post [5/10 23:26 us > central]. A mimetic structure such as Python will sit somewhere between > restriction and liberty. Best to be deliberate in choosing a place on the > continuum. But where, exactly? What on earth is a "mimetic structure"? Please keep the jargon understandable for the rest of us, at least if you want to be heard. > Discouraging customized syntax is one thing. Prohibiting it altogether is > another extreme. The current positioning lies with the latter. Put > `parser' in to encourage the adventurous explorer, -while- keeping native > dynamic constructs disabled in order to keep up unity. > > I do not hold that we lift all restrictions. Rather, merely -reduce- the > number of hoops you must jump through to get at Python internals. Depends on which internals you're talking about. Most internals are very close to the surface. Syntax happens to be hermetic though. Perhaps you need to find a different language for what you want? > If you think that everybody will jump-to and create their own Python the > very first day you let a second ray of light shine in, you've underestimated > Python. For one thing, we -want- to stick together, and will on our own. > Present the option, and you'll only get better suggestions, thenceforth. > > The current state is too restrictive. That's easy for you to say. Have you tried (*seriously* tried) to specify such a thing? (For Python, maintaining full backwards compatibility.) In this community, code talks. Good understandable specs are sometimes allowed to speak. Wild ideas, especially if they involve "let others figure out how to design and implement my idea, but I need it now" are shown the door. -- --Guido van Rossum (home page: http://www.python.org/~guido/) From jimjjewett at gmail.com Sat May 12 18:11:02 2007 From: jimjjewett at gmail.com (Jim Jewett) Date: Sat, 12 May 2007 12:11:02 -0400 Subject: [Python-ideas] Alternate quote delimiters In-Reply-To: <4644D80B.4080806@ronadam.com> References: <4644D80B.4080806@ronadam.com> Message-ID: > ... doctest that do test on quoted strings > may have multiple nested doc strings ... > ... Add a 'q' string prefix similar to the 'u' and 'r' prefix's > that takes the first character inside the quotes as an > additional delimiter. Then ending quote will then need to > have that same character proceeding it. > q"^I said, "Can you hear me?"^" > q"""|I said, "Can you hear me?"|""" > The vertical bar is part of the quote here, not part of > the string. This should work, but I can't help wondering if it is too complicated. What if the character were limited to the opening of a bracketed-pair, such as {[( Or is that just as bad, and less flexible to boot? }]} > rq"^The Windows path is C:\Foo\Bar\Baz\^" > This example will work as expected. How serious is this problem? r"The Windows path is C:\Foo\Bar\Baz\X"[:-1] is awkward, but ... how much complexity do we want to incur avoiding it? -jJ From jimjjewett at gmail.com Sat May 12 18:35:54 2007 From: jimjjewett at gmail.com (Jim Jewett) Date: Sat, 12 May 2007 12:35:54 -0400 Subject: [Python-ideas] parameter omit In-Reply-To: <20070512005615.EB6681E4005@bag.python.org> References: <20070511220225.216BE1E4006@bag.python.org> <20070512005615.EB6681E4005@bag.python.org> Message-ID: On 5/11/07, Aaron Brady wrote: > And while I'm at it and thinking clearly, with cool weather and open doors, > the basic problem here, underlying and distilled, is that None is serving > double-duty. Yes. When None appears in a parameter list (or an argument list, at the calling site), it might really be a sentinel for something else, and that is a wart. > You could always require all parameter defaults to equal `None'. But since > they're not, take this. > DefaultArg = object() Yes; this is used when None actually is a valid and meaningful value. I don't see a good way to *always* use this idiom though, because (1) If DefaultArg is a pre-existing object, then there will be times when it is valid and meaningful data -- such as when introspecting. (2) Creating it afresh is a bit of boilerplate that we wouldn't want to require when it isn't really needed. sentinel=object() def f(val=sentinel): if val is sentinel: And note that the creation can't be inline, such as def f(val=object()): or there wouldn't be any good way to test for it. Adding a keyword to do that def f(val=object()): if defaulted val: would probably be a good idea. (I don't think it would get used often enough to justify the costs of a change, but there would be a clear benefit to include in the cost-benefit calculations.) -jJ From rrr at ronadam.com Sat May 12 19:37:41 2007 From: rrr at ronadam.com (Ron Adam) Date: Sat, 12 May 2007 12:37:41 -0500 Subject: [Python-ideas] Alternate quote delimiters In-Reply-To: References: <4644D80B.4080806@ronadam.com> Message-ID: <4645FB65.6090809@ronadam.com> Jim Jewett wrote: >> ... doctest that do test on quoted strings >> may have multiple nested doc strings ... > >> ... Add a 'q' string prefix similar to the 'u' and 'r' prefix's >> that takes the first character inside the quotes as an >> additional delimiter. Then ending quote will then need to >> have that same character proceeding it. > >> q"^I said, "Can you hear me?"^" > >> q"""|I said, "Can you hear me?"|""" > >> The vertical bar is part of the quote here, not part of >> the string. > > This should work, but I can't help wondering if it is too complicated. > What if the character were limited to the opening of a > bracketed-pair, such as {[( Or is that just as bad, and less flexible > to boot? }]} If we are not concerned about meta uses, then we probably only need one. I prefer the non-directional symbols as they don't suggest the string is another container type. Raymonds information attribute pep might fulfill the meta uses I had in mind. (Don't know until we see it.) >> rq"^The Windows path is C:\Foo\Bar\Baz\^" > >> This example will work as expected. > > How serious is this problem? > > r"The Windows path is C:\Foo\Bar\Baz\X"[:-1] > > is awkward, but ... how much complexity do we want to incur avoiding it? Since Guido gave the nod to Martin for starting a pep to remove escapes from raw strings completely, this one may no longer be an issue. ;-) On another note, it may be useful to have or be able to use an alternative escape character. e&"The Windows path is C:\Foo\Bar\Baz\X\" # '&' is escape, not '\' e&"I said, &"Can you hear me now?&"" The '&' is used much less frequently than the '\' is. Raw strings wouldn't use it. ;-) The advantage in this is that many other languages use the '\' as an escape introducer. So being able to use a '&' can avoid escape character clashes if you are using python to generate code or scripts where the '\' is used frequently. And then we can have the ('\' + chr) or ('&' + chr) pairs always be an escape character. Currently '\' by it self isn't always an escape character and it's evaluated differently than for example how re evaluates it if the character following the '\' is not special. Alternatively it might be good if python raised an error on an escape sequence it doesn't recognize just as it does with the percent character. (Just looking for the little things that can be cleaned up a tiny bit, I'll leave the big Base Classes and Super issues to the experts. ;-) Cheers, Ron From castironpi at comcast.net Sat May 12 20:40:58 2007 From: castironpi at comcast.net (Aaron Brady) Date: Sat, 12 May 2007 13:40:58 -0500 Subject: [Python-ideas] parameter omit In-Reply-To: Message-ID: <20070512184112.75CFA1E4010@bag.python.org> > -----Original Message----- > From: Jim Jewett [mailto:jimjjewett at gmail.com] > Sent: Saturday, May 12, 2007 11:36 AM > > On 5/11/07, Aaron Brady wrote: > > > And while I'm at it and thinking clearly, with cool weather and open > doors, > > the basic problem here, underlying and distilled, is that None is > serving > > double-duty. > > Yes. When None appears in a parameter list (or an argument list, at > the calling site), it might really be a sentinel for something else, > and that is a wart. > > > You could always require all parameter defaults to equal `None'. But > since > > they're not, take this. > > > DefaultArg = object() > > Yes; this is used when None actually is a valid and meaningful value. > > I don't see a good way to *always* use this idiom though, because > > (1) If DefaultArg is a pre-existing object, then there will be times > when it is valid and meaningful data -- such as when introspecting. > > (2) Creating it afresh is a bit of boilerplate that we wouldn't want > to require when it isn't really needed. > > sentinel=object() > def f(val=sentinel): > if val is sentinel: > > And note that the creation can't be inline, such as > > def f(val=object()): > > or there wouldn't be any good way to test for it. Adding a keyword to do > that > > def f(val=object()): > if defaulted val: > > would probably be a good idea. (I don't think it would get used often > enough to justify the costs of a change, but there would be a clear > benefit to include in the cost-benefit calculations.) > > -jJ Can we do: > sentinel=object() > def f(val=sentinel): > if val is sentinel: sentinel=object() def f(val='utf-8'): if val is sentinel: pass f(sentinel) ? How common are non-None default values? From jimjjewett at gmail.com Sat May 12 21:10:00 2007 From: jimjjewett at gmail.com (Jim Jewett) Date: Sat, 12 May 2007 15:10:00 -0400 Subject: [Python-ideas] parameter omit In-Reply-To: <20070512184112.75CFA1E4010@bag.python.org> References: <20070512184112.75CFA1E4010@bag.python.org> Message-ID: On 5/12/07, Aaron Brady wrote: > Can we do: > sentinel=object() > def f(val='utf-8'): > if val is sentinel: Sure, but then people have to import sentinel before using it to call your function. > ? How common are non-None default values? Pretty common. They are usually (but not always) a zero of some sort (0, "", {}, []) which *could* be done with the None and type annotations in Py3. -jJ From castironpi at comcast.net Sun May 13 00:21:22 2007 From: castironpi at comcast.net (Aaron Brady) Date: Sat, 12 May 2007 17:21:22 -0500 Subject: [Python-ideas] parameter omit In-Reply-To: Message-ID: <20070512222132.0E4781E4005@bag.python.org> > -----Original Message----- > From: Jim Jewett [mailto:jimjjewett at gmail.com] > Sent: Saturday, May 12, 2007 2:10 PM > To: Aaron Brady > Cc: python-ideas at python.org > Subject: Re: [Python-ideas] parameter omit > > On 5/12/07, Aaron Brady wrote: > > Can we do: > > > sentinel=object() > > def f(val='utf-8'): > > if val is sentinel: > > Sure, but then people have to import sentinel before using it to call > your function. > > > ? How common are non-None default values? > > Pretty common. They are usually (but not always) a zero of some sort > (0, "", {}, []) which *could* be done with the None and type > annotations in Py3. > > -jJ I've gone through quite a few moods, attitudes, reading this. If you do, seek help; I am a miscreant by profession. Ranging from audacity and awe, to indignance, I have found the newsgroup on the whole to be reasonable yet stubborn. Expect me to take the other side soon. Erratic, fickle, go for it. Jewett's idea, > if defaulted val: -is- very Pythonic, blending in much better than mine. Mine isn't after all but I don't see why or how. Too bad too; it's a beaut' as ideas go. > Sure, but then people have to import sentinel before using it to call > your function. Good. Fine. From constants import True, None, Sentinel. I see in contrast. You know how many cigarettes I'd get for free if I saved all my C-Note Camelbucks? More later, if at all. From cvrebert at gmail.com Sun May 13 00:43:36 2007 From: cvrebert at gmail.com (Chris Rebert) Date: Sat, 12 May 2007 15:43:36 -0700 Subject: [Python-ideas] parameter omit In-Reply-To: <20070512184112.75CFA1E4010@bag.python.org> References: <20070512184112.75CFA1E4010@bag.python.org> Message-ID: <46464318.4050204@gmail.com> > ? How common are non-None default values? Quoting myself from http://mail.python.org/pipermail/python-3000/2007-February/005704.html ([Python-3000] pre-PEP: Default Argument Expressions), when I generated statistics related to this subject: > A survey of the standard library for Python v2.5, produced via a > script [7], gave the following statistics for the standard library > (608 files, test suites were excluded): > > total number of non-None immutable default arguments: 1585 (41.5%) > total number of mutable default arguments: 186 (4.9%) > total number of default arguments with a value of None: 1813 (47.4%) > total number of default arguments with unknown mutability: 238 (6.2%) > total number of comparisons to None: 940 So, I'd say that they're pretty frequent, with at least 41.5% of all std lib default values being non-None. - Chris Rebert From jan.kanis at phil.uu.nl Sun May 13 01:13:48 2007 From: jan.kanis at phil.uu.nl (Jan Kanis) Date: Sun, 13 May 2007 01:13:48 +0200 Subject: [Python-ideas] parameter omit In-Reply-To: <20070511180949.D387B2DC7@kleene.admin.phil.uu.nl> References: <20070511180949.D387B2DC7@kleene.admin.phil.uu.nl> Message-ID: On Fri, 11 May 2007 20:09:39 +0200, Aaron Brady wrote: >> -----Original Message----- >> From: Jan Kanis [mailto:jan.kanis at phil.uu.nl] >> Sent: Friday, May 11, 2007 6:59 AM >> >> In short, any new addition has to have a *lot* of utility to be >> acceptable, or else it wil lead to the way of the Perl side. > > Agreed entirely. You mean, like this? > > Who brings up the manual? Good. Document something. It isn't really about the manual, and I think I meant something like 'language reference' (sorry, not native English). It's about the complexity of the language. The size of the language reference can be seen as a more or less objective way to measure language complexity. Your proposal adds a little bit more complexity, and most people here agree that the benefits, which are there, are not worth it. From aahz at pythoncraft.com Sun May 13 01:30:57 2007 From: aahz at pythoncraft.com (Aahz) Date: Sat, 12 May 2007 16:30:57 -0700 Subject: [Python-ideas] the future of the GIL In-Reply-To: <464281AE.7040903@acm.org> References: <463E4645.5000503@acm.org> <20070506222840.25B2.JCARLSON@uci.edu> <4642745C.1040702@canterbury.ac.nz> <464281AE.7040903@acm.org> Message-ID: <20070512233057.GA16939@panix.com> [excessive quoting ahead to move to python-ideas from python-3000, please trim when you followup] On Wed, May 09, 2007, Talin wrote: > Greg Ewing wrote: >> Giovanni Bajo wrote: >>> >>> using multiple processes cause some >>> headaches with frozen distributions (PyInstaller, py2exe, etc.), >>> like those usually found on Windows, specifically because Windows >>> does not have fork(). >> >> Isn't that just a problem with Windows generally? I don't >> see what the method of packaging has to do with it. >> >> Also, I've seen it suggested that there may actually be >> a way of doing something equivalent to a fork in Windows, >> even though it doesn't have a fork() system call as such. >> Does anyone know more about this? > > I also wonder about embedded systems and game consoles. I don't know how > many embedded microprocessors support fork(), but I know that modern > consoles such as PS/3 and Xbox do not, since they have no support for > virtual memory at all. > > Also remember that the PS/3 is supposed to be one of the poster children > for multiprocessing -- the whole 'cell processor' thing. You can't write > an efficient game on the PS/3 unless it uses multiple processors. > > Admittedly, not many current console-based games use Python, but that > need not always be the case in the future, and a number of PC-based > games are using it already. > > This much I agree: There's no point in talking about supporting multiple > processors using threads as long as we're living in a refcounting world. > > Thought experiment: Suppose you were writing and brand-new dynamic > language today, designed to work efficiently on multi-processor systems. > Forget all of Python's legacy implementation details such as GILs and > refcounts and such. What would it look like, and how well would it > perform? (And I don't mean purely functional languages a la Erlang.) > > For example, in a language that is based on continuations at a very deep > level, there need not be any "global interpreter" at all. Each separate > flow of execution is merely a pointer to a call frame, the evaluation of > which produces a pointer to another call frame (or perhaps the same > one). Yes, there would still be some shared state that would have to be > managed, but I wouldn't think that the performance penalty of managing > that would be horrible. One of the primary goals of Python was/is to be an easy glue language for C libraries. How do you propose to handle the issue that many C libraries use global state? -- Aahz (aahz at pythoncraft.com) <*> http://www.pythoncraft.com/ "Look, it's your affair if you want to play with five people, but don't go calling it doubles." --John Cleese anticipates Usenet From greg.ewing at canterbury.ac.nz Sun May 13 02:58:59 2007 From: greg.ewing at canterbury.ac.nz (Greg Ewing) Date: Sun, 13 May 2007 12:58:59 +1200 Subject: [Python-ideas] Alternate quote delimiters In-Reply-To: References: <4644D80B.4080806@ronadam.com> Message-ID: <464662D3.9020406@canterbury.ac.nz> Jim Jewett wrote: > What if the character were limited to the opening of a > bracketed-pair, such as {[( Or is that just as bad, and less flexible > to boot? }]} This would be better, I think, as then nested occurrences of the bracket chars could be skipped without having to pick a different character for each level of quoting. It could even be restricted to just one kind of bracket if desired without losing anything. > How serious is this problem? > > r"The Windows path is C:\Foo\Bar\Baz\X"[:-1] > > is awkward, but ... how much complexity do we want to incur avoiding it? If you use os.path.join and friends to manipulate your paths (as you should!) you will hardly ever have to deal with a path containing a trailing backslash in the first place. So I wouldn't worry about it much. -- Greg From castironpi at comcast.net Sun May 13 06:41:27 2007 From: castironpi at comcast.net (Aaron Brady) Date: Sat, 12 May 2007 23:41:27 -0500 Subject: [Python-ideas] parser in stdlib In-Reply-To: Message-ID: <20070513044141.74BAE1E4006@bag.python.org> > -----Original Message----- > From: gvanrossum at gmail.com [mailto:gvanrossum at gmail.com] On Behalf Of > Guido van Rossum > Sent: Friday, May 11, 2007 9:30 PM > > On 5/11/07, Aaron Brady wrote: > > I suspect the true reason lies more with Sakkis' post [5/10 23:26 us > > central]. A mimetic structure such as Python will sit somewhere between > > restriction and liberty. Best to be deliberate in choosing a place on > the > > continuum. But where, exactly? > > What on earth is a "mimetic structure"? Please keep the jargon > understandable for the rest of us, at least if you want to be heard. > > > [snip] > > The current state is too restrictive. > > That's easy for you to say. Have you tried (*seriously* tried) to > specify such a thing? (For Python, maintaining full backwards > compatibility.) In this community, code talks. Good understandable > specs are sometimes allowed to speak. Wild ideas, especially if they > involve "let others figure out how to design and implement my idea, > but I need it now" are shown the door. > > -- > --Guido van Rossum (home page: http://www.python.org/~guido/) > What on earth is a "mimetic structure"? Please keep the jargon Any kind of framework. Policies, axioms, etc. A bit of a stretch. > Good understandable specs are sometimes allowed to speak. Here is the potential seed of compromise. >>> import compiler >>> compiler.suite( 'tok1 id2' ) Module(None, Stmt([Name('a')), Name('b'))])) The ASTVisitor raises a SyntaxError prior to execution. From taleinat at gmail.com Sun May 13 11:07:44 2007 From: taleinat at gmail.com (Tal Einat) Date: Sun, 13 May 2007 12:07:44 +0300 Subject: [Python-ideas] Alternate quote delimiters In-Reply-To: <464662D3.9020406@canterbury.ac.nz> References: <4644D80B.4080806@ronadam.com> <464662D3.9020406@canterbury.ac.nz> Message-ID: <7afdee2f0705130207v144f033fm5468ad2ba432fe29@mail.gmail.com> On 5/13/07, Greg Ewing wrote: > > Jim Jewett wrote: > > > How serious is this problem? > > > > r"The Windows path is C:\Foo\Bar\Baz\X"[:-1] > > > > is awkward, but ... how much complexity do we want to incur avoiding it? > > If you use os.path.join and friends to manipulate your > paths (as you should!) you will hardly ever have to deal > with a path containing a trailing backslash in the first > place. So I wouldn't worry about it much. When learning Python, new users often get bitten by this. Simple learning exercises often leave os.path for later, and use simpler hard-coded file paths instead. When teaching Python, this is one more sharp edge I'm forced to warn new users about. I also hear people complaining about this when using Python for simple automation scripts, where hard-coded paths are common, and using os.path can easily double the amount of code and its complexity for no extra functionality. (Yes, the [:-1] hack works, but it's ugly, and Python should be beautiful.) I'm sure the "completely remove escapes from raw strings" PEP will solve this issue, and I'm looking forward to it. - Tal -------------- next part -------------- An HTML attachment was scrubbed... URL: From castironpi at comcast.net Sun May 13 22:27:59 2007 From: castironpi at comcast.net (Aaron Brady) Date: Sun, 13 May 2007 15:27:59 -0500 Subject: [Python-ideas] parser in stdlib In-Reply-To: <20070511042520.19A5E1E4003@bag.python.org> Message-ID: <20070513202808.E6B011E4007@bag.python.org> > -----Original Message----- > From: python-ideas-bounces+castironpi=comcast.net at python.org > [mailto:python-ideas-bounces+castironpi=comcast.net at python.org] On Behalf > Of Aaron Brady > > > -----Original Message----- > > From: python-ideas-bounces at python.org [mailto:python-ideas- > > bounces at python.org] On Behalf Of Terry Reedy > > [snip] > > I've very much looked into it. In fact, it gave rise to the follow-up > idea > of attaching a `firstlineno' attribute to class objects. (18:12 American > Central Time.) Rather costly, 50% of the attributes, but stepping through > the InteractiveCodeGenerator class hasn't failed yet. This is better. Inspect.getsource( AClass ) can be wrong. Raise exceptions before that happens. import inspect class A: b=1 class A: b=2 B=A print inspect.getsource(B) Output is: class A: b=1 Which is not what I asked it. Return candidates maybe? From castironpi at comcast.net Sun May 13 23:37:09 2007 From: castironpi at comcast.net (Aaron Brady) Date: Sun, 13 May 2007 16:37:09 -0500 Subject: [Python-ideas] parameter omit In-Reply-To: Message-ID: <20070513213716.B115F1E400D@bag.python.org> > -----Original Message----- > From: Jim Jewett [mailto:jimjjewett at gmail.com] > Sent: Saturday, May 12, 2007 11:36 AM > > def f(val=object()): > if defaulted val: Might this create a option to omit required parameters too? From castironpi at comcast.net Mon May 14 00:50:55 2007 From: castironpi at comcast.net (Aaron Brady) Date: Sun, 13 May 2007 17:50:55 -0500 Subject: [Python-ideas] parameter omit In-Reply-To: <7afdee2f0705111714s60118d8cuc219765830b3f59f@mail.gmail.com> Message-ID: <20070513225103.BE04B1E400A@bag.python.org> > -----Original Message----- > From: Tal Einat [mailto:taleinat at gmail.com] > Sent: Friday, May 11, 2007 7:15 PM > > > > MenuBarItem = MainMenuBar.Controls.Add( > > Office.MsoControlType.msoControlPopup, > > Type.Missing, Type.Missing, Type.Missing, true); MenuBarItem = MainMenuBar.Controls.Add( *[Office.MsoControlType.msoControlPopup] + [Type.Missing]*3 + [true]); > > Excel.Application excelApp = new Excel.ApplicationClass (); > > Excel.Workbook thisWorkbook = > > excelApp.Workbooks.Open(strFileName,Type.Missing, Type.Missing, > > Type.Missing, Type.Missing,Type.Missing, Type.Missing, > Type.Missing, > > Type.Missing,Type.Missing , Type.Missing, Type.Missing, > > Type.Missing,Type.Missing, Type.Missing); Excel.Workbook thisWorkbook = excelApp.Workbooks.Open( *[strFileName] + [Type.Missing]*14 ); From rrr at ronadam.com Mon May 14 01:57:24 2007 From: rrr at ronadam.com (Ron Adam) Date: Sun, 13 May 2007 18:57:24 -0500 Subject: [Python-ideas] parameter omit In-Reply-To: <20070509202544.CC7471E4002@bag.python.org> References: <20070509202544.CC7471E4002@bag.python.org> Message-ID: <4647A5E4.5070300@ronadam.com> Aaron Brady wrote: > Is it possible to signal to a parameter to use its default? > > > def f( a, b=None, c=?? ):... > > f( 123, , ?abc? ) > > f( 123, ObjA, ) > > > Did I miss something, plus did you cover it before? You might be able to make a decorator that handles this the way you describe. It might look something like the following. class DefaultValue(object): """ An signal object. """ pass DfV = DefaultValue() # Default value signal object def defaults(*args): " a decorator that assigns and checks defaults values." ... @defaults(None, None, '') def f(a, b, c): return a, b, c Then you could do as you wrote above and get something like... >>> f(123, DfV, 'abc') 123, None, 'abc' >>> f(123, ObjA, DfV) 123, , '' I'll leave the actual implementation to you. It might be useful in cases where you want the calling signature to look alike for a group of dispatched functions and the added overhead the decorator adds isn't a problem. But you probably wouldn't want that overhead all the time, so having it as an optional decorator would be good. Cheers, Ron From castironpi at comcast.net Mon May 14 02:32:08 2007 From: castironpi at comcast.net (Aaron Brady) Date: Sun, 13 May 2007 19:32:08 -0500 Subject: [Python-ideas] parameter omit In-Reply-To: <4647A5E4.5070300@ronadam.com> Message-ID: <20070514003216.278961E4007@bag.python.org> > -----Original Message----- > From: Ron Adam [mailto:rrr at ronadam.com] > Sent: Sunday, May 13, 2007 6:57 PM > To: Aaron Brady; python-ideas at python.org > Subject: Re: [Python-ideas] parameter omit > > Aaron Brady wrote: > [snip] > > You might be able to make a decorator that handles this the way you > describe. > > > It might look something like the following. > [snip] > @defaults(None, None, '') > def f(a, b, c): > return a, b, c Great ideas. It turned out really nicely. class GuardDefault: Val= object() def __call__( self, *args, **kwargs ): args=list(args) for i,j in enumerate( args ): if j is GuardDefault.Val: offset= self.callable.func_code.co_argcount-\ len(self.callable.func_defaults) args[i]= self.callable.func_defaults[i-offset] return self.callable( *args,**kwargs ) def __init__( self,callable ): self.callable= callable @GuardDefault def f( a,b=None,c='abc' ): print a,b,c f( 0,GuardDefault.Val,'def' ) f( 0,'somebody',GuardDefault.Val ) gives: 0 None def 0 somebody abc From castironpi at comcast.net Mon May 14 03:09:48 2007 From: castironpi at comcast.net (Aaron Brady) Date: Sun, 13 May 2007 20:09:48 -0500 Subject: [Python-ideas] python appreciation site Message-ID: <20070514010956.2423B1E4007@bag.python.org> This is a joke, for austerity. http://home.comcast.net/~castironpi/pythonappr.html From adam at atlas.st Mon May 14 03:26:57 2007 From: adam at atlas.st (Adam Atlas) Date: Sun, 13 May 2007 21:26:57 -0400 Subject: [Python-ideas] python appreciation site In-Reply-To: <20070514010956.2423B1E4007@bag.python.org> References: <20070514010956.2423B1E4007@bag.python.org> Message-ID: On 13 May 2007, at 21.09, Aaron Brady wrote: > This is a joke, for austerity. > > http://home.comcast.net/~castironpi/pythonappr.html Nice! I think that deserves to go on . My favourite is the Cobol one. :) From castironpi at comcast.net Mon May 14 04:28:23 2007 From: castironpi at comcast.net (Aaron Brady) Date: Sun, 13 May 2007 21:28:23 -0500 Subject: [Python-ideas] parameter omit In-Reply-To: <20070514003216.278961E4007@bag.python.org> Message-ID: <20070514022832.0638E1E4007@bag.python.org> > -----Original Message----- > From: python-ideas-bounces at python.org [mailto:python-ideas- > bounces at python.org] On Behalf Of Aaron Brady > > class GuardDefault: > Val= object() > def __call__( self, *args, **kwargs ): > args=list(args) > for i,j in enumerate( args ): > if j is GuardDefault.Val: > offset= > self.callable.func_code.co_argcount-\ > len(self.callable.func_defaults) > args[i]= > self.callable.func_defaults[i-offset] > return self.callable( *args,**kwargs ) > def __init__( self,callable ): > self.callable= callable Do you have any interest in pursuing this? From castironpi at comcast.net Mon May 14 08:19:36 2007 From: castironpi at comcast.net (Aaron Brady) Date: Mon, 14 May 2007 01:19:36 -0500 Subject: [Python-ideas] python appreciation site In-Reply-To: Message-ID: <20070514061945.DBAE41E4009@bag.python.org> > -----Original Message----- > From: python-ideas-bounces at python.org [mailto:python-ideas- > bounces at python.org] On Behalf Of Adam Atlas > Sent: Sunday, May 13, 2007 8:27 PM > To: Python-Ideas > Subject: Re: [Python-ideas] python appreciation site > > > On 13 May 2007, at 21.09, Aaron Brady wrote: > > This is a joke, for austerity. > > > > http://home.comcast.net/~castironpi/pythonappr.html > > Nice! I think that deserves to go on Humor.html>. > > My favourite is the Cobol one. :) > _______________________________________________ > Python-ideas mailing list > Python-ideas at python.org > http://mail.python.org/mailman/listinfo/python-ideas Put it up there! From rajb at rice.edu Mon May 14 18:53:11 2007 From: rajb at rice.edu (Raj B) Date: Mon, 14 May 2007 11:53:11 -0500 Subject: [Python-ideas] Function/method call issues Message-ID: Hello everyone, First of all, I'll introduce myself. I've been working on a Python compiler written in OCaml for about a year now. Some of you might know me from my talk at Google. One of the list members suggested this mailing list as a good forum for discussion and bouncing ideas. I think that one issue to consider are the complex semantics of functions and method calls. Whenever a function call is made, there is a lot of checking involved as to 'where' the function is called from: i.e. whether it's a user-defined function/method, a built-in function/method, a class function/method or an instance function/ method. Just reading the reference manual section on 'function objects' is enough to see how many different cases are there. Of course, this provides tons of flexibility in reusing the same code for different ways. However, it increases the amount of book-keeping and pre-processing required for a call. For example, Consider an object that implements methods 'str' and 'append' (the list object, for instance). During retrieval of methods, the following default retrieval method is called (in OCaml syntax, a simplified version). let list_getattr o attr = let v = get o.dict attr in (* lookup the attribute in the dictionary *) match attr with | String "append" | ... | -> v.instance = o; v (* set the method's instance to o before returning it *) | _ -> v (* else return the method object as is *) So basically, I have to check for two cases based on the actual names of the methods being called. This seems like extra work for the runtime. As a suggestion, I think that adopting a single calling convention (either 'x.foo()' or 'foo(x)') would have 2 advantages. 1) It would make it easier for users and make for more readable code. I still find myself having to refer to the docs to find out how a method needs to be called. 2) It would improve performance by reducing these checks shown above to one case. What do y'all think? Would this sacrifice too much flexibility? If this topic has been discussed on this list before, please feel free to point me there. Thank you Raj From tjreedy at udel.edu Mon May 14 20:41:47 2007 From: tjreedy at udel.edu (Terry Reedy) Date: Mon, 14 May 2007 14:41:47 -0400 Subject: [Python-ideas] Function/method call issues References: Message-ID: "Raj B" wrote in message news:AAD8D5AB-96A1-4503-A90B-B037CAFA13EB at rice.edu... | Hello everyone, | | First of all, I'll introduce myself. I've been working on a Python | compiler written in OCaml for about a year now. Some of you might | know me from my talk at Google. One of the list members suggested | this mailing list as a good forum for discussion and bouncing ideas. | | I think that one issue to consider are the complex semantics of | functions and method calls. Whenever a function call is made, there | is a lot of checking involved as to 'where' the function is called | from: i.e. whether it's a user-defined function/method, a built-in | function/method, a class function/method or an instance function/ | method. Just reading the reference manual section on 'function | objects' is enough to see how many different cases are there. | | Of course, this provides tons of flexibility in reusing the same code | for different ways. However, it increases the amount of book-keeping | and pre-processing required for a call. For example, Consider an | object that implements methods 'str' and 'append' (the list object, | for instance). During retrieval of methods, the following default | retrieval method is called (in OCaml syntax, a simplified version). | | let list_getattr o attr = | let v = get o.dict attr in (* lookup the attribute in the dictionary *) | | match attr with | | String "append" | ... | -> | v.instance = o; v (* set the method's instance to o | before returning it *) | | | _ -> v (* else return the method object as is *) I cannot understand above, even 'simplified'. | So basically, I have to check for two cases based on the actual names | of the methods being called. This seems like extra work for the runtime. | | As a suggestion, I think that adopting a single calling convention | (either 'x.foo()' or 'foo(x)') would have 2 advantages. If foo is an instance method, the latter has to be x.__class__.foo(x). There is no way to disallow the latter; but the former is much easier. | 1) It would make it easier for users and make for more readable code. | I still find myself having to refer to the docs to find out how a | method needs to be called. I do not understand 'needs'. Any instance method can be called either way, with the first much easier. Knowing about the second is mainly needed to understand why instance methods all have a self parameter. | 2) It would improve performance by reducing these checks shown above | to one case. tjr From jcarlson at uci.edu Mon May 14 20:53:11 2007 From: jcarlson at uci.edu (Josiah Carlson) Date: Mon, 14 May 2007 11:53:11 -0700 Subject: [Python-ideas] Function/method call issues In-Reply-To: References: Message-ID: <20070514114644.855C.JCARLSON@uci.edu> Raj B wrote: > 1) It would make it easier for users and make for more readable code. > I still find myself having to refer to the docs to find out how a > method needs to be called. > 2) It would improve performance by reducing these checks shown above > to one case. foo(x) means one thing. x.foo() means another. Trying to merge them for the sake of "consistency" will only confuse everyone who has been using method calling (x.foo()) to call methods on an object (making every function call into a generic function that users don't know if it is really just a generic function, or a method caller), or will give all objects in which you want to call the function foo() on have a method x.foo() (making every method call indistinguishable as to whether you are calling the function foo with argument x, or method foo on object x). While it may make it easier for you to implement in OCaml, it makes no sense in terms of Python sementics that are understood by basically everyone for at least 10 years. - Josiah From rajb at rice.edu Mon May 14 21:52:53 2007 From: rajb at rice.edu (Raj B) Date: Mon, 14 May 2007 14:52:53 -0500 Subject: [Python-ideas] Function/method call issues In-Reply-To: <20070514114644.855C.JCARLSON@uci.edu> References: <20070514114644.855C.JCARLSON@uci.edu> Message-ID: <38D88956-0540-4EC1-87D3-E15736A2D312@rice.edu> Well, this definitely makes no difference to me to implement in OCaml or any other language. I'm implementing exactly how Python behaves, so whether it's easy or difficult is not really the question. Consider the list object (listobject.c). In CPython, the 'repr' method for integers is implemented by the 'list_repr' function and the 'insert operation is implemented by 'listinsert', which in turn is part of the 'list_as_sequence' set of methods. So it both 'repr' and 'insert' are implemented as 'methods'. However, the Python convention is that 'repr' is called as repr(l) whereas insert would be l.insert(i,v), with l passed implicitly. In both cases, they are performing almost the same amount of work in looking up a function in a PyObject structure (with two lookups for 'repr' and three for 'insert'). Obviously there is a design/ implementation/philosophical decision that one is a generic function and the other is a method call. However, the implementation has to do 2 different things based on the name of the function to be called, even though they are both part of the same object structure. I was wondering why it was necessary to do it that way. Thanks Raj On May 14, 2007, at 1:53 PM, Josiah Carlson wrote: > > Raj B wrote: >> 1) It would make it easier for users and make for more readable code. >> I still find myself having to refer to the docs to find out how a >> method needs to be called. >> 2) It would improve performance by reducing these checks shown above >> to one case. > > foo(x) means one thing. x.foo() means another. Trying to merge them > for the sake of "consistency" will only confuse everyone who has been > using method calling (x.foo()) to call methods on an object (making > every function call into a generic function that users don't know > if it > is really just a generic function, or a method caller), or will > give all > objects in which you want to call the function foo() on have a method > x.foo() (making every method call indistinguishable as to whether you > are calling the function foo with argument x, or method foo on > object x). > > While it may make it easier for you to implement in OCaml, it makes no > sense in terms of Python sementics that are understood by basically > everyone for at least 10 years. > > > - Josiah -- When you are not cute, you've got to be clever -- David Sedaris From jcarlson at uci.edu Mon May 14 22:23:56 2007 From: jcarlson at uci.edu (Josiah Carlson) Date: Mon, 14 May 2007 13:23:56 -0700 Subject: [Python-ideas] Function/method call issues In-Reply-To: <38D88956-0540-4EC1-87D3-E15736A2D312@rice.edu> References: <20070514114644.855C.JCARLSON@uci.edu> <38D88956-0540-4EC1-87D3-E15736A2D312@rice.edu> Message-ID: <20070514130706.8566.JCARLSON@uci.edu> Please don't top post, it unnecessarily removes context for replies that help in understanding (most people read top to bottom, not bottom to top). Raj B wrote: > Well, this definitely makes no difference to me to implement in OCaml > or any other language. I'm implementing exactly how Python behaves, > so whether it's easy or difficult is not really the question. > > Consider the list object (listobject.c). In CPython, the 'repr' > method for integers is implemented by the 'list_repr' function and (repr(5) is implemented as int_repr() in intobject.c) > the 'insert operation is implemented by 'listinsert', which in turn > is part of the 'list_as_sequence' set of methods. So it both 'repr' > and 'insert' are implemented as 'methods'. However, the Python > convention is that 'repr' is called as repr(l) whereas insert would > be l.insert(i,v), with l passed implicitly. You are not going to change the oft-discussed, long-time established __magic__ method and magic() builtins. That is to say, certain builtin functions (and some operations) result in a method invocation of obj.__magic__() (sometimes with additional arguments). This is not going to change. Please see the various Python 3.0 PEPs. Among those are len(), repr(), etc., as well as functions listed in operator module. Why? Generally, finding the length of an object has been defined to be discovered by len(obj). While it is internally translated into obj.__len__(), this is to allow for user methods to take on names that could otherwise clash with standard methods. > In both cases, they are performing almost the same amount of work in > looking up a function in a PyObject structure (with two lookups for > 'repr' and three for 'insert'). Obviously there is a design/ > implementation/philosophical decision that one is a generic function > and the other is a method call. However, the implementation has to do > 2 different things based on the name of the function to be called, > even though they are both part of the same object structure. I was > wondering why it was necessary to do it that way. Convenience, flexibility, established semantics, etc. To change it would be a major language overhaul for little (if any, if not negative) Python user gains. - Josiah > On May 14, 2007, at 1:53 PM, Josiah Carlson wrote: > > > > > Raj B wrote: > >> 1) It would make it easier for users and make for more readable code. > >> I still find myself having to refer to the docs to find out how a > >> method needs to be called. > >> 2) It would improve performance by reducing these checks shown above > >> to one case. > > > > foo(x) means one thing. x.foo() means another. Trying to merge them > > for the sake of "consistency" will only confuse everyone who has been > > using method calling (x.foo()) to call methods on an object (making > > every function call into a generic function that users don't know > > if it > > is really just a generic function, or a method caller), or will > > give all > > objects in which you want to call the function foo() on have a method > > x.foo() (making every method call indistinguishable as to whether you > > are calling the function foo with argument x, or method foo on > > object x). > > > > While it may make it easier for you to implement in OCaml, it makes no > > sense in terms of Python sementics that are understood by basically > > everyone for at least 10 years. > > > > > > - Josiah > > -- > When you are not cute, you've got to be clever > -- David Sedaris > From castironpi at comcast.net Tue May 15 08:45:32 2007 From: castironpi at comcast.net (Aaron Brady) Date: Tue, 15 May 2007 01:45:32 -0500 Subject: [Python-ideas] parameter omit Message-ID: <20070515064546.663581E4016@bag.python.org> > -----Original Message----- > From: Aaron Brady [mailto:castironpi at comcast.net] > Sent: Sunday, May 13, 2007 9:28 PM > > > -----Original Message----- > > From: python-ideas-bounces at python.org [mailto:python-ideas- > > bounces at python.org] On Behalf Of Aaron Brady > > > > class GuardDefault: > > Val= object() > > def __call__( self, *args, **kwargs ): > > args=list(args) > > for i,j in enumerate( args ): > > if j is GuardDefault.Val: > > offset= > > self.callable.func_code.co_argcount-\ > > len(self.callable.func_defaults) > > args[i]= > > self.callable.func_defaults[i-offset] > > return self.callable( *args,**kwargs ) > > def __init__( self,callable ): > > self.callable= callable > > Do you have any interest in pursuing this? Actually not too bad for functools. Does this take a proposal? -I- am God-awful at lengthy technical writing. From steven.bethard at gmail.com Tue May 15 08:53:46 2007 From: steven.bethard at gmail.com (Steven Bethard) Date: Tue, 15 May 2007 00:53:46 -0600 Subject: [Python-ideas] parameter omit In-Reply-To: <20070515064546.663581E4016@bag.python.org> References: <20070515064546.663581E4016@bag.python.org> Message-ID: On 5/15/07, Aaron Brady wrote: > > -----Original Message----- > > From: Aaron Brady [mailto:castironpi at comcast.net] > > Sent: Sunday, May 13, 2007 9:28 PM > > > > > -----Original Message----- > > > From: python-ideas-bounces at python.org [mailto:python-ideas- > > > bounces at python.org] On Behalf Of Aaron Brady > > > > > > class GuardDefault: > > > Val= object() > > > def __call__( self, *args, **kwargs ): > > > args=list(args) > > > for i,j in enumerate( args ): > > > if j is GuardDefault.Val: > > > offset= > > > self.callable.func_code.co_argcount-\ > > > len(self.callable.func_defaults) > > > args[i]= > > > self.callable.func_defaults[i-offset] > > > return self.callable( *args,**kwargs ) > > > def __init__( self,callable ): > > > self.callable= callable > > > > Do you have any interest in pursuing this? > > Actually not too bad for functools. Does this take a proposal? -I- am > God-awful at lengthy technical writing. You might be able to get away without a PEP, but you'll definitely need to post an implementation patch to the bug tracker (http://sourceforge.net/tracker/?group_id=5470&atid=105470). Once you've posted your implementation, you should send an email to python-dev asking folks what they think about it. Be sure to give some code examples that using this decorator would simplify. STeVe -- I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a tiny blip on the distant coast of sanity. --- Bucky Katt, Get Fuzzy From rrr at ronadam.com Tue May 15 14:39:22 2007 From: rrr at ronadam.com (Ron Adam) Date: Tue, 15 May 2007 07:39:22 -0500 Subject: [Python-ideas] parameter omit In-Reply-To: <200705142344234.SM01928@sccrmhc11.comcast.net> References: <200705142344234.SM01928@sccrmhc11.comcast.net> Message-ID: <4649A9FA.7030208@ronadam.com> Aaron Brady wrote: >> -----Original Message----- >> From: Aaron Brady [mailto:castironpi at comcast.net] >> Sent: Sunday, May 13, 2007 9:28 PM >> >>> -----Original Message----- >>> From: python-ideas-bounces at python.org [mailto:python-ideas- >>> bounces at python.org] On Behalf Of Aaron Brady >>> >>> class GuardDefault: >>> Val= object() >>> def __call__( self, *args, **kwargs ): >>> args=list(args) >>> for i,j in enumerate( args ): >>> if j is GuardDefault.Val: >>> offset= >>> self.callable.func_code.co_argcount-\ >>> len(self.callable.func_defaults) >>> args[i]= >>> self.callable.func_defaults[i-offset] >>> return self.callable( *args,**kwargs ) >>> def __init__( self,callable ): >>> self.callable= callable >> Do you have any interest in pursuing this? > > Actually not too bad for functools. Does this take a proposal? -I- am > God-awful at lengthy technical writing. I suggest you post it on the python-list firsts and see what others think. They may offer alternative ways of doing it that will make it better based on how they will used it. Cheers, Ron From ian.bollinger at gmail.com Tue May 15 16:53:57 2007 From: ian.bollinger at gmail.com (Ian D. Bollinger) Date: Tue, 15 May 2007 10:53:57 -0400 Subject: [Python-ideas] Have list/deque grow a copy() method Message-ID: <4649C985.7050100@gmail.com> It would be nice if containers had a more consistent interface. The standard idiom for copying a list has been L[:], but this isn't polymorphic and perhaps arcane. Also, deques can only be copied with the copy module's copy function (or calling the __copy__ wrapper directly); thus using copy.copy is the only polymorphic way to copy a mutable container. Additionally, having a consistent interface for mutable containers may dovetail with the ABC PEP. An alternate proposal would be to move copy.copy (and perhaps copy.deepcopy) into __builtins__. (Though this might be nice regardless.) As an aside, in addition to the copy method, list is the only mutable container not to have a clear method. Of course, del L[:] is the standard idiom for doing so, but this has the same problem of not being polymorphic. Perhaps having both del L[:] and L.clear() would violate the TOOWTDI principle, but L.reverse() can also be done with L = L[::-1] (maybe not the best example since they have different semantics.) Nevertheless, one is a lot easier to read. As for a use case, one might be a class that generalizes how it stores elements. For instance... class MutableUnorderedTree(AbstractTree): _storage_class = set class MutableOrderedTree(AbstractTree): _storage_class = list ...the latter has to be adapted to ensure consistent interface for methods like copy/clear. Well, that's my crackpot idea for today. - Ian D. Bolligner From jcarlson at uci.edu Tue May 15 17:11:58 2007 From: jcarlson at uci.edu (Josiah Carlson) Date: Tue, 15 May 2007 08:11:58 -0700 Subject: [Python-ideas] Have list/deque grow a copy() method In-Reply-To: <4649C985.7050100@gmail.com> References: <4649C985.7050100@gmail.com> Message-ID: <20070515080638.8569.JCARLSON@uci.edu> "Ian D. Bollinger" wrote: > It would be nice if containers had a more consistent interface. The > standard idiom for copying a list has been L[:], but this isn't The standard way of copying a list (or producing a list from an arbitrary sequence) is list(L). > polymorphic and perhaps arcane. Also, deques can only be copied with the > copy module's copy function (or calling the __copy__ wrapper directly); No, you can use deque(D). > As an aside, in addition to the copy method, list is the only mutable > container not to have a clear method. Of course, del L[:] is the > standard idiom for doing so, but this has the same problem of not being > polymorphic. Perhaps having both del L[:] and L.clear() would violate > the TOOWTDI principle, but L.reverse() can also be done with L = L[::-1] > (maybe not the best example since they have different semantics.) > Nevertheless, one is a lot easier to read. I'm -0 on list.clear(), but can see why people would prefer it over del L[:] . Regarding your main proposal of inserting copy.copy into the builtins, I'm -1. Using the object constructors themselves as copying/creation procedures is generally seen to be a good practice, as it also typically allows users to pass *any* iterable and have it end up in a format that the recipient of the data wants. - Josiah From g.brandl at gmx.net Tue May 15 17:10:35 2007 From: g.brandl at gmx.net (Georg Brandl) Date: Tue, 15 May 2007 17:10:35 +0200 Subject: [Python-ideas] Have list/deque grow a copy() method In-Reply-To: <20070515080638.8569.JCARLSON@uci.edu> References: <4649C985.7050100@gmail.com> <20070515080638.8569.JCARLSON@uci.edu> Message-ID: Josiah Carlson schrieb: > "Ian D. Bollinger" wrote: >> It would be nice if containers had a more consistent interface. The >> standard idiom for copying a list has been L[:], but this isn't > > The standard way of copying a list (or producing a list from an > arbitrary sequence) is list(L). The first part is news to me. Who defined that standard? Georg From fdrake at acm.org Tue May 15 17:21:44 2007 From: fdrake at acm.org (Fred L. Drake, Jr.) Date: Tue, 15 May 2007 11:21:44 -0400 Subject: [Python-ideas] Have list/deque grow a copy() method In-Reply-To: <4649C985.7050100@gmail.com> References: <4649C985.7050100@gmail.com> Message-ID: <200705151121.45297.fdrake@acm.org> On Tuesday 15 May 2007, Ian D. Bollinger wrote: > It would be nice if containers had a more consistent interface. The > standard idiom for copying a list has been L[:], but this isn't > polymorphic and perhaps arcane. Also, deques can only be copied with the > copy module's copy function (or calling the __copy__ wrapper directly); > thus using copy.copy is the only polymorphic way to copy a mutable > container. Additionally, having a consistent interface for mutable > containers may dovetail with the ABC PEP. copy.copy() and copy.deepcopy() have always been the only polymorphic ways to create copies. Is there any real motivation not to just use them? I've not found that I need a way to copy arbitrary objects very often, and haven't found the occaissional import of the copy module to be an obstruction. Are you needing to create lots of copies for some reason? -Fred -- Fred L. Drake, Jr. From steven.bethard at gmail.com Tue May 15 17:48:13 2007 From: steven.bethard at gmail.com (Steven Bethard) Date: Tue, 15 May 2007 09:48:13 -0600 Subject: [Python-ideas] Have list/deque grow a copy() method In-Reply-To: <200705151121.45297.fdrake@acm.org> References: <4649C985.7050100@gmail.com> <200705151121.45297.fdrake@acm.org> Message-ID: On 5/15/07, Fred L. Drake, Jr. wrote: > On Tuesday 15 May 2007, Ian D. Bollinger wrote: > > It would be nice if containers had a more consistent interface. The > > standard idiom for copying a list has been L[:], but this isn't > > polymorphic and perhaps arcane. Also, deques can only be copied with the > > copy module's copy function (or calling the __copy__ wrapper directly); > > thus using copy.copy is the only polymorphic way to copy a mutable > > container. Additionally, having a consistent interface for mutable > > containers may dovetail with the ABC PEP. > > copy.copy() and copy.deepcopy() have always been the only polymorphic ways to > create copies. For builtin container types (and many other container types as well): type(obj)(obj) is another polymorphic way to create copies. STeVe -- I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a tiny blip on the distant coast of sanity. --- Bucky Katt, Get Fuzzy From fdrake at acm.org Tue May 15 18:06:49 2007 From: fdrake at acm.org (Fred L. Drake, Jr.) Date: Tue, 15 May 2007 12:06:49 -0400 Subject: [Python-ideas] Have list/deque grow a copy() method In-Reply-To: References: <4649C985.7050100@gmail.com> <200705151121.45297.fdrake@acm.org> Message-ID: <200705151206.50034.fdrake@acm.org> On Tuesday 15 May 2007, Steven Bethard wrote: > For builtin container types (and many other container types as well): > type(obj)(obj) > is another polymorphic way to create copies. If you're willing to rely on the constructor signature, sure. For many applications, the convention that the constructor can be used as a copier doesn't hold. -Fred -- Fred L. Drake, Jr. From jcarlson at uci.edu Tue May 15 22:47:09 2007 From: jcarlson at uci.edu (Josiah Carlson) Date: Tue, 15 May 2007 13:47:09 -0700 Subject: [Python-ideas] Have list/deque grow a copy() method In-Reply-To: <200705151206.50034.fdrake@acm.org> References: <200705151206.50034.fdrake@acm.org> Message-ID: <20070515134615.8572.JCARLSON@uci.edu> "Fred L. Drake, Jr." wrote: > > On Tuesday 15 May 2007, Steven Bethard wrote: > > For builtin container types (and many other container types as well): > > type(obj)(obj) > > is another polymorphic way to create copies. > > If you're willing to rely on the constructor signature, sure. For many > applications, the convention that the constructor can be used as a copier > doesn't hold. But for builtin types (which is the only objects we can reliably change), using the base constructor to copy an object *does* work for all container types (except for defaultdict). - Josiah From jcarlson at uci.edu Tue May 15 22:54:07 2007 From: jcarlson at uci.edu (Josiah Carlson) Date: Tue, 15 May 2007 13:54:07 -0700 Subject: [Python-ideas] Have list/deque grow a copy() method In-Reply-To: References: <20070515080638.8569.JCARLSON@uci.edu> Message-ID: <20070515134716.8575.JCARLSON@uci.edu> Georg Brandl wrote: > Josiah Carlson schrieb: > > "Ian D. Bollinger" wrote: > >> It would be nice if containers had a more consistent interface. The > >> standard idiom for copying a list has been L[:], but this isn't > > > > The standard way of copying a list (or producing a list from an > > arbitrary sequence) is list(L). > > The first part is news to me. Who defined that standard? No one needs to define a standard for it to be the standard. How would you propose, generally, to convert some arbitrary sequence into a list? Would you use a list comprehension: [i for i in seq] ? Would you use a generator expression passed to a list: list(i for i in seq) ? Or would you just use list(seq)? Me, I prefer simplicity and the case that works the way I usually need it to: list(seq). Conveniently, this works for list(dct), list(lst), list(deq), list(st), list(uni), list(tup), list(ite), ... To not use list(obj) when you can would seem to me to be an anti-pattern, regardless of the minor opimization that can be had in lst[:] copying. This technique is also going to be used in the 2to3 conversion utility to convert range() calls to list(range()) calls, and I am honestly baffled by anyone asking, "how do I copy a list, deque, dictionary,...". How could one *not* look at the base constructors? - Josiah From g.brandl at gmx.net Tue May 15 22:54:41 2007 From: g.brandl at gmx.net (Georg Brandl) Date: Tue, 15 May 2007 22:54:41 +0200 Subject: [Python-ideas] Have list/deque grow a copy() method In-Reply-To: <20070515134716.8575.JCARLSON@uci.edu> References: <20070515080638.8569.JCARLSON@uci.edu> <20070515134716.8575.JCARLSON@uci.edu> Message-ID: Josiah Carlson schrieb: > Georg Brandl wrote: >> Josiah Carlson schrieb: >> > "Ian D. Bollinger" wrote: >> >> It would be nice if containers had a more consistent interface. The >> >> standard idiom for copying a list has been L[:], but this isn't >> > >> > The standard way of copying a list (or producing a list from an >> > arbitrary sequence) is list(L). >> >> The first part is news to me. Who defined that standard? > > No one needs to define a standard for it to be the standard. How would > you propose, generally, to convert some arbitrary sequence into a list? No, I meant the "copying a list" part. Getting a list from an iterable is easiest with list(), of course. Georg From jcarlson at uci.edu Tue May 15 23:12:16 2007 From: jcarlson at uci.edu (Josiah Carlson) Date: Tue, 15 May 2007 14:12:16 -0700 Subject: [Python-ideas] Have list/deque grow a copy() method In-Reply-To: References: <20070515134716.8575.JCARLSON@uci.edu> Message-ID: <20070515140958.8578.JCARLSON@uci.edu> Georg Brandl wrote: > Josiah Carlson schrieb: > > Georg Brandl wrote: > >> Josiah Carlson schrieb: > >> > "Ian D. Bollinger" wrote: > >> >> It would be nice if containers had a more consistent interface. The > >> >> standard idiom for copying a list has been L[:], but this isn't > >> > > >> > The standard way of copying a list (or producing a list from an > >> > arbitrary sequence) is list(L). > >> > >> The first part is news to me. Who defined that standard? > > > > No one needs to define a standard for it to be the standard. How would > > you propose, generally, to convert some arbitrary sequence into a list? > > No, I meant the "copying a list" part. Getting a list from an iterable is > easiest with list(), of course. I choose as standard what works in the most cases. Since list() works everywhere, using it on lists makes the most sense to me. - Josiah From castironpi at comcast.net Wed May 16 12:54:53 2007 From: castironpi at comcast.net (Aaron Brady) Date: Wed, 16 May 2007 05:54:53 -0500 Subject: [Python-ideas] dot bend spoon Message-ID: <20070516105510.26D531E4002@bag.python.org> Is the going semantic to carry a relation: spoon.bend() or johnson.bend( spoon ) ? How to phrase this. How do -you- do it? Weird. Because spoon.bend() is a misnomer; construed to mean spoon.getsbent(). More in the predicate vs. controller category. Haven't got model-view-controller yet but I know the term. From adam at atlas.st Wed May 16 14:21:46 2007 From: adam at atlas.st (Adam Atlas) Date: Wed, 16 May 2007 08:21:46 -0400 Subject: [Python-ideas] dot bend spoon In-Reply-To: <20070516105510.26D531E4002@bag.python.org> References: <20070516105510.26D531E4002@bag.python.org> Message-ID: <98B0F0E9-A048-4BD3-B72B-5779F78500BB@atlas.st> On 16 May 2007, at 06.54, Aaron Brady wrote: > Is the going semantic to carry a relation: > > spoon.bend() > > or > > johnson.bend( spoon ) ? This is probably more appropriate for the usual comp.lang.python group rather than Python-ideas, no? In any case, this would probably be an easier question to answer with a more realistic example. From george.sakkis at gmail.com Wed May 16 16:50:40 2007 From: george.sakkis at gmail.com (George Sakkis) Date: Wed, 16 May 2007 10:50:40 -0400 Subject: [Python-ideas] Positional only arguments Message-ID: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> This was posted on python-dev two weeks ago [1] but didn't get very far; probably python-ideas is a more appropriate list if this is to be taken any further. In short, PEP 3102 enables the declaration of keyword-only arguments, making it easier for an API to grow in a backwards compatible way. As Benji York, I see the utility of positional-only arguments, not just for the sake of symmetry but for pragmatic reasons; in fact the same reasons that serve as rationale to the keywords-only PEP. I don't have any concrete proposal (syntactic or otherwise) at this point, but I'd like to see this feature in Py3K even if I dislike the specific syntax or other machinery that implements it (just like decorators). For now it's worth just getting an idea of whether the feature itself is deemed useful enough or the current status quo is adequate. George [1] http://mail.python.org/pipermail/python-dev/2006-May/064790.html -- "If I have been able to see further, it was only because I stood on the shoulders of million monkeys." Unknown From guido at python.org Wed May 16 17:09:26 2007 From: guido at python.org (Guido van Rossum) Date: Wed, 16 May 2007 08:09:26 -0700 Subject: [Python-ideas] Positional only arguments In-Reply-To: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> Message-ID: +1 for the concept. Personally, when I really wanted this, I've given the arguments names like __foo. --Guido On 5/16/07, George Sakkis wrote: > This was posted on python-dev two weeks ago [1] but didn't get very > far; probably python-ideas is a more appropriate list if this is to be > taken any further. > > In short, PEP 3102 enables the declaration of keyword-only arguments, > making it easier for an API to grow in a backwards compatible way. As > Benji York, I see the utility of positional-only arguments, not just > for the sake of symmetry but for pragmatic reasons; in fact the same > reasons that serve as rationale to the keywords-only PEP. > > I don't have any concrete proposal (syntactic or otherwise) at this > point, but I'd like to see this feature in Py3K even if I dislike the > specific syntax or other machinery that implements it (just like > decorators). For now it's worth just getting an idea of whether the > feature itself is deemed useful enough or the current status quo is > adequate. > > George > > > [1] http://mail.python.org/pipermail/python-dev/2006-May/064790.html > > > > -- > "If I have been able to see further, it was only because I stood on > the shoulders of million monkeys." > > Unknown > _______________________________________________ > Python-ideas mailing list > Python-ideas at python.org > http://mail.python.org/mailman/listinfo/python-ideas > -- --Guido van Rossum (home page: http://www.python.org/~guido/) From george.sakkis at gmail.com Wed May 16 18:25:05 2007 From: george.sakkis at gmail.com (George Sakkis) Date: Wed, 16 May 2007 12:25:05 -0400 Subject: [Python-ideas] Positional only arguments In-Reply-To: <464B2114.9030601@zope.com> References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> <464B2114.9030601@zope.com> Message-ID: <91ad5bf80705160925p158dd8dbiff7919c352b81349@mail.gmail.com> On 5/16/07, Benji York wrote: > Guido van Rossum wrote: > > Personally, when I really wanted this, I've given the arguments names > > like __foo. > > That could be enshrined as the syntax, much like "private" attributes. What's the future of "private" attributes in Py3K ? I remember Raymond Hettinger bringing up a challenge on c.l.py about a decorator that could replace the double underscore mangling and Michele Simionato caming up with a bytecode hack that showed it is possible. If they're staying though, +epsilon for blessing __args as positional-only (for some positive epsilon ;-)). George -- "If I have been able to see further, it was only because I stood on the shoulders of million monkeys." From taleinat at gmail.com Wed May 16 18:29:15 2007 From: taleinat at gmail.com (Tal Einat) Date: Wed, 16 May 2007 19:29:15 +0300 Subject: [Python-ideas] Positional only arguments In-Reply-To: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> Message-ID: <7afdee2f0705160929v60e82fbcja948b0bb9e0f02f6@mail.gmail.com> On 5/16/07, George Sakkis wrote: > > This was posted on python-dev two weeks ago [1] but didn't get very > far; probably python-ideas is a more appropriate list if this is to be > taken any further. > > In short, PEP 3102 enables the declaration of keyword-only arguments, > making it easier for an API to grow in a backwards compatible way. As > Benji York, I see the utility of positional-only arguments, not just > for the sake of symmetry but for pragmatic reasons; in fact the same > reasons that serve as rationale to the keywords-only PEP. > > I don't have any concrete proposal (syntactic or otherwise) at this > point, but I'd like to see this feature in Py3K even if I dislike the > specific syntax or other machinery that implements it (just like > decorators). For now it's worth just getting an idea of whether the > feature itself is deemed useful enough or the current status quo is > adequate. > > George > > > [1] http://mail.python.org/pipermail/python-dev/2006-May/064790.html Well, if the syntax currently suggested in PEP 3102 [1] is adopted: def compare(a, b, *, key=None): Then it could be decided that arguments before the asterisk are positional-only, and those after the asterisk are keyword-only. This would be backwards compatible, since functions defined without the asterisk could work as they currently do. Alternatively, we could decide that we don't like positional-or-keyword-arguments at all any more, and do away with them altogether. All arguments would be positional only by default, unless they are declared keyword-only (by whatever syntax is adopted). Now waiting for the big guys to knock this down :) - Tal [1] http://www.python.org/dev/peps/pep-3102/ -------------- next part -------------- An HTML attachment was scrubbed... URL: From guido at python.org Wed May 16 18:45:42 2007 From: guido at python.org (Guido van Rossum) Date: Wed, 16 May 2007 09:45:42 -0700 Subject: [Python-ideas] Positional only arguments In-Reply-To: <91ad5bf80705160925p158dd8dbiff7919c352b81349@mail.gmail.com> References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> <464B2114.9030601@zope.com> <91ad5bf80705160925p158dd8dbiff7919c352b81349@mail.gmail.com> Message-ID: On 5/16/07, George Sakkis wrote: > What's the future of "private" attributes in Py3K ? I remember Raymond > Hettinger bringing up a challenge on c.l.py about a decorator that > could replace the double underscore mangling and Michele Simionato > caming up with a bytecode hack that showed it is possible. > > If they're staying though, +epsilon for blessing __args as > positional-only (for some positive epsilon ;-)). Nobody submitted a PEP to remove them in time for any of the several deadlines I gave, so they are staying. (I think that even if a PEP had been submitted it would probably have been rejected, after a long discussion.) But I'd love to see better syntax for positional-only arguments. What I would like to be able to do is somehow write a signature like this: def foo(abc, xyz=42): ... where both arguments (if present) *must* be given using positional notation, so that foo(42) and foo(42, 24) are legal, but foo(abc=42) and foo(42, xyz=24) are illegal. (Alas, I don't have any clever suggestions.) This could be proposed as an addition for 2.6 and then we'd have to slip it into 3.0. -- --Guido van Rossum (home page: http://www.python.org/~guido/) From steven.bethard at gmail.com Wed May 16 19:17:30 2007 From: steven.bethard at gmail.com (Steven Bethard) Date: Wed, 16 May 2007 11:17:30 -0600 Subject: [Python-ideas] Positional only arguments In-Reply-To: References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> <464B2114.9030601@zope.com> <91ad5bf80705160925p158dd8dbiff7919c352b81349@mail.gmail.com> Message-ID: On 5/16/07, Guido van Rossum wrote: > But I'd love to see better syntax for positional-only arguments. What > I would like to be able to do is somehow write a signature like this: > > def foo(abc, xyz=42): ... > > where both arguments (if present) *must* be given using positional > notation, so that foo(42) and foo(42, 24) are legal, but foo(abc=42) > and foo(42, xyz=24) are illegal. (Alas, I don't have any clever > suggestions.) I'd particularly like to see some way to do this because it would make duplicating the dict() and dict.update() signatures easier. Currently you could write:: class C(object): def __init__(self, obj=None, **kwargs): but this breaks when you try something like:: C(obj='foo', bar='baz') and expect both keyword arguments to be caught in the **kwargs. And let's hope you never need to write something like:: C(self=1, other=2) where you'll get a:: TypeError: __init__() got multiple values for keyword argument 'self' The current correct version looks like:: class C(object): def __init__(*args, **kwargs): self = args[0] if len(args) == 2: obj = args[1] elif len(args) == 1: obj = None else: raise TypeError() Nasty. STeVe -- I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a tiny blip on the distant coast of sanity. --- Bucky Katt, Get Fuzzy From benji at benjiyork.com Wed May 16 19:47:23 2007 From: benji at benjiyork.com (Benji York) Date: Wed, 16 May 2007 13:47:23 -0400 Subject: [Python-ideas] Positional only arguments In-Reply-To: References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> Message-ID: <464B43AB.8030005@benjiyork.com> Guido van Rossum wrote: > Personally, when I really wanted this, I've given the arguments names > like __foo. That could be enshrined as the syntax, much like "private" attributes. -- Benji York http://benjiyork.com From greg.ewing at canterbury.ac.nz Thu May 17 02:45:33 2007 From: greg.ewing at canterbury.ac.nz (Greg Ewing) Date: Thu, 17 May 2007 12:45:33 +1200 Subject: [Python-ideas] Positional only arguments In-Reply-To: References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> Message-ID: <464BA5AD.4050507@canterbury.ac.nz> Guido van Rossum wrote: > Personally, when I really wanted this, I've given the arguments names > like __foo. But that doesn't address all the reasons for wanting keyword-only args. An important reason is when you want to accept an arbitrary number of positional args, plus some keyword args. You can only do that now by manually unpacking things from **kwds. -- Greg From jimjjewett at gmail.com Thu May 17 02:59:03 2007 From: jimjjewett at gmail.com (Jim Jewett) Date: Wed, 16 May 2007 20:59:03 -0400 Subject: [Python-ideas] dot bend spoon In-Reply-To: <20070516105510.26D531E4002@bag.python.org> References: <20070516105510.26D531E4002@bag.python.org> Message-ID: On 5/16/07, Aaron Brady wrote: > Is the going semantic to carry a relation: Do you just mean, "What is the most common idiom?" I'll answer on that assumption, though if I'm correct, comp.lang.python would be the more appropriate list. > spoon.bend() Tell the spoon to bend itself. There are probably other things you could tell the spoon, but no reason to believe that other objects bend. > or > johnson.bend( spoon ) ? Tell Johnson to bend a spoon. You could have told him to bend a knife instead. -jJ From guido at python.org Thu May 17 04:04:34 2007 From: guido at python.org (Guido van Rossum) Date: Wed, 16 May 2007 19:04:34 -0700 Subject: [Python-ideas] Positional only arguments In-Reply-To: <464BA5AD.4050507@canterbury.ac.nz> References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> <464BA5AD.4050507@canterbury.ac.nz> Message-ID: On 5/16/07, Greg Ewing wrote: > Guido van Rossum wrote: > > > Personally, when I really wanted this, I've given the arguments names > > like __foo. > > But that doesn't address all the reasons for wanting > keyword-only args. An important reason is when you > want to accept an arbitrary number of positional args, > plus some keyword args. You can only do that now by > manually unpacking things from **kwds. In Py3k, the syntax is extended to support this: def f(*args, foo=1, bar=2): pass -- --Guido van Rossum (home page: http://www.python.org/~guido/) From greg.ewing at canterbury.ac.nz Thu May 17 05:58:04 2007 From: greg.ewing at canterbury.ac.nz (Greg Ewing) Date: Thu, 17 May 2007 15:58:04 +1200 Subject: [Python-ideas] dot bend spoon In-Reply-To: References: <20070516105510.26D531E4002@bag.python.org> Message-ID: <464BD2CC.6000909@canterbury.ac.nz> Jim Jewett wrote: > > or > > > johnson.bend( spoon ) ? > > Tell Johnson to bend a spoon. or uri_geller.bend(spoon) which doesn't actually bend the spoon, but makes the rest of the program think it has been. :-) More seriously, you can't say that one of these is better than the other out of context. It depends on how the rest of the program is designed. -- Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | Carpe post meridiem! | Christchurch, New Zealand | (I'm not a morning person.) | greg.ewing at canterbury.ac.nz +--------------------------------------+ From greg.ewing at canterbury.ac.nz Thu May 17 06:06:38 2007 From: greg.ewing at canterbury.ac.nz (Greg Ewing) Date: Thu, 17 May 2007 16:06:38 +1200 Subject: [Python-ideas] Positional only arguments In-Reply-To: <464BA5AD.4050507@canterbury.ac.nz> References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> <464BA5AD.4050507@canterbury.ac.nz> Message-ID: <464BD4CE.10203@canterbury.ac.nz> I wrote: > Guido van Rossum wrote: > > > Personally, when I really wanted this, I've given the arguments names > > like __foo. > > But that doesn't address all the reasons for wanting > keyword-only args. Sorry, I got mixed up between the positional-only and keyword-only threads going on at the same time. Please disregard that comment. Personally I don't care much about positional-only args other than through *args. If an elegant way of accommodating them can be found, that's fine, but I wouldn't go out of my way to find one. -- Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | Carpe post meridiem! | Christchurch, New Zealand | (I'm not a morning person.) | greg.ewing at canterbury.ac.nz +--------------------------------------+ From rasky at develer.com Fri May 18 01:58:31 2007 From: rasky at develer.com (Giovanni Bajo) Date: Fri, 18 May 2007 01:58:31 +0200 Subject: [Python-ideas] Positional only arguments In-Reply-To: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> Message-ID: On 16/05/2007 16.50, George Sakkis wrote: > In short, PEP 3102 enables the declaration of keyword-only arguments, > making it easier for an API to grow in a backwards compatible way. As > Benji York, I see the utility of positional-only arguments, not just > for the sake of symmetry but for pragmatic reasons; in fact the same > reasons that serve as rationale to the keywords-only PEP. I've needed this only a few times, and I have used something like: def foo(*args): a,b,c = args as a workaround. Doesn't look too clumsy after all. For Py4k, the only thing that occurred to me is to reuse the parenthesis: def foo((a, b, c, d), e, f, *, g, h): pass - a,b,c,d are positional-only - e,f can be either positional or keyword - g,h are only keyword. -- Giovanni Bajo From gsakkis at rutgers.edu Fri May 18 03:14:57 2007 From: gsakkis at rutgers.edu (George Sakkis) Date: Thu, 17 May 2007 21:14:57 -0400 Subject: [Python-ideas] Positional only arguments In-Reply-To: References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> Message-ID: <91ad5bf80705171814h2b6b3ce1k8ee58a2e3e3aa78a@mail.gmail.com> On 5/17/07, Giovanni Bajo wrote: > On 16/05/2007 16.50, George Sakkis wrote: > > > In short, PEP 3102 enables the declaration of keyword-only arguments, > > making it easier for an API to grow in a backwards compatible way. As > > Benji York, I see the utility of positional-only arguments, not just > > for the sake of symmetry but for pragmatic reasons; in fact the same > > reasons that serve as rationale to the keywords-only PEP. > > I've needed this only a few times, and I have used something like: > > def foo(*args): > a,b,c = args > > as a workaround. Doesn't look too clumsy after all. Well, it's better than nothing but it's an abuse of the *varargs syntax and not friendly to signature inspection tools. > For Py4k, the only thing that occurred to me is to reuse the parenthesis: > > def foo((a, b, c, d), e, f, *, g, h): > pass > > - a,b,c,d are positional-only > - e,f can be either positional or keyword > - g,h are only keyword. Not too bad, but the pair of parentheses is redundant; positional-only args (if any) must start from index 0. Also this doesn't address pos-only args with defaults like Guido's example foo(abc, xyz=42). A single "delimiter" symbol (e.g. '%') between pos-only and pos-or-kw would kill both birds with one stone, i.e. something like: def foo(a, b=42, # pos-only % , # delimiter c=0, d=None, # pos-or-kw *args, # varargs e=-1,z='', # kw-only **kwds # keyword dictionary ) Pros: - Backwards compatible: args are pos-or-kw by default as they are now; only those before the new delimiter are positional. - Easy to change the status of a parameter; just move it to the appropriate section (at least if it has a default value). Cons: - Yet another magic symbol, smells like perl (reusing the single star would be ambiguous). - The presumably common cases of functions without pos-or-kw args is clumsy: def foo(a, b, c=31, %): # all pos-only def bar(a, b=1, %, *, c=31, d=None): # pos-only or kw-only Overall, I still prefer the double underscores. George -- "If I have been able to see further, it was only because I stood on the shoulders of million monkeys." From rrr at ronadam.com Fri May 18 04:10:05 2007 From: rrr at ronadam.com (Ron Adam) Date: Thu, 17 May 2007 21:10:05 -0500 Subject: [Python-ideas] Positional only arguments In-Reply-To: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> Message-ID: <464D0AFD.3080900@ronadam.com> George Sakkis wrote: > This was posted on python-dev two weeks ago [1] but didn't get very > far; probably python-ideas is a more appropriate list if this is to be > taken any further. > > In short, PEP 3102 enables the declaration of keyword-only arguments, > making it easier for an API to grow in a backwards compatible way. As > Benji York, I see the utility of positional-only arguments, not just > for the sake of symmetry but for pragmatic reasons; in fact the same > reasons that serve as rationale to the keywords-only PEP. > > I don't have any concrete proposal (syntactic or otherwise) at this > point, but I'd like to see this feature in Py3K even if I dislike the > specific syntax or other machinery that implements it (just like > decorators). For now it's worth just getting an idea of whether the > feature itself is deemed useful enough or the current status quo is > adequate. > > George > > > [1] http://mail.python.org/pipermail/python-dev/2006-May/064790.html It seems there is a growing menu of arguments options. I suppose that's a good thing. As long as it doesn't get too confusing. Another thing I've wished I had recently is a way to over specify an argument list by giving it a larger list of arguments (or keywords) than is needed. For example if I'm dispatching a collection of functions that each have different set or number of arguments, I'd like to say on the calling end for the function to take what it needs from a list and/or dictionary, but ignore what it doesn't need. In the case of positional only arguments, it could take them in order, and in the case of keywords only, by name. The point is to be able to specify it from the calling end in a generic way instead of having to do it inside the function or by adding a decorator to each function. It's kind of like an simplified or generic adapter in a way. Cheers, Ron From arno at marooned.org.uk Fri May 18 08:35:06 2007 From: arno at marooned.org.uk (Arnaud Delobelle) Date: Fri, 18 May 2007 07:35:06 +0100 (BST) Subject: [Python-ideas] Positional only arguments In-Reply-To: References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> <464B2114.9030601@zope.com> <91ad5bf80705160925p158dd8dbiff7919c352b81349@mail.gmail.com> Message-ID: <61393.80.195.169.49.1179470106.squirrel@webmail.marooned.org.uk> On Wed, May 16, 2007 5:45 pm, Guido van Rossum wrote: [...] > But I'd love to see better syntax for positional-only arguments. What > I would like to be able to do is somehow write a signature like this: > > def foo(abc, xyz=42): ... > > where both arguments (if present) *must* be given using positional > notation, so that foo(42) and foo(42, 24) are legal, but foo(abc=42) > and foo(42, xyz=24) are illegal. (Alas, I don't have any clever > suggestions.) One could decorate foo with: def posonly(f): def posf(*args, **kwargs): return f(*args, *kwargs) posf.__name__ = f.__name__ return f So: @posonly def foo(abc, xyz=42):... would behave as you want. Of course it doesn't have an interesting signature. By extension one could have the arglist element *(a, b, c) for positional-only arguments and **(x, y, z) for keyword-only arguments: def foo(*(abc, xyz=42)):... def bar(a, b, **(x, y=2)):... # a and b are positional/keyword arguments # x is keyword-only and mandatory # y is keyword-only with a default value of 2 It sort of fits with the current use of * as when calling foo: foo(my_abc, my_xyz) is equivalent to foo(*(my_abc, my_xyz)) -- Arnaud From fdrake at acm.org Fri May 18 14:51:20 2007 From: fdrake at acm.org (Fred L. Drake, Jr.) Date: Fri, 18 May 2007 08:51:20 -0400 Subject: [Python-ideas] Positional only arguments In-Reply-To: <91ad5bf80705171814h2b6b3ce1k8ee58a2e3e3aa78a@mail.gmail.com> References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> <91ad5bf80705171814h2b6b3ce1k8ee58a2e3e3aa78a@mail.gmail.com> Message-ID: <200705180851.20823.fdrake@acm.org> On Thursday 17 May 2007, George Sakkis wrote: > single "delimiter" symbol (e.g. '%') between pos-only and pos-or-kw > would kill both birds with one stone, i.e. something like: A delimeter that would be needed anyway would make this a little nicer: def myfunc(a, b, c=24; *, kw=42): pass This example would have 3 positional-only arguments (a, b, c) and one keyword-only argument (kw). Replacing the comma with a semicolon avoids the need for a syntax-only position (good, IMO), avoids introducing a new special character, and re-uses one that's rarely used anyway. -Fred -- Fred L. Drake, Jr. From guido at python.org Fri May 18 16:40:08 2007 From: guido at python.org (Guido van Rossum) Date: Fri, 18 May 2007 07:40:08 -0700 Subject: [Python-ideas] Positional only arguments In-Reply-To: <61393.80.195.169.49.1179470106.squirrel@webmail.marooned.org.uk> References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> <464B2114.9030601@zope.com> <91ad5bf80705160925p158dd8dbiff7919c352b81349@mail.gmail.com> <61393.80.195.169.49.1179470106.squirrel@webmail.marooned.org.uk> Message-ID: This decorator solution is the best I've seen so far! It is probably possible to (a) copy signature info into the returned wrapper, and (b) support keyword args (after the lone '*' or after *args). --Guido On 5/17/07, Arnaud Delobelle wrote: > > On Wed, May 16, 2007 5:45 pm, Guido van Rossum wrote: > [...] > > But I'd love to see better syntax for positional-only arguments. What > > I would like to be able to do is somehow write a signature like this: > > > > def foo(abc, xyz=42): ... > > > > where both arguments (if present) *must* be given using positional > > notation, so that foo(42) and foo(42, 24) are legal, but foo(abc=42) > > and foo(42, xyz=24) are illegal. (Alas, I don't have any clever > > suggestions.) > > One could decorate foo with: > > def posonly(f): > def posf(*args, **kwargs): return f(*args, *kwargs) > posf.__name__ = f.__name__ > return f > > So: > > @posonly > def foo(abc, xyz=42):... > > would behave as you want. Of course it doesn't have an interesting > signature. > > By extension one could have the arglist element *(a, b, c) for > positional-only arguments and **(x, y, z) for keyword-only arguments: > > def foo(*(abc, xyz=42)):... > > def bar(a, b, **(x, y=2)):... > # a and b are positional/keyword arguments > # x is keyword-only and mandatory > # y is keyword-only with a default value of 2 > > It sort of fits with the current use of * as when calling foo: > > foo(my_abc, my_xyz) > > is equivalent to > > foo(*(my_abc, my_xyz)) > > -- > Arnaud > > > _______________________________________________ > Python-ideas mailing list > Python-ideas at python.org > http://mail.python.org/mailman/listinfo/python-ideas > -- --Guido van Rossum (home page: http://www.python.org/~guido/) From rrr at ronadam.com Fri May 18 17:14:42 2007 From: rrr at ronadam.com (Ron Adam) Date: Fri, 18 May 2007 10:14:42 -0500 Subject: [Python-ideas] Positional only arguments In-Reply-To: <200705180851.20823.fdrake@acm.org> References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> <91ad5bf80705171814h2b6b3ce1k8ee58a2e3e3aa78a@mail.gmail.com> <200705180851.20823.fdrake@acm.org> Message-ID: <464DC2E2.5000603@ronadam.com> Fred L. Drake, Jr. wrote: > On Thursday 17 May 2007, George Sakkis wrote: > > single "delimiter" symbol (e.g. '%') between pos-only and pos-or-kw > > would kill both birds with one stone, i.e. something like: > > A delimeter that would be needed anyway would make this a little nicer: > > def myfunc(a, b, c=24; *, kw=42): > pass > > This example would have 3 positional-only arguments (a, b, c) and one > keyword-only argument (kw). > > Replacing the comma with a semicolon avoids the need for a syntax-only > position (good, IMO), avoids introducing a new special character, and re-uses > one that's rarely used anyway. [A few thoughts] def foo([positonal_only_args][; [kwd_args][; kwds_only]]): ... def myfunct(a, b, c=42; e=99; kw=42): ... args = (1, 2, 3, 4) # 'e' can be in either args or kwds, kwds = {'kw': 42} # but not both. bar = foo(*args, **kwds) How about signature objects that are similar to slice objects? sig = signature(*args, **kwds) # Pre package signature. sig = signature(1, 2, 3, 4, kw=42) Could something like this have performance benefit if the same exact signature is used over and over? Possibly just passing a pre parsed name space to the function? bar = foo(sig) # No need to unpack with * or **. bar = foo(@sig) # Be lenient, extra args and kwds # are consumed or ignored. # But always error if something is missing. The '@' sign is like a vortex which sucks up unused args. ;-) Ron From rrr at ronadam.com Fri May 18 17:41:48 2007 From: rrr at ronadam.com (Ron Adam) Date: Fri, 18 May 2007 10:41:48 -0500 Subject: [Python-ideas] Positional only arguments In-Reply-To: <464DC2E2.5000603@ronadam.com> References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> <91ad5bf80705171814h2b6b3ce1k8ee58a2e3e3aa78a@mail.gmail.com> <200705180851.20823.fdrake@acm.org> <464DC2E2.5000603@ronadam.com> Message-ID: <464DC93C.3080304@ronadam.com> Ron Adam wrote: > Fred L. Drake, Jr. wrote: >> On Thursday 17 May 2007, George Sakkis wrote: >> > single "delimiter" symbol (e.g. '%') between pos-only and pos-or-kw >> > would kill both birds with one stone, i.e. something like: >> >> A delimeter that would be needed anyway would make this a little nicer: >> >> def myfunc(a, b, c=24; *, kw=42): >> pass >> >> This example would have 3 positional-only arguments (a, b, c) and one >> keyword-only argument (kw). >> >> Replacing the comma with a semicolon avoids the need for a syntax-only >> position (good, IMO), avoids introducing a new special character, and re-uses >> one that's rarely used anyway. > > > [A few thoughts] > > def foo([positonal_only_args][; [kwd_args][; kwds_only]]): ... > > def myfunct(a, b, c=42; e=99; kw=42): ... Hmmm, this has a problem if you use * or ** in the definition. :( def myfunc(*args; ? ; **kwds): ... I think this would be an issue with some of the other ideas as well. > args = (1, 2, 3, 4) # 'e' can be in either args or kwds, > kwds = {'kw': 42} # but not both. > > bar = foo(*args, **kwds) > > > How about signature objects that are similar to slice objects? > > sig = signature(*args, **kwds) # Pre package signature. > sig = signature(1, 2, 3, 4, kw=42) > > Could something like this have performance benefit if the same exact > signature is used over and over? Possibly just passing a pre parsed name > space to the function? > > bar = foo(sig) # No need to unpack with * or **. > > bar = foo(@sig) # Be lenient, extra args and kwds > # are consumed or ignored. > # But always error if something is missing. > > The '@' sign is like a vortex which sucks up unused args. ;-) > > Ron From martin at ambric.com Fri May 18 17:34:53 2007 From: martin at ambric.com (Rick Martin) Date: Fri, 18 May 2007 08:34:53 -0700 Subject: [Python-ideas] Positional only arguments In-Reply-To: Message-ID: Has anyone considered the Common Lisp argument list as a place to look for ideas? (var... &optional (var initform svar)... &rest var &key ((keyword var) initform svar)... &aux (var initform)...) http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node64.html Rick From arno at marooned.org.uk Fri May 18 19:42:13 2007 From: arno at marooned.org.uk (Arnaud Delobelle) Date: Fri, 18 May 2007 18:42:13 +0100 (BST) Subject: [Python-ideas] Positional only arguments In-Reply-To: <61393.80.195.169.49.1179470106.squirrel@webmail.marooned.org.uk> References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> <464B2114.9030601@zope.com> <91ad5bf80705160925p158dd8dbiff7919c352b81349@mail.gmail.com> <61393.80.195.169.49.1179470106.squirrel@webmail.marooned.org.uk> Message-ID: <61788.80.195.168.31.1179510133.squirrel@webmail.marooned.org.uk> On Fri, May 18, 2007 7:35 am, Arnaud Delobelle wrote: [...] > def posonly(f): > def posf(*args, **kwargs): return f(*args, *kwargs) > posf.__name__ = f.__name__ > return f I wrote this just before going to work this morning, and of course I didn't try it or probably even reread it... So apart from the typos it doesn't work with **kwargs. I've got a working version: def posonly(arg): def deco(f, nposargs): name = f.__name__ posargnames = f.func_code.co_varnames[:nposargs] def posf(*args, **kwargs): for kw in kwargs: if kw in posargnames: raise TypeError("%s() arg '%s' is posonly" % (name, kw)) return f(*args, **kwargs) posf.__name__ = name return posf if isinstance(arg, int): return lambda f: deco(f, arg) else: return deco(arg, arg.func_code.co_argcount) It works like this: @posonly def foo(x, y, z=10, t=100): # All arguments are positional only # foo(1, 2, 3) -> 106 # foo(1, y=2) -> TypeError # foo(1, t=7) -> TypeError return x+y+z+t @posonly(2) def bar(x, y=1, z=10, t=100): # Only the first two arguments are posonly # bar(1, y=2) -> TypeError # bar(1, z=0) -> 102 Being a mere python end-user, I don't know if I'm using the func_code attribute of functions correctly, so this might break in various ways! -- Arnaud From steven.bethard at gmail.com Fri May 18 23:07:22 2007 From: steven.bethard at gmail.com (Steven Bethard) Date: Fri, 18 May 2007 15:07:22 -0600 Subject: [Python-ideas] Positional only arguments In-Reply-To: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> Message-ID: On 5/16/07, George Sakkis wrote: > I see the utility of positional-only arguments, not just > for the sake of symmetry but for pragmatic reasons; in fact the same > reasons that serve as rationale to the keywords-only PEP. In the hopes of keeping this discussion enough on track that we can eventually come to a conclusion, I thought I'd just take a couple minutes to summarize the proposals so far. I'm looking at the following function as an example:: def f(a, b=None, *, c=42, **kwargs) where ``a`` and ``b`` should be positional-only and ``c`` should be keyword-only. Here are the alternatives I've seen so far: * Do nothing, e.g.:: def (*args, c=42, **kwargs): if len(args) == 1: a = args[0] b = None elif len(args) == 2: a, b = args else: raise TypeError() Pro: backwards compatible, requires no new syntax Con: unfriendly to introspection, requires extra boiler-plate * Enforce double-underscore names as being positional-only syntactically, e.g.:: def f(__a, __b=None, *, c=42, **kwargs) Pro: requires no new syntax Con: slightly backwards incompatible (but who calls f(__a) anyway?) * Use a decorator, e.g.:: @posonly(2) def f(a, b=None, *, c=42, **kwargs) Pro: backwards compatible, requires no new syntax, could work with Python 2.5 Con: moves some signature info out of the argument list * Make the lone '*' force everything to the left to be positional-only and everything to the right be keyword-only, e.g.:: def f(a, b=None, *, c=42, **kwargs): Pro: backwards compatible (since lone '*' is not yet introduced), requires no new syntax Con: disallows named arguments with keyword-only arguments, disallows positional-only arguments with *args. * Reuse syntax like what was removed for tuple arguments, e.g.:: def f((a, b=None), *, c=42, **kwargs): Pro: ? Con: changes meaning of tuple argument syntax * Add a new delimiter, e.g.:: def f(a, b=None, %, *, c=42, **kwargs) def f(a, b=None; *, c=42, **kwargs) Pro: backwards compatible Con: requires new syntax, in second version semi-colon vs. comma is hard to spot So at the moment, it looks to me like the double-underscores and the decorator are the top competitors. STeVe -- I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a tiny blip on the distant coast of sanity. --- Bucky Katt, Get Fuzzy From jimjjewett at gmail.com Fri May 18 23:52:01 2007 From: jimjjewett at gmail.com (Jim Jewett) Date: Fri, 18 May 2007 17:52:01 -0400 Subject: [Python-ideas] Positional only arguments In-Reply-To: References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> Message-ID: On 5/16/07, George Sakkis wrote: > I see the utility of positional-only arguments, not just > for the sake of symmetry but for pragmatic reasons; in fact the same > reasons that serve as rationale to the keywords-only PEP. uhh... could you spell those out, please? keywords-only is justified by functions that take both *args and a keyword that meets meets at least one of (1) Wasn't there before, so you can't stick it in front for backwards-compatibility reasons. (think "cmp") (2) Doesn't have a default (3) Should always be called by name, for readability. The following signature is awful def max(cmp=mysort, *args): And if you've already released max, it isn't even legal. How could there ever be an argument that *needs* to be positional? There are some that don't work if you call them by keyword, because they happen to be implemented in C without keyword support, but ... is there any reason to postively forbid using the argument name? The closest I can come to an example is def lappend(object): # This mimics list.append, and the *real* function wouldn't # take a keyword, so neither will I, just to prevent bad habits. Even that can already be written if you really want to... def lappend(*object): if len(object) != 1: raise TypeError("lappend takes ...") object = object[0] ... -jJ From steven.bethard at gmail.com Sat May 19 01:04:09 2007 From: steven.bethard at gmail.com (Steven Bethard) Date: Fri, 18 May 2007 17:04:09 -0600 Subject: [Python-ideas] Positional only arguments In-Reply-To: References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> Message-ID: On 5/18/07, Jim Jewett wrote: > How could there ever be an argument that *needs* to be positional? As I've mentioned before, a great example of this is the dict() signature. It takes an optional "container" argument, followed by arbitrary keywords. If you write this in the naive way:: def __init__(self, container=None, **kwargs) ... for key, value in kwargs.items(): self[key] = value then you get TypeErrors for the following code:: d.update(sequence=1, container=2) d.update(other=1, self=2) That is, the **kwargs can never include anything named 'self' or 'container'. If you could declare these two arguments as positional-only, you'd never run into this problem. STeVe -- I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a tiny blip on the distant coast of sanity. --- Bucky Katt, Get Fuzzy From steven.bethard at gmail.com Sat May 19 01:11:27 2007 From: steven.bethard at gmail.com (Steven Bethard) Date: Fri, 18 May 2007 17:11:27 -0600 Subject: [Python-ideas] Positional only arguments In-Reply-To: References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> Message-ID: On 5/18/07, Steven Bethard wrote: > On 5/18/07, Jim Jewett wrote: > > How could there ever be an argument that *needs* to be positional? > > As I've mentioned before, a great example of this is the dict() > signature. It takes an optional "container" argument, followed by > arbitrary keywords. If you write this in the naive way:: > > def __init__(self, container=None, **kwargs) > ... > for key, value in kwargs.items(): > self[key] = value > > then you get TypeErrors for the following code:: > > d.update(sequence=1, container=2) > d.update(other=1, self=2) Sorry, those should have been dict(sequence=1, container=2) dict(other=1, self=2) Of course, the same argument is valid for dict.update(). > That is, the **kwargs can never include anything named 'self' or > 'container'. If you could declare these two arguments as > positional-only, you'd never run into this problem. STeVe -- I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a tiny blip on the distant coast of sanity. --- Bucky Katt, Get Fuzzy From castironpi at comcast.net Sat May 19 04:55:49 2007 From: castironpi at comcast.net (Aaron Brady) Date: Fri, 18 May 2007 21:55:49 -0500 Subject: [Python-ideas] Positional only arguments In-Reply-To: <91ad5bf80705171814h2b6b3ce1k8ee58a2e3e3aa78a@mail.gmail.com> Message-ID: <20070519025555.23EE01E4004@bag.python.org> > -----Original Message----- > From: python-ideas-bounces at python.org [mailto:python-ideas- > bounces at python.org] On Behalf Of George Sakkis > def foo(a, b=42, # pos-only > % , # delimiter > c=0, d=None, # pos-or-kw > *args, # varargs > e=-1,z='', # kw-only > **kwds # keyword dictionary > ) > > Pros: > - Backwards compatible: args are pos-or-kw by default as they are now; > only those before the new delimiter are positional. > - Easy to change the status of a parameter; just move it to the > appropriate section (at least if it has a default value). > > Cons: > - Yet another magic symbol, smells like perl (reusing the single star > would be ambiguous). > - The presumably common cases of functions without pos-or-kw args is > clumsy: > def foo(a, b, c=31, %): # all pos-only > def bar(a, b=1, %, *, c=31, d=None): # pos-only or kw-only > > Overall, I still prefer the double underscores. > > George > One of the things I like about Python is we've got some extra room in the syntax to complexify. Careful how we spend it. The extra is on a budget, not unlimited as some things are. def foo(a, b=42; # pos-only c=0, d=None, # pos-or-kw *args; # varargs e=-1,z='', # kw-only **kwds # keyword dictionary ) def foo(a, b, c=31; ): # all pos-only def bar(a, b=1;; c=31, d=None): # pos-only or kw-only > - Yet another magic symbol, smells like perl (reusing the single star > would be ambiguous). True dat. From castironpi at comcast.net Sat May 19 06:07:39 2007 From: castironpi at comcast.net (Aaron Brady) Date: Fri, 18 May 2007 23:07:39 -0500 Subject: [Python-ideas] Positional only arguments In-Reply-To: Message-ID: <20070519040745.6CF001E4004@bag.python.org> > -----Original Message----- > From: python-ideas-bounces+castironpi=comcast.net at python.org > [mailto:python-ideas-bounces+castironpi=comcast.net at python.org] On Behalf > Of Steven Bethard > Sent: Friday, May 18, 2007 6:04 PM > To: Jim Jewett > Cc: python-ideas at python.org; benji at zope.com > Subject: Re: [Python-ideas] Positional only arguments > > On 5/18/07, Jim Jewett wrote: > > How could there ever be an argument that *needs* to be positional? > > As I've mentioned before, a great example of this is the dict() > signature. It takes an optional "container" argument, followed by > arbitrary keywords. If you write this in the naive way:: > > def __init__(self, container=None, **kwargs) > ... > for key, value in kwargs.items(): > self[key] = value > > then you get TypeErrors for the following code:: > > d.update(sequence=1, container=2) > d.update(other=1, self=2) > > That is, the **kwargs can never include anything named 'self' or > 'container'. If you could declare these two arguments as > positional-only, you'd never run into this problem. > > STeVe Might you use d.update(container=2, sequence=1)? 'Can never' caught me up. > > How could there ever be an argument that *needs* to be positional? To deliberately poise, evaluate extremes. Couple continuums going on here so don't contradict one with another's counterexample. Annotate every call parameter? Double equals sign? Not advocating, but illustrating this one. Balance is trade-off between flexibility to call, and convenience to define. Function decoration is a fledgling addition to syntax. Can we use this to kindle, as opposed to snuff? Shows great ease of use promise. From steven.bethard at gmail.com Sat May 19 06:15:22 2007 From: steven.bethard at gmail.com (Steven Bethard) Date: Fri, 18 May 2007 22:15:22 -0600 Subject: [Python-ideas] Positional only arguments In-Reply-To: <464e780e.562683cf.2949.0fe8SMTPIN_ADDED@mx.google.com> References: <464e780e.562683cf.2949.0fe8SMTPIN_ADDED@mx.google.com> Message-ID: On 5/18/07, Aaron Brady wrote: > Steven Bethard wrote: > > On 5/18/07, Jim Jewett wrote: > > > How could there ever be an argument that *needs* to be positional? > > > > As I've mentioned before, a great example of this is the dict() > > signature. It takes an optional "container" argument, followed by > > arbitrary keywords. If you write this in the naive way:: > > > > def __init__(self, container=None, **kwargs) > > ... > > for key, value in kwargs.items(): > > self[key] = value > > > > then you get TypeErrors for the following code:: > > > > d.update(sequence=1, container=2) > > d.update(other=1, self=2) > > > > That is, the **kwargs can never include anything named 'self' or > > 'container'. If you could declare these two arguments as > > positional-only, you'd never run into this problem. > > Might you use d.update(container=2, sequence=1)? 'Can never' caught me up. Not sure I understand the question. My point was only that you'll never reproduce this behavior:: >>> dict(self=1, other=2) {'self': 1, 'other': 2} >>> d = {} >>> d.update(container=2, sequence=1) >>> d {'container': 2, 'sequence': 1} Of course, you can rename the 'self' and 'container' parameters to something else, but that just means that you can't use whatever new names you choose. The only way to solve this is to use real positional-only arguments, which currently means using *args and parsing out things within the function body. STeVe -- I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a tiny blip on the distant coast of sanity. --- Bucky Katt, Get Fuzzy From rhamph at gmail.com Sat May 19 07:49:57 2007 From: rhamph at gmail.com (Adam Olsen) Date: Fri, 18 May 2007 23:49:57 -0600 Subject: [Python-ideas] Positional only arguments In-Reply-To: References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> Message-ID: On 5/18/07, Steven Bethard wrote: > On 5/16/07, George Sakkis wrote: > > I see the utility of positional-only arguments, not just > > for the sake of symmetry but for pragmatic reasons; in fact the same > > reasons that serve as rationale to the keywords-only PEP. > > In the hopes of keeping this discussion enough on track that we can > eventually come to a conclusion, I thought I'd just take a couple > minutes to summarize the proposals so far. I'm looking at the > following function as an example:: > > def f(a, b=None, *, c=42, **kwargs) > > where ``a`` and ``b`` should be positional-only and ``c`` should be > keyword-only. Here are the alternatives I've seen so far: * Use ** for keyword-only and * for positional-only: def (a, b=None, *, **, c=42, **kwargs): Pro: backwards compatible, reuses existing meanings Con: requires new syntax, changes keyword-only PEP -- Adam Olsen, aka Rhamphoryncus From talin at acm.org Sat May 19 07:49:43 2007 From: talin at acm.org (Talin) Date: Fri, 18 May 2007 22:49:43 -0700 Subject: [Python-ideas] Positional only arguments In-Reply-To: References: <464e780e.562683cf.2949.0fe8SMTPIN_ADDED@mx.google.com> Message-ID: <464E8FF7.5000208@acm.org> Steven Bethard wrote: > Not sure I understand the question. My point was only that you'll > never reproduce this behavior:: > > >>> dict(self=1, other=2) > {'self': 1, 'other': 2} > >>> d = {} > >>> d.update(container=2, sequence=1) > >>> d > {'container': 2, 'sequence': 1} > > Of course, you can rename the 'self' and 'container' parameters to > something else, but that just means that you can't use whatever new > names you choose. The only way to solve this is to use real > positional-only arguments, which currently means using *args and > parsing out things within the function body. I would just use names beginning with an underscore, or some other convention that is unlikely to occur as a dict key. -- Talin From steven.bethard at gmail.com Sat May 19 08:40:38 2007 From: steven.bethard at gmail.com (Steven Bethard) Date: Sat, 19 May 2007 00:40:38 -0600 Subject: [Python-ideas] Positional only arguments In-Reply-To: <464E8FF7.5000208@acm.org> References: <464e780e.562683cf.2949.0fe8SMTPIN_ADDED@mx.google.com> <464E8FF7.5000208@acm.org> Message-ID: On 5/18/07, Talin wrote: > Steven Bethard wrote: > > Not sure I understand the question. My point was only that you'll > > never reproduce this behavior:: > > > > >>> dict(self=1, other=2) > > {'self': 1, 'other': 2} > > >>> d = {} > > >>> d.update(container=2, sequence=1) > > >>> d > > {'container': 2, 'sequence': 1} > > > > Of course, you can rename the 'self' and 'container' parameters to > > something else, but that just means that you can't use whatever new > > names you choose. The only way to solve this is to use real > > positional-only arguments, which currently means using *args and > > parsing out things within the function body. > > I would just use names beginning with an underscore, or some other > convention that is unlikely to occur as a dict key. So should I take that as a +1 for: * Enforce double-underscore names as being positional-only syntactically, e.g.:: def f(__a, __b=None, *, c=42, **kwargs) Pro: requires no new syntax Con: slightly backwards incompatible (but who calls f(__a) anyway?) STeVe -- I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a tiny blip on the distant coast of sanity. --- Bucky Katt, Get Fuzzy From arno at marooned.org.uk Sat May 19 09:22:43 2007 From: arno at marooned.org.uk (Arnaud Delobelle) Date: Sat, 19 May 2007 08:22:43 +0100 (BST) Subject: [Python-ideas] Positional only arguments In-Reply-To: References: <464e780e.562683cf.2949.0fe8SMTPIN_ADDED@mx.google.com> <464E8FF7.5000208@acm.org> Message-ID: <61964.80.195.169.49.1179559363.squirrel@webmail.marooned.org.uk> On Sat, May 19, 2007 7:40 am, Steven Bethard wrote: [...] > So should I take that as a +1 for: > > * Enforce double-underscore names as being positional-only syntactically, > e.g.:: > > def f(__a, __b=None, *, c=42, **kwargs) > > Pro: requires no new syntax > Con: slightly backwards incompatible (but who calls f(__a) anyway?) > - There is also incompatibility in the definition of functions: 'def f(a, __b)' is currently correct, it wouldn't be anymore. - How would this work with name mangling and methods? For example: class Foo(object): def posfun(__self, __a, b, ...): * Would self have to be renamed __self? (As positional only arguments should come first) * Would __self and __a be mangled, as is the rule within classes up to now? If so care has to be taken I suppose. -- Arnaud From arno at marooned.org.uk Sun May 20 10:56:18 2007 From: arno at marooned.org.uk (Arnaud Delobelle) Date: Sun, 20 May 2007 09:56:18 +0100 (BST) Subject: [Python-ideas] Positional only arguments Message-ID: <63611.80.195.169.49.1179651378.squirrel@webmail.marooned.org.uk> On Wed, May 16, 2007 5:25 pm, George Sakkis wrote: [...] > > What's the future of "private" attributes in Py3K ? I remember Raymond > Hettinger bringing up a challenge on c.l.py about a decorator that > could replace the double underscore mangling and Michele Simionato > caming up with a bytecode hack that showed it is possible. IIRC Michele Simionato made a 'CurrentClass' name available to methods, which contains the class that the method is defined in. While interesting, this doesn't help create 'private' attribute, as name mangling does. In fact it is possible to implement this in pure Python using decorators and metaclasses. I tried to take up the challenge (without bytecode hackery, which I am not capable of) but it turned out you need to chase around the call stack a lot! -- Arnaud From arno at marooned.org.uk Sun May 20 16:08:33 2007 From: arno at marooned.org.uk (Arnaud Delobelle) Date: Sun, 20 May 2007 15:08:33 +0100 (BST) Subject: [Python-ideas] Implementing PEP 3130 using decorators Message-ID: <64117.80.195.169.49.1179670113.squirrel@webmail.marooned.org.uk> Hi PEP 3130, 'Access to Current Module/Class/Function', proposed the introduction of new keywords (__class__, __function__, and __module__) to refer to what lexical unit theses names were in. It was rejected, but I have thought about a way to produce the same functionality without the need of new keywords, by using decorators instead. It would go like this: class Foo(object): # some defs... @bindclass def bar(thisclass, self): # Within this method the name 'thiclass' refers to class Foo # ... @bindclass def bar(Foo, self): # The name of 'thisclass' can be chosen, just like 'self' can. # Within this method the name 'Foo' refers to class Foo, even # after Foo is bound to another object # ... # More defs... @bindfunction def factorial(thisfunction, n): # Within this function the name 'thisfunction' refers to the factorial # function (with only one argument), even after 'factorial' is bound # to another object if n > 0: return n * thisfunction(n - 1) else: return 1 Here is an implementation: class bindclass(object): def __init__(self, f): self.f = f def bind(self, cls, attr): def bound_m(*args, **kwargs): return self.f(cls, *args, **kwargs) bound_m.__name__ = attr self.m = bound_m def __get__(self, obj, objtype=None): return self.m.__get__(obj, objtype) class Type(type): def __init__(self, name, bases, attrs): for attr, val in attrs.iteritems(): if isinstance(val, bindclass): val.bind(self, attr) class Object(object): __metaclass__ = Type def bindfunction(f): def bound_f(*args, **kwargs): return f(bound_f, *args, **kwargs) bound_f.__name__ = f.__name__ return bound_f And an example: class Foo(Object): @bindclass def foo(this_class, self): return this_class, self class Bar(Foo): @bindclass def bar(this_class, self): return this_class, self f = Foo() b = Bar() f.foo() # -> Foo, Foo object b.foo() # -> Foo, Foo object f.bar() # -> Bar, Foo object -- Arnaud From steven.bethard at gmail.com Sun May 20 17:24:22 2007 From: steven.bethard at gmail.com (Steven Bethard) Date: Sun, 20 May 2007 09:24:22 -0600 Subject: [Python-ideas] Positional only arguments In-Reply-To: <61964.80.195.169.49.1179559363.squirrel@webmail.marooned.org.uk> References: <464e780e.562683cf.2949.0fe8SMTPIN_ADDED@mx.google.com> <464E8FF7.5000208@acm.org> <61964.80.195.169.49.1179559363.squirrel@webmail.marooned.org.uk> Message-ID: On 5/19/07, Arnaud Delobelle wrote: > > On Sat, May 19, 2007 7:40 am, Steven Bethard wrote: > [...] > > So should I take that as a +1 for: > > > > * Enforce double-underscore names as being positional-only syntactically, > > e.g.:: > > > > def f(__a, __b=None, *, c=42, **kwargs) > > > > Pro: requires no new syntax > > Con: slightly backwards incompatible (but who calls f(__a) anyway?) > > - There is also incompatibility in the definition of functions: 'def f(a, > __b)' is currently correct, it wouldn't be anymore. Good point. Though I also suspect that's pretty low frequency. > - How would this work with name mangling and methods? For example: > > class Foo(object): > def posfun(__self, __a, b, ...): > > * Would self have to be renamed __self? (As positional only arguments > should come first) Yes. > * Would __self and __a be mangled, as is the rule within classes up to > now? If so care has to be taken I suppose. I don't see any reason to mangle them. The only time you'd ever notice is using locals(). I've also noticed that the current @posonly decorator won't solve the dict() and dict.update() problem:: >>> @posonly(2) ... def update(self, container=None, **kwargs): ... print self, container, kwargs ... >>> update(self=1, other=2) Traceback (most recent call last): File "", line 1, in File "", line 8, in posf raise TypeError("%s() arg '%s' is posonly" % (name, kw)) TypeError: update() arg 'self' is posonly I think it should probably be defined as something like:: def posonly(n=None): def get_positional_only_wrapper(func, n=n): if n is None: n = func.func_code.co_argcount n -= len(func.func_defaults) def positional_only_wrapper(*args, **kwargs): if len(args) < n: msg = '%s() expected %i positional arguments, found %i' raise TypeError(msg % (func.__name__, n, len(args))) return func(*args, **kwargs) return positional_only_wrapper return get_positional_only_wrapper But note that this still doesn't solve the dict() and dict.update() problem because we still can't get 'self' and 'container' in the **kwargs:: >>> @posonly(2) ... def update(self, container=None, **kwargs): ... print self, container, kwargs ... >>> update('foo', self=1, other=2) Traceback (most recent call last): File "", line 1, in File "", line 10, in positional_only_wrapper return func(*args, **kwargs) TypeError: update() got multiple values for keyword argument 'self' STeVe -- I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a tiny blip on the distant coast of sanity. --- Bucky Katt, Get Fuzzy From george.sakkis at gmail.com Sun May 20 18:31:40 2007 From: george.sakkis at gmail.com (George Sakkis) Date: Sun, 20 May 2007 12:31:40 -0400 Subject: [Python-ideas] Positional only arguments In-Reply-To: References: <464e780e.562683cf.2949.0fe8SMTPIN_ADDED@mx.google.com> <464E8FF7.5000208@acm.org> <61964.80.195.169.49.1179559363.squirrel@webmail.marooned.org.uk> Message-ID: <91ad5bf80705200931q53325a33t3bc231306382af09@mail.gmail.com> On 5/20/07, Steven Bethard wrote: > On 5/19/07, Arnaud Delobelle wrote: > > - How would this work with name mangling and methods? For example: > > > > class Foo(object): > > def posfun(__self, __a, b, ...): > > > > * Would self have to be renamed __self? (As positional only arguments > > should come first) > > Yes. Ouch, hadn't thought of that. Many people find explicit self ugly, and now you'll tell them they *have to* spell it __self (or __s for fewer keystrokes) ? That's indeed ugly. The semicolon proposal looks better, at least for this case: class Foo(object): def posfun(self, a; b, ...): George -- "If I have been able to see further, it was only because I stood on the shoulders of million monkeys." From rrr at ronadam.com Sun May 20 19:08:20 2007 From: rrr at ronadam.com (Ron Adam) Date: Sun, 20 May 2007 12:08:20 -0500 Subject: [Python-ideas] Positional only arguments In-Reply-To: <91ad5bf80705200931q53325a33t3bc231306382af09@mail.gmail.com> References: <464e780e.562683cf.2949.0fe8SMTPIN_ADDED@mx.google.com> <464E8FF7.5000208@acm.org> <61964.80.195.169.49.1179559363.squirrel@webmail.marooned.org.uk> <91ad5bf80705200931q53325a33t3bc231306382af09@mail.gmail.com> Message-ID: <46508084.9080708@ronadam.com> George Sakkis wrote: > On 5/20/07, Steven Bethard wrote: >> On 5/19/07, Arnaud Delobelle wrote: >>> - How would this work with name mangling and methods? For example: >>> >>> class Foo(object): >>> def posfun(__self, __a, b, ...): >>> >>> * Would self have to be renamed __self? (As positional only arguments >>> should come first) >> Yes. > > Ouch, hadn't thought of that. Many people find explicit self ugly, and > now you'll tell them they *have to* spell it __self (or __s for fewer > keystrokes) ? That's indeed ugly. > > The semicolon proposal looks better, at least for this case: > > class Foo(object): > def posfun(self, a; b, ...): I would also say identifying the semicolon isn't a problem. After all we've been telling the difference between periods and comma's for quite a long time now with no difficulty. So it's more a matter of just getting used to looking for it in function signatures. Ron From steven.bethard at gmail.com Sun May 20 19:13:01 2007 From: steven.bethard at gmail.com (Steven Bethard) Date: Sun, 20 May 2007 11:13:01 -0600 Subject: [Python-ideas] Positional only arguments In-Reply-To: References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> Message-ID: On 5/18/07, Adam Olsen wrote: > On 5/18/07, Steven Bethard wrote: > > > > In the hopes of keeping this discussion enough on track that we can > > eventually come to a conclusion, I thought I'd just take a couple > > minutes to summarize the proposals so far. I'm looking at the > > following function as an example:: > > > > def f(a, b=None, *, c=42, **kwargs) > > > > where ``a`` and ``b`` should be positional-only and ``c`` should be > > keyword-only. Here are the alternatives I've seen so far: > > * Use ** for keyword-only and * for positional-only: > > def (a, b=None, *, **, c=42, **kwargs): > > Pro: backwards compatible, reuses existing meanings > Con: requires new syntax, changes keyword-only PEP I like the idea of matching the * with positional-only arguments and the ** with keyword-only arguments. In the example above though, I don't really like how we look forward for ** but backward for *. I feel like I the semantics should instead be:: - Everything after a * is a positional-only argument - Everything after a ** is a keyword-only argument These interpretations are consistent with the current meanings of *args and **kwargs. So to write the dict() or dict.update() signatures, we'd write:: def update(*, self, container=None, **kwargs) And to write the signature from my example, we'd write:: def f(*, a, b=None, **, c=42, **kwargs) My only use cases are for functions with '*' at the beginning, because the only time I care about having positional only arguments is when I also have a **kwargs, and in that situation, I want *all* other arguments to be positional only. Does anyone have a use case that requires both positional-only and positional-or-keyword arguments? STeVe -- I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a tiny blip on the distant coast of sanity. --- Bucky Katt, Get Fuzzy From steven.bethard at gmail.com Sun May 20 19:16:47 2007 From: steven.bethard at gmail.com (Steven Bethard) Date: Sun, 20 May 2007 11:16:47 -0600 Subject: [Python-ideas] Positional only arguments In-Reply-To: <46508084.9080708@ronadam.com> References: <464e780e.562683cf.2949.0fe8SMTPIN_ADDED@mx.google.com> <464E8FF7.5000208@acm.org> <61964.80.195.169.49.1179559363.squirrel@webmail.marooned.org.uk> <91ad5bf80705200931q53325a33t3bc231306382af09@mail.gmail.com> <46508084.9080708@ronadam.com> Message-ID: On 5/20/07, Ron Adam wrote: > George Sakkis wrote: > > The semicolon proposal looks better, at least for this case: > > > > class Foo(object): > > def posfun(self, a; b, ...): > > I would also say identifying the semicolon isn't a problem. After all > we've been telling the difference between periods and comma's for quite a > long time now with no difficulty. So it's more a matter of just getting > used to looking for it in function signatures. Of course, in most Python code, there are spaces after commas, but not periods:: (foo, bar, baz) foo.bar.baz In the semi-colon proposal, the spacing around commas and semi-colons will be exactly the same. That said, I'd really like positional-only arguments one way or another, so if they have to come with a semi-colon, I'm willing to accept that. STeVe -- I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a tiny blip on the distant coast of sanity. --- Bucky Katt, Get Fuzzy From arno at marooned.org.uk Sun May 20 20:59:29 2007 From: arno at marooned.org.uk (Arnaud Delobelle) Date: Sun, 20 May 2007 19:59:29 +0100 (BST) Subject: [Python-ideas] Positional only arguments In-Reply-To: References: <464e780e.562683cf.2949.0fe8SMTPIN_ADDED@mx.google.com> <464E8FF7.5000208@acm.org> <61964.80.195.169.49.1179559363.squirrel@webmail.marooned.org.uk> Message-ID: <64296.80.195.169.49.1179687569.squirrel@webmail.marooned.org.uk> On Sun, May 20, 2007 4:24 pm, Steven Bethard wrote: > On 5/19/07, Arnaud Delobelle wrote: [...] >> * Would __self and __a be mangled, as is the rule within classes up to >> now? If so care has to be taken I suppose. > > I don't see any reason to mangle them. The only time you'd ever > notice is using locals(). I was asking because this means name mangling will have to be triggered conditionally in this case. > > I've also noticed that the current @posonly decorator won't solve the > dict() and dict.update() problem:: > >>>> @posonly(2) > ... def update(self, container=None, **kwargs): > ... print self, container, kwargs > ... >>>> update(self=1, other=2) > Traceback (most recent call last): > File "", line 1, in > File "", line 8, in posf > raise TypeError("%s() arg '%s' is posonly" % (name, kw)) > TypeError: update() arg 'self' is posonly Yes. I don't see how this can be avoided in pure Python. But I came up with the solution below (I'm not saying it's good :) def posonly(arg=0, safe_kwargs=False): def deco(f, nposargs=0): name = f.__name__ if nposargs == 0: nposargs = f.func_code.co_argcount if safe_kwargs: nposargs += 1 posargnames = f.func_code.co_varnames[:nposargs] if safe_kwargs: def posf(*args, **kwargs): safe_kwargs = dict((k, kwargs.pop(k)) for k in posargnames if kwargs.has_key(k)) return f(safe_kwargs, *args, **kwargs) else: def posf(*args, **kwargs): for kw in kwargs: if kw in posargnames: raise TypeError("'%s()' arg %s is posonly" % (name, kw)) return f(*args, **kwargs) posf.__name__ = name return posf if isinstance(arg, int): return lambda f: deco(f, arg) else: return deco(arg) Note: again this is a 'proof of concept' implementation. Perhaps I should have started from my own implementation of 'posonly' instead of mine... If the optional argument 'safe_kwargs' is set to True, then the decorated function must provide an extra first positional argument which will contain the keyword arguments whose name is one of the positional argument names. >>> class MyDict(object): >>> @posonly(2, safe_kwargs=True) >>> def update(safe_kwargs, self, container=None, **kwargs): >>> return self, container, safe_kwargs, kwargs >>> d=MyDict() >>> d.update({1:2}, self=3, other=5) >>> (<__main__.MyDict object at 0x133c3d0>, {1: 2}, {'self': 3}, {'other': 5}) It solves the problem I think. It's not the most elegant but the question is whether the need for such a feature is strong enough to require new syntax. My personal opinion is that it isn't, as I've never needed it :) but I have limited experience. One could imagine a 'all_safe_kwargs' optional argument to posonly that would pack all the keyword arguments together and pass them on to the decorated function so that dict.update could be written: @posonly(2, all_safe_kwargs=True) def update(kwargs, self, container=None): # All keyword args are now in 'kwargs' ... -- Arnaud From steven.bethard at gmail.com Sun May 20 22:32:52 2007 From: steven.bethard at gmail.com (Steven Bethard) Date: Sun, 20 May 2007 14:32:52 -0600 Subject: [Python-ideas] Positional only arguments In-Reply-To: <64296.80.195.169.49.1179687569.squirrel@webmail.marooned.org.uk> References: <464e780e.562683cf.2949.0fe8SMTPIN_ADDED@mx.google.com> <464E8FF7.5000208@acm.org> <61964.80.195.169.49.1179559363.squirrel@webmail.marooned.org.uk> <64296.80.195.169.49.1179687569.squirrel@webmail.marooned.org.uk> Message-ID: On 5/20/07, Arnaud Delobelle wrote: > On Sun, May 20, 2007 4:24 pm, Steven Bethard wrote: > > I've also noticed that the current @posonly decorator won't solve the > > dict() and dict.update() problem:: [snip] > Yes. I don't see how this can be avoided in pure Python. But I came up > with the solution below (I'm not saying it's good :) [snip] > >>> class MyDict(object): > >>> @posonly(2, safe_kwargs=True) > >>> def update(safe_kwargs, self, container=None, **kwargs): > >>> return self, container, safe_kwargs, kwargs Since currently the only use case for positional-only arguments is the dict() and dict.update() signature, I would simplify the decorator to look like:: def positional_kwargs(func): def func_with_positional_kwargs(*args, **kwargs): n_missing = func.func_code.co_argcount - len(args) - 1 args += func.func_defaults[-n_missing - 1:-1] args += (kwargs,) return func(*args) functools.update_wrapper(func_with_positional_kwargs, func) return func_with_positional_kwargs You could use it like:: >>> class D(object): ... @positional_kwargs ... def __init__(self, container=None, kwargs={}): ... print self, container, kwargs ... >>> d = D(self=1, container=2) <__main__.D object at 0x00F05E30> None {'self': 1, 'container': 2} That's not too bad because you're just replacing **kwargs with kwargs={}. And it's relatively easy to explain. I guess that would cover all the use cases I care about. I still lean slightly towards the lone '*' and '**' proposal, particularly since one of them is already introduced by `PEP 3102`_, but putting this decorator in functools is a good backup plan. .. _PEP 3102: http://www.python.org/dev/peps/pep-3102/ STeVe -- I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a tiny blip on the distant coast of sanity. --- Bucky Katt, Get Fuzzy From george.sakkis at gmail.com Mon May 21 02:11:04 2007 From: george.sakkis at gmail.com (George Sakkis) Date: Sun, 20 May 2007 20:11:04 -0400 Subject: [Python-ideas] Positional only arguments In-Reply-To: References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> Message-ID: <91ad5bf80705201711l4debd819ybde15aaf38a94045@mail.gmail.com> On 5/20/07, Steven Bethard wrote: > So to write the dict() or dict.update() signatures, we'd write:: > > def update(*, self, container=None, **kwargs) > > And to write the signature from my example, we'd write:: > > def f(*, a, b=None, **, c=42, **kwargs) > > My only use cases are for functions with '*' at the beginning, because > the only time I care about having positional only arguments is when I > also have a **kwargs, and in that situation, I want *all* other > arguments to be positional only. > > Does anyone have a use case that requires both positional-only and > positional-or-keyword arguments? I don't have a hard use case, but more of a good API design argument, similar to those used to support the second subproposal of PEP 3102 (e.g. see [1]). Maybe it's just me but I often cannot find a good name for a parameter (at least not when I first write it) or I think of a more appropriate name later. I'd like to be able to go back and change it, knowing it won't break anything as it is always passed positionally. IOW, it's a way to say "these names are not part of the function's signature" and enforce this rather than just document it. For instance, think of a function that initially was designed to work for sequences and was defined as "def f(sequence, **kwds)". Later the implementor realizes that the same function works (or its implementation can easily change so that it works) for arbitrary iterables. It would be nice to go back and change the signature to "def f(iterable, **kwds)", knowing that nobody is calling it as f(sequence=range(10)). George [1] http://mail.python.org/pipermail/python-dev/2006-May/064695.html -- "If I have been able to see further, it was only because I stood on the shoulders of million monkeys." From steven.bethard at gmail.com Mon May 21 02:26:23 2007 From: steven.bethard at gmail.com (Steven Bethard) Date: Sun, 20 May 2007 18:26:23 -0600 Subject: [Python-ideas] Positional only arguments In-Reply-To: <91ad5bf80705201711l4debd819ybde15aaf38a94045@mail.gmail.com> References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> <91ad5bf80705201711l4debd819ybde15aaf38a94045@mail.gmail.com> Message-ID: On 5/20/07, George Sakkis wrote: > On 5/20/07, Steven Bethard wrote: > > > So to write the dict() or dict.update() signatures, we'd write:: > > > > def update(*, self, container=None, **kwargs) > > > > And to write the signature from my example, we'd write:: > > > > def f(*, a, b=None, **, c=42, **kwargs) > > > > My only use cases are for functions with '*' at the beginning, because > > the only time I care about having positional only arguments is when I > > also have a **kwargs, and in that situation, I want *all* other > > arguments to be positional only. > > > > Does anyone have a use case that requires both positional-only and > > positional-or-keyword arguments? [snip] > For instance, think of a function that initially was designed to work > for sequences and was defined as "def f(sequence, **kwds)". Later the > implementor realizes that the same function works (or its > implementation can easily change so that it works) for arbitrary > iterables. It would be nice to go back and change the signature to > "def f(iterable, **kwds)", knowing that nobody is calling it as > f(sequence=range(10)). This is a good example for why you might want positional-only arguments. But I guess I wasn't clear -- I'm looking for an example where you need both a positional-only argument and a positional-or-keyword argument *in the same signature*. The reason I ask is that I'd like to propose that the lone * can only appear at the beginning of the signature. That would cover the dict() and dict.update() use cases as well as your use case above:: def f(*, sequence, **kwds) Are there any use cases that it wouldn't cover? Seems like the cautious programmer from your example above would want all of his positional arguments to be positional-only. STeVe -- I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a tiny blip on the distant coast of sanity. --- Bucky Katt, Get Fuzzy From george.sakkis at gmail.com Mon May 21 04:14:05 2007 From: george.sakkis at gmail.com (George Sakkis) Date: Sun, 20 May 2007 22:14:05 -0400 Subject: [Python-ideas] Positional only arguments In-Reply-To: References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> <91ad5bf80705201711l4debd819ybde15aaf38a94045@mail.gmail.com> Message-ID: <91ad5bf80705201914m2443aa7atfe4d5250bfd0d164@mail.gmail.com> On 5/20/07, Steven Bethard wrote: > On 5/20/07, George Sakkis wrote: > > On 5/20/07, Steven Bethard wrote: > > > > > So to write the dict() or dict.update() signatures, we'd write:: > > > > > > def update(*, self, container=None, **kwargs) > > > > > > And to write the signature from my example, we'd write:: > > > > > > def f(*, a, b=None, **, c=42, **kwargs) > > > > > > My only use cases are for functions with '*' at the beginning, because > > > the only time I care about having positional only arguments is when I > > > also have a **kwargs, and in that situation, I want *all* other > > > arguments to be positional only. > > > > > > Does anyone have a use case that requires both positional-only and > > > positional-or-keyword arguments? > [snip] > > For instance, think of a function that initially was designed to work > > for sequences and was defined as "def f(sequence, **kwds)". Later the > > implementor realizes that the same function works (or its > > implementation can easily change so that it works) for arbitrary > > iterables. It would be nice to go back and change the signature to > > "def f(iterable, **kwds)", knowing that nobody is calling it as > > f(sequence=range(10)). > > This is a good example for why you might want positional-only > arguments. But I guess I wasn't clear -- I'm looking for an example > where you need both a positional-only argument and a > positional-or-keyword argument *in the same signature*. > > The reason I ask is that I'd like to propose that the lone * can only > appear at the beginning of the signature. That would cover the dict() > and dict.update() use cases as well as your use case above:: > > def f(*, sequence, **kwds) > > Are there any use cases that it wouldn't cover? Seems like the > cautious programmer from your example above would want all of his > positional arguments to be positional-only. Are you proposing the removal of positional-or-keyword arguments altogether or only in the presence of positional-only ? In the former case, perhaps this needs a separate thread on its own as it's too big of a change. In the latter case, whatever reasons one has for using positional-or-keyword arguments, chances are that they will hold also in the presence of positional-only. Honestly, I can't think of a compelling reason for positional-or-keyword arguments (with or without the presence of positional-only in the same signature) other than that by definition offer two ways to the caller to spell the same thing. Even that could be considered a misfeature since it goes against TOOWTDI. In any case, that's more of a language design and philosophy argument ("should the caller of a function have the freedom on how to pass the arguments or that should be decided only by the function writer ?") rather than a hard use case. George -- "If I have been able to see further, it was only because I stood on the shoulders of million monkeys." From steven.bethard at gmail.com Mon May 21 04:35:37 2007 From: steven.bethard at gmail.com (Steven Bethard) Date: Sun, 20 May 2007 20:35:37 -0600 Subject: [Python-ideas] Positional only arguments In-Reply-To: <91ad5bf80705201914m2443aa7atfe4d5250bfd0d164@mail.gmail.com> References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> <91ad5bf80705201711l4debd819ybde15aaf38a94045@mail.gmail.com> <91ad5bf80705201914m2443aa7atfe4d5250bfd0d164@mail.gmail.com> Message-ID: On 5/20/07, George Sakkis wrote: > Are you proposing the removal of positional-or-keyword arguments No. My current proposal is: - Everything after a * is a positional-only argument, up to the first ** - Everything after a ** is a keyword-only argument - A lone * may only appear at the beginning of the signature In essence, this is changing the lone * of `PEP 3102`_ into a lone **, and allowing a lone * at the beginning of the signature to indicate that all positional arguments are positional-only. .. _PEP 3102: http://www.python.org/dev/peps/pep-3102/ That means that in the following signature:: def f(*, a, b=None, *args, **, c=42, **kwargs) - 'a' and 'b' are positional-only - 'args' is positional-only (as usual) - 'c' is keyword-only - 'kwargs' is keyword-only (as usual) If you want positional-or-keyword arguments, simply omit the initial *:: def f(a, b=None, *args, **, c=42, **kwargs) - 'a' and 'b' are positional-or-keyword (as usual) - 'args' is positional-only (as usual) - 'c' is keyword-only - 'kwargs' is keyword-only (as usual) If you want keyword-only arguments with no *args, simply omit it:: def f(a, b=None, **, c=42, **kwargs) - 'a' and 'b' are positional-or-keyword (as usual) - 'c' is keyword-only - 'kwargs' is keyword-only (as usual) Does anyone have use cases that this doesn't cover? STeVe -- I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a tiny blip on the distant coast of sanity. --- Bucky Katt, Get Fuzzy From aahz at pythoncraft.com Mon May 21 06:24:57 2007 From: aahz at pythoncraft.com (Aahz) Date: Sun, 20 May 2007 21:24:57 -0700 Subject: [Python-ideas] Ideas towards GIL removal In-Reply-To: <4622BAD4.2020706@canterbury.ac.nz> References: <461ED2F9.9020407@canterbury.ac.nz> <46225CE4.4040207@acm.org> <4622BAD4.2020706@canterbury.ac.nz> Message-ID: <20070521042456.GA26693@panix.com> On Mon, Apr 16, 2007, Greg Ewing wrote: > Brett Cannon wrote: >> >> And I know some people love the (mostly) instantaneous garbage >> collection when the refcount should be at 0. > > Yeah, and even a 6 millisecond pause could be too long in some > applications, such as high frame rate animation. 6 milliseconds is a > *long* time for today's GHz processors. Hrm. Assuming that really is the maximum, I don't think it's an issue for Python applications: 6ms slices still allow for >150 frames/sec. If overall object creation/destruction throughput is increased or this allows greater throughput on multi-core machines without dramatically decreasing performance for single-CPU machines, it may well be worthwhile. But my primary concern remains the issue of Python being a glue language with external libraries: the GIL is one of our best weapons for making it easy. This approach seems like it would be easier to integrate than other options I've seen. -- Aahz (aahz at pythoncraft.com) <*> http://www.pythoncraft.com/ "Look, it's your affair if you want to play with five people, but don't go calling it doubles." --John Cleese anticipates Usenet From rhamph at gmail.com Mon May 21 08:36:42 2007 From: rhamph at gmail.com (Adam Olsen) Date: Mon, 21 May 2007 00:36:42 -0600 Subject: [Python-ideas] Positional only arguments In-Reply-To: References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> <91ad5bf80705201711l4debd819ybde15aaf38a94045@mail.gmail.com> <91ad5bf80705201914m2443aa7atfe4d5250bfd0d164@mail.gmail.com> Message-ID: On 5/20/07, Steven Bethard wrote: > On 5/20/07, George Sakkis wrote: > > Are you proposing the removal of positional-or-keyword arguments > > No. My current proposal is: > > - Everything after a * is a positional-only argument, up to the first ** > - Everything after a ** is a keyword-only argument > - A lone * may only appear at the beginning of the signature > > In essence, this is changing the lone * of `PEP 3102`_ into a lone **, > and allowing a lone * at the beginning of the signature to indicate > that all positional arguments are positional-only. > > .. _PEP 3102: http://www.python.org/dev/peps/pep-3102/ > > That means that in the following signature:: > > def f(*, a, b=None, *args, **, c=42, **kwargs) > > - 'a' and 'b' are positional-only > - 'args' is positional-only (as usual) > - 'c' is keyword-only > - 'kwargs' is keyword-only (as usual) > > If you want positional-or-keyword arguments, simply omit the initial *:: > > def f(a, b=None, *args, **, c=42, **kwargs) ** is redundant here. You get the same behaviour without it: def f(a, b=None, *args, c=42, **kwargs) See below though. > - 'a' and 'b' are positional-or-keyword (as usual) > - 'args' is positional-only (as usual) > - 'c' is keyword-only > - 'kwargs' is keyword-only (as usual) > > If you want keyword-only arguments with no *args, simply omit it:: > > def f(a, b=None, **, c=42, **kwargs) > > - 'a' and 'b' are positional-or-keyword (as usual) > - 'c' is keyword-only > - 'kwargs' is keyword-only (as usual) > > Does anyone have use cases that this doesn't cover? I initially had the same reservations you do about my proposal, but now I think there's a bigger problem: it undermines the obviousness of PEP 3102's behaviour. Consider this example: def compare(a, b, *args, key=None): Although not legal today, the behaviour is obvious. All positional arguments get sucked up in *args so key *must* be keyword-only. That leads to this variant: def compare(a, b, *, key=None): You continue sucking up extra positional args, but since it's nameless there must be none of them. Again, obvious. Changing the token required from * to ** or giving * extra behaviour when nameless just isn't obvious. Most of the proposed syntax changes also have a question of whether or not to include *args: "def f(a, *, *args)" or "def(a, *args, *)"? "def f((a), *args)" or "def f((a, *args))"? "def f(__a, *args)" or "def(__a, *__args)"? Finally (I hope) is the problem of motivation. Where as PEP 3102 is motivated by "explicit is better than implicit", positional-only arguments actually *want* implicit! It seems to be more for completeness and "C functions already support it". -1 on any syntax changes. A decorator may be okay, but I'm unsure the use cases are significant enough to warrant adding it. Go figure. -- Adam Olsen, aka Rhamphoryncus From steven.bethard at gmail.com Mon May 21 08:58:43 2007 From: steven.bethard at gmail.com (Steven Bethard) Date: Mon, 21 May 2007 00:58:43 -0600 Subject: [Python-ideas] Positional only arguments In-Reply-To: References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> <91ad5bf80705201711l4debd819ybde15aaf38a94045@mail.gmail.com> <91ad5bf80705201914m2443aa7atfe4d5250bfd0d164@mail.gmail.com> Message-ID: On 5/21/07, Adam Olsen wrote: > On 5/20/07, Steven Bethard wrote: > > No. My current proposal is: > > > > - Everything after a * is a positional-only argument, up to the first ** > > - Everything after a ** is a keyword-only argument > > - A lone * may only appear at the beginning of the signature > > > > In essence, this is changing the lone * of `PEP 3102`_ into a lone **, > > and allowing a lone * at the beginning of the signature to indicate > > that all positional arguments are positional-only. > > > > .. _PEP 3102: http://www.python.org/dev/peps/pep-3102/ > > > > That means that in the following signature:: > > > > def f(*, a, b=None, *args, **, c=42, **kwargs) > > > > - 'a' and 'b' are positional-only > > - 'args' is positional-only (as usual) > > - 'c' is keyword-only > > - 'kwargs' is keyword-only (as usual) > > > > If you want positional-or-keyword arguments, simply omit the initial *:: > > > > def f(a, b=None, *args, **, c=42, **kwargs) > > ** is redundant here. You get the same behaviour without it: > > def f(a, b=None, *args, c=42, **kwargs) > > See below though. I note that below you argue for explicit is better than implicit. Requiring the ** even when it could be inferred from the *args is a good example of EIBTI. I don't have strong feelings on this issue though. > I initially had the same reservations you do about my proposal, but > now I think there's a bigger problem: it undermines the obviousness of > PEP 3102's behaviour. [snip] > > def compare(a, b, *, key=None): > > You continue sucking up extra positional args, but since it's nameless > there must be none of them. Again, obvious. I have to disagree. The first thing I think when I see a lone * is multiplication, not "keyword-only arguments start after me". I would say it's just as obvious to see:: def g(*, a, b) and say, "oh, it's after a * so it must be positional-only just like *args is". That is, I don't think the PEP 3102 meaning for lone * is any more intuitive than the meaning I'm proposing here. > Where as PEP 3102 is motivated by "explicit is better than implicit", > positional-only arguments actually *want* implicit! I don't follow this logic. How is a positional-only argument more implicit? You still have to supply it on every function call. It's not like you can omit it. Or are you saying that using positional arguments instead of keyword arguments is implicit? > A decorator may be okay, but I'm unsure the > use cases are significant enough to warrant adding it. Just for reference, here are the current motivating use cases: * User mapping types that need to match the dict() and dict.update() method signatures * Code where positional argument names might change, e.g. George's def f(sequence) which later becomes def f(iterable) Particularly since user mappings are relatively common, I do think this issue deserves at least a decorator. STeVe -- I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a tiny blip on the distant coast of sanity. --- Bucky Katt, Get Fuzzy From steven.bethard at gmail.com Mon May 21 09:08:58 2007 From: steven.bethard at gmail.com (Steven Bethard) Date: Mon, 21 May 2007 01:08:58 -0600 Subject: [Python-ideas] Positional only arguments In-Reply-To: References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> <91ad5bf80705201711l4debd819ybde15aaf38a94045@mail.gmail.com> <91ad5bf80705201914m2443aa7atfe4d5250bfd0d164@mail.gmail.com> Message-ID: On 5/21/07, Adam Olsen wrote: > now I think there's a bigger problem: it undermines the obviousness of > PEP 3102's behaviour. > > Consider this example: > > def compare(a, b, *args, key=None): > > Although not legal today, the behaviour is obvious. All positional > arguments get sucked up in *args so key *must* be keyword-only. This may not be so obvious anymore now that we have extended iterable unpacking from `PEP 3132`_. Given an iterable unpacking like:: a, b, *c, d = iterable I may assume that names after a *args work just like names before one:: def f(a, b, *c, d) So in this case I'd assume that the 'd' is also positional, not keyword-only. Again, I'm not saying people can't learn the appropriate meaning, just that it's not inherently obvious. .. _PEP 3132: http://www.python.org/dev/peps/pep-3132/ STeVe -- I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a tiny blip on the distant coast of sanity. --- Bucky Katt, Get Fuzzy From greg.ewing at canterbury.ac.nz Mon May 21 09:07:12 2007 From: greg.ewing at canterbury.ac.nz (Greg Ewing) Date: Mon, 21 May 2007 19:07:12 +1200 Subject: [Python-ideas] Positional only arguments In-Reply-To: References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> <91ad5bf80705201711l4debd819ybde15aaf38a94045@mail.gmail.com> <91ad5bf80705201914m2443aa7atfe4d5250bfd0d164@mail.gmail.com> Message-ID: <46514520.2040907@canterbury.ac.nz> Steven Bethard wrote: > That means that in the following signature:: > > def f(*, a, b=None, *args, **, c=42, **kwargs) I don't like this. Having more than one * or ** in the same signature seems like it would be very confusing. I think the desire for positional-only args would be addressed well enough using a naming convention. Even without further explanation, if I saw something like def f(_a, _b, _c): ... it would be pretty clear to me that the author intended the parameter names to be an implementation detail. This could even be enforced if relying on a convention were not considered strong enough, although it would be more consistent to insist on a double underscore to get automatic enforcement. -- Greg From steven.bethard at gmail.com Mon May 21 09:15:49 2007 From: steven.bethard at gmail.com (Steven Bethard) Date: Mon, 21 May 2007 01:15:49 -0600 Subject: [Python-ideas] Positional only arguments In-Reply-To: <46514520.2040907@canterbury.ac.nz> References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> <91ad5bf80705201711l4debd819ybde15aaf38a94045@mail.gmail.com> <91ad5bf80705201914m2443aa7atfe4d5250bfd0d164@mail.gmail.com> <46514520.2040907@canterbury.ac.nz> Message-ID: On 5/21/07, Greg Ewing wrote: > I think the desire for positional-only args would be > addressed well enough using a naming convention. Even > without further explanation, if I saw something like > > def f(_a, _b, _c): > ... > > it would be pretty clear to me that the author intended > the parameter names to be an implementation detail. So what about the signature for dict() and dict.update() where you want to write:: def update(self, container=None, **kwargs) Note that I shouldn't want to write '__container' because it's not an implementation detail. It's a valid positional argument that my clients can use. But if I write 'container', then I'm limiting what they can send as **kwargs and I can't reproduce the dict behavior:: >>> d = {} >>> d.update(container=1) >>> d {'container': 1} STeVe -- I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a tiny blip on the distant coast of sanity. --- Bucky Katt, Get Fuzzy From greg.ewing at canterbury.ac.nz Mon May 21 09:14:57 2007 From: greg.ewing at canterbury.ac.nz (Greg Ewing) Date: Mon, 21 May 2007 19:14:57 +1200 Subject: [Python-ideas] Ideas towards GIL removal In-Reply-To: <20070521042456.GA26693@panix.com> References: <461ED2F9.9020407@canterbury.ac.nz> <46225CE4.4040207@acm.org> <4622BAD4.2020706@canterbury.ac.nz> <20070521042456.GA26693@panix.com> Message-ID: <465146F1.2090408@canterbury.ac.nz> Aahz wrote: > > On Mon, Apr 16, 2007, Greg Ewing wrote: > > > even a 6 millisecond pause could be too long in some > > applications, such as high frame rate animation. > > 6ms slices still allow for >150 frames/sec. Only if you don't want to do anything else during your frame. At 50fps, 6ms is nearly one-third of your frame time. However, I tend to agree that this approach has the greatest chance of succeeding of any suggestion I've seen so far. -- Greg From greg.ewing at canterbury.ac.nz Mon May 21 09:39:34 2007 From: greg.ewing at canterbury.ac.nz (Greg Ewing) Date: Mon, 21 May 2007 19:39:34 +1200 Subject: [Python-ideas] Positional only arguments In-Reply-To: References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> <91ad5bf80705201711l4debd819ybde15aaf38a94045@mail.gmail.com> <91ad5bf80705201914m2443aa7atfe4d5250bfd0d164@mail.gmail.com> Message-ID: <46514CB6.6050203@canterbury.ac.nz> Steven Bethard wrote: > I don't think the PEP 3102 meaning for lone * is > any more intuitive than the meaning I'm proposing here. Although I wouldn't go so far as to call the PEP 3102 behaviour "obvious", it is a fairly *logical* extension of the existing semantics. On the other hand, a rule like "arguments after a lone * are positional-only" is something new and arbitrary. It doesn't follow logically from anything existing. Also, your proposal assigns two quite different meanings to *. If it's followed by a name, it sucks up all remaining positional args, but if it's not, it can't suck up anything, since it's followed by more positional args! -- Greg From greg.ewing at canterbury.ac.nz Mon May 21 09:45:31 2007 From: greg.ewing at canterbury.ac.nz (Greg Ewing) Date: Mon, 21 May 2007 19:45:31 +1200 Subject: [Python-ideas] Positional only arguments In-Reply-To: References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> <91ad5bf80705201711l4debd819ybde15aaf38a94045@mail.gmail.com> <91ad5bf80705201914m2443aa7atfe4d5250bfd0d164@mail.gmail.com> Message-ID: <46514E1B.9070904@canterbury.ac.nz> Steven Bethard wrote: > On 5/21/07, Adam Olsen wrote: > > > All positional > > arguments get sucked up in *args so key *must* be keyword-only. > > This may not be so obvious anymore now that we have extended iterable > unpacking from `PEP 3132`_. Given an iterable unpacking like:: > > a, b, *c, d = iterable I'm not in favour of allowing a * which isn't at the end here, for various reasons, one of which is that it weakens the analogy with call signatures. -- Greg From steven.bethard at gmail.com Mon May 21 10:16:57 2007 From: steven.bethard at gmail.com (Steven Bethard) Date: Mon, 21 May 2007 02:16:57 -0600 Subject: [Python-ideas] Positional only arguments In-Reply-To: <46514E1B.9070904@canterbury.ac.nz> References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> <91ad5bf80705201711l4debd819ybde15aaf38a94045@mail.gmail.com> <91ad5bf80705201914m2443aa7atfe4d5250bfd0d164@mail.gmail.com> <46514E1B.9070904@canterbury.ac.nz> Message-ID: On 5/21/07, Greg Ewing wrote: > Steven Bethard wrote: > > On 5/21/07, Adam Olsen wrote: > > > > > All positional > > > arguments get sucked up in *args so key *must* be keyword-only. > > > > This may not be so obvious anymore now that we have extended iterable > > unpacking from `PEP 3132`_. Given an iterable unpacking like:: > > > > a, b, *c, d = iterable > > I'm not in favour of allowing a * which isn't at the end > here, for various reasons, one of which is that it weakens > the analogy with call signatures. I wasn't either, but I believe the PEP has already been accepted and implemented. STeVe -- I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a tiny blip on the distant coast of sanity. --- Bucky Katt, Get Fuzzy From steven.bethard at gmail.com Mon May 21 10:18:58 2007 From: steven.bethard at gmail.com (Steven Bethard) Date: Mon, 21 May 2007 02:18:58 -0600 Subject: [Python-ideas] Positional only arguments In-Reply-To: <46514CB6.6050203@canterbury.ac.nz> References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> <91ad5bf80705201711l4debd819ybde15aaf38a94045@mail.gmail.com> <91ad5bf80705201914m2443aa7atfe4d5250bfd0d164@mail.gmail.com> <46514CB6.6050203@canterbury.ac.nz> Message-ID: On 5/21/07, Greg Ewing wrote: > Also, your proposal assigns two quite different meanings > to *. If it's followed by a name, it sucks up all remaining > positional args, but if it's not, it can't suck up > anything, since it's followed by more positional args! Note this is also true of the * in PEP 3102. STeVe -- I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a tiny blip on the distant coast of sanity. --- Bucky Katt, Get Fuzzy From rrr at ronadam.com Mon May 21 19:18:28 2007 From: rrr at ronadam.com (Ron Adam) Date: Mon, 21 May 2007 12:18:28 -0500 Subject: [Python-ideas] Positional only arguments In-Reply-To: References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> <91ad5bf80705201711l4debd819ybde15aaf38a94045@mail.gmail.com> <91ad5bf80705201914m2443aa7atfe4d5250bfd0d164@mail.gmail.com> Message-ID: <4651D464.2020806@ronadam.com> Steven Bethard wrote: > On 5/21/07, Adam Olsen wrote: >> On 5/20/07, Steven Bethard wrote: >>> No. My current proposal is: >>> >>> - Everything after a * is a positional-only argument, up to the first ** >>> - Everything after a ** is a keyword-only argument >>> - A lone * may only appear at the beginning of the signature >>> >>> In essence, this is changing the lone * of `PEP 3102`_ into a lone **, >>> and allowing a lone * at the beginning of the signature to indicate >>> that all positional arguments are positional-only. >>> >>> .. _PEP 3102: http://www.python.org/dev/peps/pep-3102/ >>> >>> That means that in the following signature:: >>> >>> def f(*, a, b=None, *args, **, c=42, **kwargs) >>> >>> - 'a' and 'b' are positional-only >>> - 'args' is positional-only (as usual) >>> - 'c' is keyword-only >>> - 'kwargs' is keyword-only (as usual) >>> >>> If you want positional-or-keyword arguments, simply omit the initial *:: >>> >>> def f(a, b=None, *args, **, c=42, **kwargs) >> ** is redundant here. You get the same behaviour without it: >> >> def f(a, b=None, *args, c=42, **kwargs) >> >> See below though. > > I note that below you argue for explicit is better than implicit. > Requiring the ** even when it could be inferred from the *args is a > good example of EIBTI. I don't have strong feelings on this issue > though. > >> I initially had the same reservations you do about my proposal, but >> now I think there's a bigger problem: it undermines the obviousness of >> PEP 3102's behaviour. > [snip] >> def compare(a, b, *, key=None): >> >> You continue sucking up extra positional args, but since it's nameless >> there must be none of them. Again, obvious. > > I have to disagree. The first thing I think when I see a lone * is > multiplication, not "keyword-only arguments start after me". I would > say it's just as obvious to see:: > > def g(*, a, b) > > and say, "oh, it's after a * so it must be positional-only just like > *args is". That is, I don't think the PEP 3102 meaning for lone * is > any more intuitive than the meaning I'm proposing here. I agree with Greg, it seems arbitrary. The number of meanings for the '*' is also growing too large I think. * multiply * pack in function defs # but at call time. * pack in left hand expressions # left of '=' * unpack in function calls * positional only indicator in function defs ** power ** pack dictionary in functions defs ** unpack dictionary in function calls ** keyword only indicator in function defs I'm sure this will get confusing to new users. Yes, each one is clear by context, but there's a lot of subtle behaviors by context going on here. What I would like is for unpack to be '^' instead of '*', then you would have... Packing operations: * multiply * pack in function defs * pack in left hand expressions ** power ** pack dictionary in functions defs Unpacking operations: ^ unpack in function calls ^ unpack in right hand expressions (possible) ^ positional only in function defs (See why I think so below) ^^ unpack dictionary in function calls ^^ keyword only in function defs (also see below) I think these become much easier to parse visually and mentally, so it's more of a human interface issue than a computer parsing issue. When using the "name=value" form in function definitions, it can be a positional or keyword argument. So all you need is a way to say this is either one or the other. (Using * here to show similarity, introducing the '^' further down.) *(b=2, c=3) positional only args *args rest of args **(b=2, c=3) keywords only kwds **kwds rest of keywords def f(a, *(b=2, c=3), *args) # b and c are positional only def f(a, **(b=2, c=3), **kwds) # b and c are keyword only Now the problem with this is when it's use with the *() and **() form, it resembles unpacking behavior, but in the *args, and **kwds form, it's packing behavior. Normally you would have only packing in a function def and unpacking in a function call. Now if we use ^ for unpacking, and * for packing, it reduces the number of meanings for the '*' and fixes the context of positional and keyword only arguments. def f(a, ^(b=2, c=3), *rest): b and c are positional only here. def f(a, d=5, ^^(b=2, c=3), **rest_kwds): # b and c are keywords only here. I feel this code better expresses it's intent. Think of the ^() as unpack these as args, and **() as unpack these as keywords. If '^' is used outside of function defs like the '*', it can retain it's meaning. a, b, *c = 1, 2, 3, 4, 5 # pack remainder z = (x, y, z) a, b, c, d = (a, ^z) # unpack z There is the possibility of extending this for use in other ways as well. xlist = [[1, 2], [3, 4, 5], [6, 7, 8, 9]] alist = [^x for x in xlist] This would have list "extend" behavior instead of list "append" behavior. Ok, just some possible ideas of how to organize all this. Cheers, Ron >> Where as PEP 3102 is motivated by "explicit is better than implicit", >> positional-only arguments actually *want* implicit! > > I don't follow this logic. How is a positional-only argument more > implicit? You still have to supply it on every function call. It's > not like you can omit it. Or are you saying that using positional > arguments instead of keyword arguments is implicit? > >> A decorator may be okay, but I'm unsure the >> use cases are significant enough to warrant adding it. > > Just for reference, here are the current motivating use cases: > > * User mapping types that need to match the dict() and dict.update() > method signatures > * Code where positional argument names might change, e.g. George's def > f(sequence) which later becomes def f(iterable) > > Particularly since user mappings are relatively common, I do think > this issue deserves at least a decorator. > > STeVe From steven.bethard at gmail.com Mon May 21 19:55:04 2007 From: steven.bethard at gmail.com (Steven Bethard) Date: Mon, 21 May 2007 11:55:04 -0600 Subject: [Python-ideas] Positional only arguments In-Reply-To: <4651D464.2020806@ronadam.com> References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> <91ad5bf80705201711l4debd819ybde15aaf38a94045@mail.gmail.com> <91ad5bf80705201914m2443aa7atfe4d5250bfd0d164@mail.gmail.com> <4651D464.2020806@ronadam.com> Message-ID: On 5/21/07, Ron Adam wrote: > Steven Bethard wrote: > > On 5/21/07, Adam Olsen wrote: > >> > >> def compare(a, b, *, key=None): > >> > >> You continue sucking up extra positional args, but since it's nameless > >> there must be none of them. Again, obvious. > > > > I have to disagree. The first thing I think when I see a lone * is > > multiplication, not "keyword-only arguments start after me". I would > > say it's just as obvious to see:: > > > > def g(*, a, b) > > > > and say, "oh, it's after a * so it must be positional-only just like > > *args is". That is, I don't think the PEP 3102 meaning for lone * is > > any more intuitive than the meaning I'm proposing here. > > I agree with Greg, it seems arbitrary. The number of meanings for the '*' > is also growing too large I think. Yes, both my proposal and the PEP 3102 use of * are pretty arbitrary, and I agree that we're probably getting too many uses of *. I'm going to try to post a decorator that I think will cover the use cases so far. > What I would like is for unpack to be '^' instead of '*' -1. This is at least as arbitrary as any of the '*', '**' or ';' suggestions, so I see no reason to prefer it. STeVe -- I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a tiny blip on the distant coast of sanity. --- Bucky Katt, Get Fuzzy From steven.bethard at gmail.com Mon May 21 20:30:38 2007 From: steven.bethard at gmail.com (Steven Bethard) Date: Mon, 21 May 2007 12:30:38 -0600 Subject: [Python-ideas] positional only arguments decorator Message-ID: Ok, looks like there's not much chance of agreeing on a syntax, so here's a decorator that covers the two use cases I know of:: * matching the signature of dict() and dict.update() * allowing arguments to have their names changed without worrying about backwards compatibility (e.g. ``def func(sequence)`` changing to ``def func(iterable)``) I've pasted the docstring and code below. The docstring should give you a pretty good idea of the functionality. Let me know if you have use cases this wouldn't cover. """ Functions declared ad @positional_only prohibit any arguments from being passed in as keyword arguments:: >>> @positional_only ... def foo(a, b=None, *args): ... return a, b, args ... >>> foo(1, 2, 3) (1, 2, (3,)) >>> foo(a=1, b=2) Traceback (most recent call last): ... TypeError: foo() does not allow keyword arguments Note that you can't use **kwargs arguments with a @positional_only function:: >>> @positional_only ... def foo(a, b=None, **kwargs): ... pass ... Traceback (most recent call last): ... TypeError: foo() may not have **kwargs If you need the functionality of **kwargs, you can request it by adding a final argument with the name _kwargs. The keyword arguments will be passed in (as a dict) through this argument:: >>> @positional_only ... def foo(a, b=None, _kwargs=None): ... return a, b, _kwargs ... >>> foo(1) (1, None, {}) >>> foo(1, 2) (1, 2, {}) >>> foo(1, bar=42, baz='spam') (1, None, {'baz': 'spam', 'bar': 42}) When your function is called with the wrong number of arguments, your callers will only see the number of arguments they expected. That is, argument counts will not include the _kwargs argument:: >>> foo() Traceback (most recent call last): ... TypeError: foo() takes at least 1 positional argument(s) (0 given) >>> foo(1, 2, 3) Traceback (most recent call last): ... TypeError: foo() takes at most 2 positional argument(s) (3 given) Note that unlike a normal **kwargs, using _kwargs in a @positional_only function causes *all* keyword arguments to be collected, even those with the same names as other function parameters:: >>> foo(1, a=42, b='spam') (1, None, {'a': 42, 'b': 'spam'}) >>> foo(1, _kwargs='this is just silly') (1, None, {'_kwargs': 'this is just silly'}) This is of course because all function parameters are considered to be positional only and therefore unnamed for the purposes of argument parsing. Note that you cannot use *args or **kwargs with the _kwargs argument:: >>> @positional_only ... def foo(a, b, _kwargs, *args): ... pass ... Traceback (most recent call last): ... TypeError: foo() may not have *args >>> @positional_only ... def foo(a, b, _kwargs, **kwargs): ... pass ... Traceback (most recent call last): ... TypeError: foo() may not have **kwargs """ import doctest import inspect import functools def positional_only(func): name = func.__name__ # don't allow **kwargs arg_names, args_name, kwargs_name, _ = inspect.getargspec(func) if kwargs_name is not None: raise TypeError('%s() may not have **kwargs' % name) # if no keyword arguments were requested, create a wrapper that # only accepts positional arguments (as *args) if not arg_names or arg_names[-1] != '_kwargs': # wrapper that raises an error for **kwargs def positional_wrapper(*args, **kwargs): if kwargs: msg = '%s() does not allow keyword arguments' raise TypeError(msg % name) return func(*args) # if keyword arguments were requested (through a final _kwargs), # create a wrapper that collects **kwargs and passes them in as # the final positional argument else: # don't allow *args if args_name is not None: msg = '%s() may not have *args' raise TypeError(msg % func.__name__) # determine defaults and expected argument counts defaults = func.func_defaults defaults = defaults and defaults[:-1] or [] n_expected = func.func_code.co_argcount - 1 min_expected = n_expected - len(defaults) def positional_wrapper(*args, **kwargs): # raise a TypeError for wrong number of arguments here # because func() needs to take the extra 'kwargs' # argument but the caller shouldn't know it arg_count_err = None if len(args) < min_expected: arg_count_err = 'at least %i' % min_expected if len(args) > n_expected: arg_count_err = 'at most %i' % n_expected if arg_count_err is not None: msg = '%s() takes %s positional argument(s) (%i given)' raise TypeError(msg % (name, arg_count_err, len(args))) # fill in defaults and add the final _kwargs argument, # then call the function with only positional arguments n_missing = n_expected - len(args) args += func.func_defaults[-n_missing - 1:-1] args += (kwargs,) return func(*args) # return the wrapped function functools.update_wrapper(positional_wrapper, func) return positional_wrapper if __name__ == '__main__': doctest.testmod() STeVe -- I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a tiny blip on the distant coast of sanity. --- Bucky Katt, Get Fuzzy From jimjjewett at gmail.com Tue May 22 00:47:01 2007 From: jimjjewett at gmail.com (Jim Jewett) Date: Mon, 21 May 2007 18:47:01 -0400 Subject: [Python-ideas] Positional only arguments In-Reply-To: References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> <91ad5bf80705201711l4debd819ybde15aaf38a94045@mail.gmail.com> <91ad5bf80705201914m2443aa7atfe4d5250bfd0d164@mail.gmail.com> <46514520.2040907@canterbury.ac.nz> Message-ID: On 5/21/07, Steven Bethard wrote: > def update(self, container=None, **kwargs) > Note that I shouldn't want to write '__container' because it's not an > implementation detail. Yes, it is. The fact that there *is* a parameter there isn't an implementation detail, but the *choice of name* for that parameter is explicitly an implementation detail -- if it weren't, then you wouldn't need to insist on positional-only calling. -jJ From jimjjewett at gmail.com Tue May 22 00:57:24 2007 From: jimjjewett at gmail.com (Jim Jewett) Date: Mon, 21 May 2007 18:57:24 -0400 Subject: [Python-ideas] Positional only arguments In-Reply-To: <4651D464.2020806@ronadam.com> References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> <91ad5bf80705201711l4debd819ybde15aaf38a94045@mail.gmail.com> <91ad5bf80705201914m2443aa7atfe4d5250bfd0d164@mail.gmail.com> <4651D464.2020806@ronadam.com> Message-ID: > What I would like is for unpack to be '^' instead of '*', then you would > have... My first reaction was negative -- but then I remembered that I was caught by this trap myself more than once, because of the asymmetry between pack and unpack, with * magically doing the normally-right thing. So now I wonder if I wouldn't like if after all, and I'm instead picking at the presentation, so you can make a stronger case. On 5/21/07, Ron Adam wrote: > Now if we use ^ for unpacking, and * for packing, it reduces the number of > meanings for the '*' and fixes the context of positional and keyword only > arguments. > def f(a, ^(b=2, c=3), *rest): b and c are positional only here. I don't think there should ever be positional-only arguments *after* a keywordable argument. Perhaps # a is a mandatory positional argument # b is an optional positional argument # c can be passed as a keyword, or as the third positional argument def f(^a, ^b=2, c=3, *rest): Or were you suggesting a tuple of the positional-only arguments, like # a is a mandatory positional argument # b is an optional positional argument # c can be passed as a keyword, or as the third positional argument def f(^(a, b=2), c=3, *rest): > There is the possibility of extending this for use in other ways as well. > > xlist = [[1, 2], [3, 4, 5], [6, 7, 8, 9]] > > alist = [^x for x in xlist] > > This would have list "extend" behavior instead of list "append" behavior. So alist == [1, 2, 3, 4, 5, 6, 7, 8, 9]? -jJ From castironpi at comcast.net Tue May 22 00:59:51 2007 From: castironpi at comcast.net (Aaron Brady) Date: Mon, 21 May 2007 17:59:51 -0500 Subject: [Python-ideas] Positional only arguments In-Reply-To: Message-ID: <20070521225954.119641E4005@bag.python.org> > -----Original Message----- > From: python-ideas-bounces at python.org [mailto:python-ideas- > bounces at python.org] On Behalf Of Steven Bethard > Sent: Sunday, May 20, 2007 10:24 AM > > I've also noticed that the current @posonly decorator won't solve the > dict() and dict.update() problem:: > > >>> @posonly(2) > ... def update(self, container=None, **kwargs): > ... print self, container, kwargs > ... > >>> update(self=1, other=2) Question on it, the example. Is this not a feature of all UserDict subclasses? Yet we have that anyway. >>> from UserDict import * >>> class C(UserDict): ... pass ... >>> c= C( a=1, b=2 ) >>> print c {'a': 1, 'b': 2} >>> c.update( self=3 ) Traceback (most recent call last): File "", line 1, in TypeError: update() got multiple values for keyword argument 'self' Where are you -def-ing update? From castironpi at comcast.net Tue May 22 01:02:23 2007 From: castironpi at comcast.net (Aaron Brady) Date: Mon, 21 May 2007 18:02:23 -0500 Subject: [Python-ideas] Positional only arguments In-Reply-To: Message-ID: <20070521230228.662421E400C@bag.python.org> > -----Original Message----- > From: python-ideas-bounces at python.org [mailto:python-ideas- > bounces at python.org] On Behalf Of Steven Bethard > Sent: Monday, May 21, 2007 1:59 AM > > I don't follow this logic. How is a positional-only argument more > implicit? You still have to supply it on every function call. It's > not like you can omit it. Not sure about it. If it's required, there is already support for it. Only omit the default value. > Particularly since user mappings are relatively common, I do think > this issue deserves at least a decorator. +1 From steven.bethard at gmail.com Tue May 22 01:07:06 2007 From: steven.bethard at gmail.com (Steven Bethard) Date: Mon, 21 May 2007 17:07:06 -0600 Subject: [Python-ideas] Positional only arguments In-Reply-To: <4652246a.047611f9.32bc.ffffd14dSMTPIN_ADDED@mx.google.com> References: <4652246a.047611f9.32bc.ffffd14dSMTPIN_ADDED@mx.google.com> Message-ID: On 5/21/07, Aaron Brady wrote: > Question on it, the example. Is this not a feature of all UserDict > subclasses? Yet we have that anyway. > > >>> from UserDict import * > >>> class C(UserDict): > ... pass > ... > >>> c= C( a=1, b=2 ) > >>> print c > {'a': 1, 'b': 2} > >>> c.update( self=3 ) > Traceback (most recent call last): > File "", line 1, in > TypeError: update() got multiple values for keyword argument 'self' Yes, it's a bug still present in UserDict. Using the @positional_only decorator I posted in a separate thread, we can make it work correctly:: >>> class C(object): ... @positional_only ... def __init__(self, container=None, _kwargs=None): ... print container, _kwargs ... >>> C(self=1, container=2) None {'self': 1, 'container': 2} STeVe -- I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a tiny blip on the distant coast of sanity. --- Bucky Katt, Get Fuzzy From castironpi at comcast.net Tue May 22 01:03:25 2007 From: castironpi at comcast.net (Aaron Brady) Date: Mon, 21 May 2007 18:03:25 -0500 Subject: [Python-ideas] Positional only arguments In-Reply-To: <4651D464.2020806@ronadam.com> Message-ID: <20070521230834.701B11E4006@bag.python.org> > -----Original Message----- > From: python-ideas-bounces at python.org [mailto:python-ideas- > bounces at python.org] On Behalf Of Ron Adam > > If '^' is used outside of function defs like the '*', it can retain it's > meaning. > > a, b, *c = 1, 2, 3, 4, 5 # pack remainder > > z = (x, y, z) > a, b, c, d = (a, ^z) # unpack z Don't forget. Any the things you want can be composed in hand. > >>> def f(*, a, b=None, *args, **, c=42, **kwargs) def f( *args, **kwargs ): if len( args ) < 2: raise error if 'b' in kwargs: raise error if 'c' not in kwargs: raise error a, b, args = args[:2], args[2:] c = kwargs['c'] It's an approximation; use case to the contrary? From rhamph at gmail.com Tue May 22 03:52:46 2007 From: rhamph at gmail.com (Adam Olsen) Date: Mon, 21 May 2007 19:52:46 -0600 Subject: [Python-ideas] Positional only arguments In-Reply-To: References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> <91ad5bf80705201711l4debd819ybde15aaf38a94045@mail.gmail.com> <91ad5bf80705201914m2443aa7atfe4d5250bfd0d164@mail.gmail.com> Message-ID: On 5/21/07, Steven Bethard wrote: > Just for reference, here are the current motivating use cases: > > * User mapping types that need to match the dict() and dict.update() > method signatures I wasn't aware the proposals given would meet this use case! PEP 3102 has no effect on correct code, instead it just adds some error detection for incorrect code. In contrast, the dict()/dict.update() signature use case needs semantics to change for an example like this: def x((a=None), **kwargs): ... x(a=3) This can't be wrapped properly without very special care. For instance, this would behave wrong: def method(self, *args, **kwargs): x(*args, **kwargs) I'm strongly against adding a feature to split **kwargs into a separate namespace when we have such a common convention of NOT doing it for self[1][2]. The decorator proposed in the other thread is a much better solution unless we want to overturn that convention. [1] Google codesearch for "self[^()]*\*\* lang:python" returned 28,800 results.. make that 200 results.. or 186 results.. numbers aren't too accurate it seems. [2] "\([a-z][^()]*\*\* lang:python" claims 29,500, but won't let me go past 200 results. Maybe there's an internal limiter? -- Adam Olsen, aka Rhamphoryncus From rrr at ronadam.com Tue May 22 04:05:17 2007 From: rrr at ronadam.com (Ron Adam) Date: Mon, 21 May 2007 21:05:17 -0500 Subject: [Python-ideas] Positional only arguments In-Reply-To: References: <91ad5bf80705160750u712fbc88o3a5379db5ddeda15@mail.gmail.com> <91ad5bf80705201711l4debd819ybde15aaf38a94045@mail.gmail.com> <91ad5bf80705201914m2443aa7atfe4d5250bfd0d164@mail.gmail.com> <4651D464.2020806@ronadam.com> Message-ID: <46524FDD.4090007@ronadam.com> Jim Jewett wrote: >> What I would like is for unpack to be '^' instead of '*', then you would >> have... > > My first reaction was negative -- but then I remembered that I was > caught by this trap myself more than once, because of the asymmetry > between pack and unpack, with * magically doing the normally-right > thing. > > So now I wonder if I wouldn't like if after all, and I'm instead > picking at the presentation, so you can make a stronger case. Yes, it's gotten me a few times as well. Usually when I have a class and some of the methods are accepting *args, **kwds, and some aren't. Then I find I'm packing arguments in some cases and unpacking them in others in the same subclass, and the methods definitions are not on the same page so it isn't immediately obvious I got them mixed up. As I said it isn't a computer issue, it's a human interface issue. > On 5/21/07, Ron Adam wrote: > >> Now if we use ^ for unpacking, and * for packing, it reduces the >> number of >> meanings for the '*' and fixes the context of positional and keyword only >> arguments. > >> def f(a, ^(b=2, c=3), *rest): b and c are positional only here. > > I don't think there should ever be positional-only arguments *after* a > keywordable argument. Perhaps > > # a is a mandatory positional argument > # b is an optional positional argument > # c can be passed as a keyword, or as the third positional argument > def f(^a, ^b=2, c=3, *rest): > > Or were you suggesting a tuple of the positional-only arguments, like > > # a is a mandatory positional argument > # b is an optional positional argument > # c can be passed as a keyword, or as the third positional argument > def f(^(a, b=2), c=3, *rest): Ah, ok, I see what I missed. I think I got optional args mixed up with positional args in my mind. Not quite the same thing. So yes, the second example fits what I was trying to think of better. # a is mandatory, positional # b is optional, positional # c is optional, positional, or by keyword # d is mandatory, keyword only # e is optional, keyword only def f(^(a, b=2), c=3, ^^(d, e=5)): Of course it could be interpreted a bit differently given the unpacking context. # x is a two tuple (a, b) # y is a single value, c # z is a dict, {'d':4, 'e':5} result = f(x, y, z) Which solves a different problem entirely. ;-) It allows you to specify unpacking behavior in the definition instead of requiring it on the calling side. So I guess I'd have to fall back to the semi-colon as the positional only and keyword only designators. def f(a, b=2; c=3; d, e=5): Or alternately use the colon as it is used in slices. def f(a, b=2: c=3: d, e=5): I'd almost rather change the slices to semicolons and keep the colon unique and with only one purpose. And ... def f(a, b=2, c=3) would be equivalent to... def f(; a, b=2, c=3;): No positional only, no keyword only Anyway, I'm not sure there is a simple way to do this. Sigh... >> There is the possibility of extending this for use in other ways as well. >> >> xlist = [[1, 2], [3, 4, 5], [6, 7, 8, 9]] >> >> alist = [^x for x in xlist] >> >> This would have list "extend" behavior instead of list "append" behavior. > > So alist == [1, 2, 3, 4, 5, 6, 7, 8, 9]? Exactly. Cheers, Ron From castironpi at comcast.net Tue May 22 11:45:01 2007 From: castironpi at comcast.net (Aaron Brady) Date: Tue, 22 May 2007 04:45:01 -0500 Subject: [Python-ideas] Positional only arguments In-Reply-To: <46524FDD.4090007@ronadam.com> Message-ID: <20070522094505.5714D1E4003@bag.python.org> > -----Original Message----- > From: python-ideas-bounces at python.org [mailto:python-ideas- > bounces at python.org] On Behalf Of Ron Adam > > def f(; a, b=2, c=3;): No positional only, no keyword only Do you prohibit defaults in type 1, the pos-only? Not necc. Does this look right? >>> def f( a=0; b=1 ): ... print a, b >>> f() 0, 1 Also, does this look right? >>> def f( a=0; b ): ... print a, b File "", line 1 SyntaxError: non-default argument follows default argument Any more groups? So far I have pos-only, pos-or-kw, and kw-only. If not, a ascii character works fine to delimit, like * and **. Do we want to annotate each parameter individually? This could get out of hand. But decorators won't let you do @f( k ) def j( k ): ... where @f( 'k' ) def j( k ): ... gets unwieldy and could show promise. Cf. Steven's positional only arguments decorator. From castironpi at comcast.net Tue May 22 12:03:54 2007 From: castironpi at comcast.net (Aaron Brady) Date: Tue, 22 May 2007 05:03:54 -0500 Subject: [Python-ideas] Positional only arguments In-Reply-To: <20070522094505.5714D1E4003@bag.python.org> Message-ID: <20070522100358.208671E4003@bag.python.org> > -----Original Message----- > From: python-ideas-bounces at python.org [mailto:python-ideas- > bounces at python.org] On Behalf Of Aaron Brady > Sent: Tuesday, May 22, 2007 4:45 AM > > -----Original Message----- > > From: python-ideas-bounces at python.org [mailto:python-ideas- > > bounces at python.org] On Behalf Of Ron Adam > > > > def f(; a, b=2, c=3;): No positional only, no keyword only > > @f( 'k' ) > def j( k ): > ... > > gets unwieldy and could show promise. Cf. Steven's positional only > arguments decorator. Cf. PEP 3102 Talin http://www.python.org/dev/peps/pep-3102/ Cf. PEP 3107 Winder and Lownds http://www.python.org/dev/peps/pep-3107/ Cf. PEP 3117 Brandl http://www.python.org/dev/peps/pep-3117/ def f( @k, @j ) Half-way compromise to Brandl, only in declaration not in use, and always optional. From castironpi at comcast.net Tue May 22 12:00:47 2007 From: castironpi at comcast.net (Aaron Brady) Date: Tue, 22 May 2007 05:00:47 -0500 Subject: [Python-ideas] crazy ideas Message-ID: <20070522101758.6789C1E4005@bag.python.org> Annotated list callers: q = d[a,b,c] is deque simple sugar for from collections import deque q = deque( a, b, c ) might also do s = s[a,b,c] for s = set([a,b,c]) From adam at atlas.st Tue May 22 14:45:28 2007 From: adam at atlas.st (Adam Atlas) Date: Tue, 22 May 2007 08:45:28 -0400 Subject: [Python-ideas] crazy ideas In-Reply-To: <20070522101758.6789C1E4005@bag.python.org> References: <20070522101758.6789C1E4005@bag.python.org> Message-ID: On 22 May 2007, at 06.00, Aaron Brady wrote: > Annotated list callers: > > q = d[a,b,c] is deque Won't work... how could that be distinguished from getting an item of a dictionary named `d` keyed by the tuple (a, b, c)? From castironpi at comcast.net Tue May 22 14:55:57 2007 From: castironpi at comcast.net (Aaron Brady) Date: Tue, 22 May 2007 07:55:57 -0500 Subject: [Python-ideas] crazy ideas In-Reply-To: Message-ID: <20070522125602.23D761E400B@bag.python.org> > -----Original Message----- > From: python-ideas-bounces at python.org [mailto:python-ideas- > bounces at python.org] On Behalf Of Adam Atlas > > On 22 May 2007, at 06.00, Aaron Brady wrote: > > Annotated list callers: > > > > q = d[a,b,c] is deque > > Won't work... how could that be distinguished from getting an item of > a dictionary named `d` keyed by the tuple (a, b, c)? Doh. In syntax design, the grouping characters go pretty quickly. d is -almost- ambiguous[1], perhaps that? [1] ...with (de) ae but isn't. From grosser.meister.morti at gmx.net Tue May 22 16:16:51 2007 From: grosser.meister.morti at gmx.net (=?ISO-8859-1?Q?Mathias_Panzenb=F6ck?=) Date: Tue, 22 May 2007 16:16:51 +0200 Subject: [Python-ideas] crazy ideas In-Reply-To: <20070522125602.23D761E400B@bag.python.org> References: <20070522125602.23D761E400B@bag.python.org> Message-ID: <4652FB53.1030408@gmx.net> maybe d{a,b,c}? whatever, I think in python3 there will be {a,b,c} as short syntax for set([a,b,c]). From g.brandl at gmx.net Tue May 22 17:04:18 2007 From: g.brandl at gmx.net (Georg Brandl) Date: Tue, 22 May 2007 17:04:18 +0200 Subject: [Python-ideas] Positional only arguments In-Reply-To: <20070522100358.208671E4003@bag.python.org> References: <20070522094505.5714D1E4003@bag.python.org> <20070522100358.208671E4003@bag.python.org> Message-ID: Aaron Brady schrieb: >> -----Original Message----- >> From: python-ideas-bounces at python.org [mailto:python-ideas- >> bounces at python.org] On Behalf Of Aaron Brady >> Sent: Tuesday, May 22, 2007 4:45 AM >> > -----Original Message----- >> > From: python-ideas-bounces at python.org [mailto:python-ideas- >> > bounces at python.org] On Behalf Of Ron Adam >> > >> > def f(; a, b=2, c=3;): No positional only, no keyword only >> >> @f( 'k' ) >> def j( k ): >> ... >> >> gets unwieldy and could show promise. Cf. Steven's positional only >> arguments decorator. > > Cf. PEP 3102 Talin http://www.python.org/dev/peps/pep-3102/ > Cf. PEP 3107 Winder and Lownds http://www.python.org/dev/peps/pep-3107/ > Cf. PEP 3117 Brandl http://www.python.org/dev/peps/pep-3117/ > > def f( @k, @j ) > > Half-way compromise to Brandl, only in declaration not in use, and always > optional. I'd prefer no compromises being made when it comes to PEP 3117. Georg From g.brandl at gmx.net Tue May 22 17:05:49 2007 From: g.brandl at gmx.net (Georg Brandl) Date: Tue, 22 May 2007 17:05:49 +0200 Subject: [Python-ideas] crazy ideas In-Reply-To: <20070522101758.6789C1E4005@bag.python.org> References: <20070522101758.6789C1E4005@bag.python.org> Message-ID: Aaron Brady schrieb: > Annotated list callers: > > q = d[a,b,c] is deque > > simple sugar for > > from collections import deque > q = deque( a, b, c ) > > > might also do > > s = s[a,b,c] > > for > > s = set([a,b,c]) Would you be happy with {a, b, c}? Georg From rrr at ronadam.com Tue May 22 19:20:46 2007 From: rrr at ronadam.com (Ron Adam) Date: Tue, 22 May 2007 12:20:46 -0500 Subject: [Python-ideas] Positional only arguments In-Reply-To: <200705220243203.SM01928@sccrmhc13.comcast.net> References: <200705220243203.SM01928@sccrmhc13.comcast.net> Message-ID: <4653266E.7060706@ronadam.com> Aaron Brady wrote: >> -----Original Message----- >> From: python-ideas-bounces at python.org [mailto:python-ideas- >> bounces at python.org] On Behalf Of Ron Adam >> >> def f(; a, b=2, c=3;): No positional only, no keyword only > > Do you prohibit defaults in type 1, the pos-only? No > Not necc. Does this look right? > >>>> def f( a=0; b=1 ): > ... print a, b >>>> f() > 0, 1 That's fine. 'a' is positional only and 'b' is either. Having defaults and being positional only are two different things. With the above function the following would be allowed. f() f(1) f(1, 2) f(1, b=2) f(b=2) But not: (If positional only also means no assignment with keywords at call time.) f(a=1) # Keyword not allowed for 'a' at call time. f(b=2, a=1) # 'a' is positional only > Also, does this look right? > >>>> def f( a=0; b ): > ... print a, b > File "", line 1 > SyntaxError: non-default argument follows default argument Looks ok to me. Even the error is correct. > Any more groups? So far I have pos-only, pos-or-kw, and kw-only. > > If not, a ascii character works fine to delimit, like * and **. Any character can possibly do it, but does it make sense given that they already have a meaning? I have a feeling we are trying to do too much at once. required optional with default with out default in order in order only with keyword with keyword only Can these be ordered into *any* decision tree that makes sense? > Do we want to annotate each parameter individually? This could get out of > hand. But decorators won't let you do > > @f( k ) > def j( k ): > ... > > where > > @f( 'k' ) > def j( k ): > ... > > gets unwieldy and could show promise. Cf. Steven's positional only > arguments decorator. I think we should let Steven's decorator be developed further. It will at least give a way to test ideas and find more use cases. Then if there are some frequent and common use cases. Then look at what is actually needed. Cheers, Ron From castironpi at comcast.net Tue May 22 20:24:28 2007 From: castironpi at comcast.net (Aaron Brady) Date: Tue, 22 May 2007 13:24:28 -0500 Subject: [Python-ideas] crazy ideas In-Reply-To: Message-ID: <20070522182432.6032C1E4012@bag.python.org> > -----Original Message----- > From: python-ideas-bounces at python.org [mailto:python-ideas- > bounces at python.org] On Behalf Of Georg Brandl > > Aaron Brady schrieb: > > Annotated list callers: > > > > q = d[a,b,c] is deque > > > > simple sugar for > > > > from collections import deque > > q = deque( a, b, c ) > > > > > > might also do > > > > s = s[a,b,c] > > > > for > > > > s = set([a,b,c]) > > Would you be happy with {a, b, c}? > > Georg > Yes, impartiality being hard to come by. Is it a deque or a set? d{a,b,c} could allow you flexibility. Don't generalize too -far-, though. This could be used anywhere, akin to r"a\bc", but don't allow users to 'cook their own'. Plenty of room but needs say so with official support. Queue.Queue, Collections.Deque, Collections.DefaultDict, set, UserGeom.Point?[1], that's all I can think of. [1] r{ p{0,0}, p{10,10} } FTR for the record, how often it's used today doesn't tell how often it will be used with convenienter syntax, impartiality still being hard to come by. From scott+python-ideas at scottdial.com Tue May 22 20:26:22 2007 From: scott+python-ideas at scottdial.com (Scott Dial) Date: Tue, 22 May 2007 14:26:22 -0400 Subject: [Python-ideas] Positional only arguments In-Reply-To: <20070521230834.701B11E4006@bag.python.org> References: <20070521230834.701B11E4006@bag.python.org> Message-ID: <465335CE.5060807@scottdial.com> Aaron Brady wrote: >>>>> def f(*, a, b=None, *args, **, c=42, **kwargs) > > def f( *args, **kwargs ): > if len( args ) < 2: raise error > if 'b' in kwargs: raise error > if 'c' not in kwargs: raise error > a, b, args = args[:2], args[2:] > c = kwargs['c'] > > It's an approximation; use case to the contrary? > I'm not sure why else you would post this reply other than a lack of understanding. The whole point of this discussion is to avoid burying this information inside the function body and have a complete function signature. f(*args, **kwargs) is the least useful function signature possible in python. -- Scott Dial scott at scottdial.com scodial at cs.indiana.edu From castironpi at comcast.net Tue May 22 20:42:34 2007 From: castironpi at comcast.net (Aaron Brady) Date: Tue, 22 May 2007 13:42:34 -0500 Subject: [Python-ideas] Positional only arguments In-Reply-To: <465335CE.5060807@scottdial.com> Message-ID: <20070522184238.6E1521E401D@bag.python.org> > -----Original Message----- > From: Scott Dial [mailto:scott+python-ideas at scottdial.com] > Sent: Tuesday, May 22, 2007 1:26 PM > > Aaron Brady wrote: > >>>>> def f(*, a, b=None, *args, **, c=42, **kwargs) > > > > def f( *args, **kwargs ): > > if len( args ) < 2: raise error > > if 'b' in kwargs: raise error > > if 'c' not in kwargs: raise error > > a, b, args = args[:2], args[2:] > > c = kwargs['c'] > > > > It's an approximation; use case to the contrary? > > > > I'm not sure why else you would post this reply other than a lack of > understanding. The whole point of this discussion is to avoid burying > this information inside the function body and have a complete function > signature. f(*args, **kwargs) is the least useful function signature > possible in python. > > -- > Scott Dial > scott at scottdial.com > scodial at cs.indiana.edu You all seemed to me to be wanting things to apply in every case. This does, but you scream at me here too. Generality or speciality, take your pick. I would say perl is highly specialized, very useful, more than python for a certain subset of tasks. What subset? Are you here for popularity, money, productivity, aesthetics, deep aesthetics, raw lines of code per day per time zone around the world, or none of the above? 'Cause ML is a beautiful idea; doesn't take a grad student to appreciate that. Just to keep your job is money. Love it. From jcarlson at uci.edu Tue May 22 21:33:45 2007 From: jcarlson at uci.edu (Josiah Carlson) Date: Tue, 22 May 2007 12:33:45 -0700 Subject: [Python-ideas] crazy ideas In-Reply-To: <20070522182432.6032C1E4012@bag.python.org> References: <20070522182432.6032C1E4012@bag.python.org> Message-ID: <20070522122942.85E1.JCARLSON@uci.edu> "Aaron Brady" wrote: > > > s = s[a,b,c] > > > > > > for > > > > > > s = set([a,b,c]) > > > > Would you be happy with {a, b, c}? > > > Yes, impartiality being hard to come by. > > Is it a deque or a set? d{a,b,c} could allow you flexibility. It's the set syntax for Python 3.0. Getting deque syntax, or a prefix for arbitrary types that are rarely used is not going to happen. There was already huge resistance to the set syntax, and those are used easily 10 times more than deques. In terms of having a syntax for deques, I honestly don't see the problem with deque([a,b,c]). It has all of 6 more characters to type than your proposed d{a,b,c} syntax, without cluttering up the language with yet another bit of syntax that can be replaced with a 2 line function... def d(*args): return deque(args) Repeat this to yourself until you realize that it's the only sane approach to Python language design: not every X line function should be made into a builtin or syntax. - Josiah From castironpi at comcast.net Tue May 22 21:42:01 2007 From: castironpi at comcast.net (Aaron Brady) Date: Tue, 22 May 2007 14:42:01 -0500 Subject: [Python-ideas] crazy ideas In-Reply-To: <20070522122942.85E1.JCARLSON@uci.edu> Message-ID: <20070522194208.4368B1E4009@bag.python.org> > -----Original Message----- > From: Josiah Carlson [mailto:jcarlson at uci.edu] > Sent: Tuesday, May 22, 2007 2:34 PM > > "Aaron Brady" wrote: > > Is it a deque or a set? d{a,b,c} could allow you flexibility. > > Repeat this to yourself until you realize that it's the only sane > approach to Python language design: not every X line function should be > made into a builtin or syntax. > Duh, so why don't we pick out some choice N-line functions? And make those syntax. Let me know if this gets "too heated" for n/g postings, and I'll take it outside[1]. We tend to have loves; we know not what. [1]Future topics include the evolution of English from Proto-Indoeuropean, past Latin, why English is good, and hence why Python should take out some good reservations, and be like English. It's a language that gets -used-. Regular yet idiomatic, like Python could be. Dream where? Lifespan of languages is looking at a couple to few decades- not ten minutes, nor ten centuries. Let's look at leadership. You want to talk precedent? From ian.bollinger at gmail.com Tue May 22 21:44:36 2007 From: ian.bollinger at gmail.com (Ian D. Bollinger) Date: Tue, 22 May 2007 15:44:36 -0400 Subject: [Python-ideas] Have list/deque grow a copy() method In-Reply-To: <20070515140958.8578.JCARLSON@uci.edu> References: <20070515134716.8575.JCARLSON@uci.edu> <20070515140958.8578.JCARLSON@uci.edu> Message-ID: <46534824.6050700@gmail.com> Josiah Carlson wrote: > I choose as standard what works in the most cases. Since list() works > everywhere, using it on lists makes the most sense to me. > > Good point. Would it be worth specifying this in the official style guide? From ian.bollinger at gmail.com Tue May 22 21:53:37 2007 From: ian.bollinger at gmail.com (Ian D. Bollinger) Date: Tue, 22 May 2007 15:53:37 -0400 Subject: [Python-ideas] crazy ideas In-Reply-To: <20070522122942.85E1.JCARLSON@uci.edu> References: <20070522182432.6032C1E4012@bag.python.org> <20070522122942.85E1.JCARLSON@uci.edu> Message-ID: <46534A41.2010609@gmail.com> Josiah Carlson wrote: > In terms of having a syntax for deques, I honestly don't see the problem > with deque([a,b,c]). It has all of 6 more characters to type than your > proposed d{a,b,c} syntax, without cluttering up the language with yet > another bit of syntax that can be replaced with a 2 line function... > > def d(*args): > return deque(args) > But what about all the memory overhead of constructing the list argument?! (I turn off my car radio to save gas.) - Ian D. Bollinger From castironpi at comcast.net Tue May 22 21:58:29 2007 From: castironpi at comcast.net (Aaron Brady) Date: Tue, 22 May 2007 14:58:29 -0500 Subject: [Python-ideas] crazy ideas In-Reply-To: <46534A41.2010609@gmail.com> Message-ID: <20070522195834.2E59D1E4003@bag.python.org> > -----Original Message----- > From: Ian D. Bollinger [mailto:ian.bollinger at gmail.com] > Sent: Tuesday, May 22, 2007 2:54 PM > > Josiah Carlson wrote: > > In terms of having a syntax for deques, I honestly don't see the problem > > with deque([a,b,c]). It has all of 6 more characters to type than your > > proposed d{a,b,c} syntax, without cluttering up the language with yet > > another bit of syntax that can be replaced with a 2 line function... > > > > def d(*args): > > return deque(args) > > > But what about all the memory overhead of constructing the list argument?! > (I turn off my car radio to save gas.) I take the bowling ball out of my trunk. From ntoronto at cs.byu.edu Tue May 22 22:09:40 2007 From: ntoronto at cs.byu.edu (Neil Toronto) Date: Tue, 22 May 2007 14:09:40 -0600 Subject: [Python-ideas] crazy ideas In-Reply-To: <20070522195834.2E59D1E4003@bag.python.org> References: <20070522195834.2E59D1E4003@bag.python.org> Message-ID: <46534E04.6000003@cs.byu.edu> Aaron Brady wrote: >> -----Original Message----- >> From: Ian D. Bollinger [mailto:ian.bollinger at gmail.com] >> Sent: Tuesday, May 22, 2007 2:54 PM >> >> Josiah Carlson wrote: >> >>> In terms of having a syntax for deques, I honestly don't see the problem >>> with deque([a,b,c]). It has all of 6 more characters to type than your >>> proposed d{a,b,c} syntax, without cluttering up the language with yet >>> another bit of syntax that can be replaced with a 2 line function... >>> >>> def d(*args): >>> return deque(args) >>> >>> >> But what about all the memory overhead of constructing the list argument?! >> (I turn off my car radio to save gas.) >> > > I take the bowling ball out of my trunk. > I dust the dashboard. Neil From castironpi at comcast.net Tue May 22 22:14:42 2007 From: castironpi at comcast.net (Aaron Brady) Date: Tue, 22 May 2007 15:14:42 -0500 Subject: [Python-ideas] crazy ideas In-Reply-To: <46534E04.6000003@cs.byu.edu> Message-ID: <20070522201447.63CB81E4003@bag.python.org> > -----Original Message----- > From: python-ideas-bounces at python.org [mailto:python-ideas- > bounces at python.org] On Behalf Of Neil Toronto > Sent: Tuesday, May 22, 2007 3:10 PM > Cc: python-ideas at python.org > Subject: Re: [Python-ideas] crazy ideas > > Aaron Brady wrote: > >> -----Original Message----- > >> From: Ian D. Bollinger [mailto:ian.bollinger at gmail.com] > >> Sent: Tuesday, May 22, 2007 2:54 PM > >> > >> Josiah Carlson wrote: > >> > >>> In terms of having a syntax for deques, I honestly don't see the > problem > >>> with deque([a,b,c]). It has all of 6 more characters to type than > your > >>> proposed d{a,b,c} syntax, without cluttering up the language with yet > >>> another bit of syntax that can be replaced with a 2 line function... > >>> > >>> def d(*args): > >>> return deque(args) > >>> > >>> > >> But what about all the memory overhead of constructing the list > argument?! > >> (I turn off my car radio to save gas.) > >> > > > > I take the bowling ball out of my trunk. > > > > I dust the dashboard. > > Neil Radio's sounding good. It's the crap vs. worse crap finals. From jcarlson at uci.edu Tue May 22 23:29:51 2007 From: jcarlson at uci.edu (Josiah Carlson) Date: Tue, 22 May 2007 14:29:51 -0700 Subject: [Python-ideas] crazy ideas In-Reply-To: <46534A41.2010609@gmail.com> References: <20070522122942.85E1.JCARLSON@uci.edu> <46534A41.2010609@gmail.com> Message-ID: <20070522142355.85E7.JCARLSON@uci.edu> "Ian D. Bollinger" wrote: > > Josiah Carlson wrote: > > In terms of having a syntax for deques, I honestly don't see the problem > > with deque([a,b,c]). It has all of 6 more characters to type than your > > proposed d{a,b,c} syntax, without cluttering up the language with yet > > another bit of syntax that can be replaced with a 2 line function... > > > > def d(*args): > > return deque(args) > > > But what about all the memory overhead of constructing the list argument?! > (I turn off my car radio to save gas.) Even with syntax, the content of the deque needs to be loaded on the stack for either a 'stack to deque' operation (like the equivalent stack to list or stack to tuple operations), or a stack to list to deque operation. And unless you are creating huge deques in-line, starting from a list won't incur any significant memory overhead as short lists (0, 4, 8, 16, etc.) are usually handled by Python's small memory allocator. If you really want to prove it to yourself that it doesn't matter, try benchmarking the difference between... d = deque(()) d = deque([]) d = deque((1,2,3,4,5,6,7,8,9,10)) d = deque([1,2,3,4,5,6,7,8,9,10]) - Josiah From jcarlson at uci.edu Tue May 22 23:31:35 2007 From: jcarlson at uci.edu (Josiah Carlson) Date: Tue, 22 May 2007 14:31:35 -0700 Subject: [Python-ideas] Have list/deque grow a copy() method In-Reply-To: <46534824.6050700@gmail.com> References: <20070515140958.8578.JCARLSON@uci.edu> <46534824.6050700@gmail.com> Message-ID: <20070522143009.85EA.JCARLSON@uci.edu> "Ian D. Bollinger" wrote: > Josiah Carlson wrote: > > I choose as standard what works in the most cases. Since list() works > > everywhere, using it on lists makes the most sense to me. > > > > > Good point. Would it be worth specifying this in the official style guide? I think that would be more hand-holding than we really want to be doing. - Josiah From ian.bollinger at gmail.com Tue May 22 23:38:16 2007 From: ian.bollinger at gmail.com (Ian D. Bollinger) Date: Tue, 22 May 2007 17:38:16 -0400 Subject: [Python-ideas] crazy ideas In-Reply-To: <20070522142355.85E7.JCARLSON@uci.edu> References: <20070522122942.85E1.JCARLSON@uci.edu> <46534A41.2010609@gmail.com> <20070522142355.85E7.JCARLSON@uci.edu> Message-ID: <465362C8.1080701@gmail.com> Josiah Carlson wrote: > "Ian D. Bollinger" wrote: > >> But what about all the memory overhead of constructing the list argument?! >> (I turn off my car radio to save gas.) >> > > Even with syntax, the content of the deque needs to be loaded on the > stack for either a 'stack to deque' operation (like the equivalent stack > to list or stack to tuple operations), or a stack to list to deque > operation. And unless you are creating huge deques in-line, starting > from a list won't incur any significant memory overhead as short lists > (0, 4, 8, 16, etc.) are usually handled by Python's small memory > allocator. > > If you really want to prove it to yourself that it doesn't matter, try > benchmarking the difference between... > > d = deque(()) > d = deque([]) > > d = deque((1,2,3,4,5,6,7,8,9,10)) > d = deque([1,2,3,4,5,6,7,8,9,10]) > > Er, I was trying to be ironic, hence the comment about gas mileage. :( - Ian D. Bollinger From arno at marooned.org.uk Tue May 22 20:16:31 2007 From: arno at marooned.org.uk (Arnaud Delobelle) Date: Tue, 22 May 2007 19:16:31 +0100 Subject: [Python-ideas] Positional only arguments In-Reply-To: <4653266E.7060706@ronadam.com> References: <200705220243203.SM01928@sccrmhc13.comcast.net> <4653266E.7060706@ronadam.com> Message-ID: <3675F215-BC6E-49DD-86F0-D83CE2814305@marooned.org.uk> On 22 May 2007, at 18:20, Ron Adam wrote: > Aaron Brady wrote: [...] >> gets unwieldy and could show promise. Cf. Steven's positional only >> arguments decorator. > > I think we should let Steven's decorator be developed further. [...] No really that's too much: I don't deserve the credit. I only came up with the idea of the decorator (with an implementation) and provided a solution to the problem of keyword arguments with the same name as positional ones. So don't mention me :) -- Arnaud From rrr at ronadam.com Wed May 23 04:52:01 2007 From: rrr at ronadam.com (Ron Adam) Date: Tue, 22 May 2007 21:52:01 -0500 Subject: [Python-ideas] Positional only arguments In-Reply-To: <3675F215-BC6E-49DD-86F0-D83CE2814305@marooned.org.uk> References: <200705220243203.SM01928@sccrmhc13.comcast.net> <4653266E.7060706@ronadam.com> <3675F215-BC6E-49DD-86F0-D83CE2814305@marooned.org.uk> Message-ID: <4653AC51.1080103@ronadam.com> Arnaud Delobelle wrote: > On 22 May 2007, at 18:20, Ron Adam wrote: > >> Aaron Brady wrote: > [...] >>> gets unwieldy and could show promise. Cf. Steven's positional only >>> arguments decorator. >> I think we should let Steven's decorator be developed further. > [...] > > No really that's too much: I don't deserve the credit. I only came up > with the idea of the decorator (with an implementation) and provided > a solution to the problem of keyword arguments with the same name as > positional ones. So don't mention me :) Correction: """I think we should let Arnaud Delobelle's decorator be developed further.""" Sorry about that, please don't let my mistake stop you from coming up with more good ideas. Sincere apologies, Ron From castironpi at comcast.net Wed May 23 17:04:23 2007 From: castironpi at comcast.net (Aaron Brady) Date: Wed, 23 May 2007 10:04:23 -0500 Subject: [Python-ideas] crazy ideas In-Reply-To: <465362C8.1080701@gmail.com> Message-ID: <20070523150430.384E11E4003@bag.python.org> > -----Original Message----- > From: python-ideas-bounces at python.org [mailto:python-ideas- > bounces at python.org] On Behalf Of Ian D. Bollinger > Sent: Tuesday, May 22, 2007 4:38 PM > > Josiah Carlson wrote: > > "Ian D. Bollinger" wrote: > > > >> But what about all the memory overhead of constructing the list > argument?! > >> (I turn off my car radio to save gas.) > >> > > If you really want to prove it to yourself that it doesn't matter, try > > benchmarking the difference between... > > > > d = deque(()) > > d = deque([]) > > > > d = deque((1,2,3,4,5,6,7,8,9,10)) > > d = deque([1,2,3,4,5,6,7,8,9,10]) > > > > > Er, I was trying to be ironic, hence the comment about gas mileage. :( > > - Ian D. Bollinger Point very well taken. Gas mileage extrapolates to two things here. Running time and coding-time[1] "miles" per backend dev-time and clutter-time. Even if it's free, it's still free clutter. Guido's demonstrating efficiency pretty advisedly. [1] How expensive is it, per instance and in total, to write deque([a,b,c]) instead of d? From castironpi at comcast.net Wed May 23 17:08:48 2007 From: castironpi at comcast.net (Aaron Brady) Date: Wed, 23 May 2007 10:08:48 -0500 Subject: [Python-ideas] Positional only arguments In-Reply-To: <4653AC51.1080103@ronadam.com> Message-ID: <20070523150849.91B371E4003@bag.python.org> > -----Original Message----- > From: python-ideas-bounces at python.org [mailto:python-ideas- > bounces at python.org] On Behalf Of Ron Adam > Sent: Tuesday, May 22, 2007 9:52 PM > > > Correction: > > """I think we should let Arnaud Delobelle's decorator be developed > further.""" > > > Sorry about that, please don't let my mistake stop you from coming up with > more good ideas. > > Sincere apologies, > Ron Something like @restrict( a=PosOnly, b=NameOnly ) def f( a, b='i', c=None ): ... You could reject 3102. From bwinton at latte.ca Wed May 23 17:32:13 2007 From: bwinton at latte.ca (Blake Winton) Date: Wed, 23 May 2007 11:32:13 -0400 Subject: [Python-ideas] crazy ideas In-Reply-To: <20070523150430.384E11E4003@bag.python.org> References: <20070523150430.384E11E4003@bag.python.org> Message-ID: <46545E7D.4090308@latte.ca> Aaron Brady wrote: > [1] How expensive is it, per instance and in total, to write deque([a,b,c]) > instead of d? I'ld be more interested in how expensive it is, per instance and in total, to _read_ deque([a,b,c]) instead of d? Speaking as someone who reads way more code than they write, I find the extra verbosity of "deque" to be quite helpful, and one fewer thing I have to try to remember when reading someone else's code. Later, Blake. From paul.hankin at pobox.com Wed May 23 17:51:20 2007 From: paul.hankin at pobox.com (Paul Hankin) Date: Wed, 23 May 2007 16:51:20 +0100 Subject: [Python-ideas] crazy ideas In-Reply-To: <46545E7D.4090308@latte.ca> References: <20070523150430.384E11E4003@bag.python.org> <46545E7D.4090308@latte.ca> Message-ID: On 23/05/07, Blake Winton wrote: > Aaron Brady wrote: > > [1] How expensive is it, per instance and in total, to write deque([a,b,c]) > > instead of d? > > I'ld be more interested in how expensive it is, per instance and in > total, to _read_ deque([a,b,c]) instead of d? > > Speaking as someone who reads way more code than they write, I find the > extra verbosity of "deque" to be quite helpful, and one fewer thing I > have to try to remember when reading someone else's code. Isn't there a problem with ambiguity? Eg f(d -e) From george.sakkis at gmail.com Wed May 23 17:57:34 2007 From: george.sakkis at gmail.com (George Sakkis) Date: Wed, 23 May 2007 11:57:34 -0400 Subject: [Python-ideas] crazy ideas In-Reply-To: References: <20070523150430.384E11E4003@bag.python.org> <46545E7D.4090308@latte.ca> Message-ID: <91ad5bf80705230857y3fbc8d39t33c507626e3bf5@mail.gmail.com> On 5/23/07, Paul Hankin wrote: > On 23/05/07, Blake Winton wrote: > > Aaron Brady wrote: > > > [1] How expensive is it, per instance and in total, to write deque([a,b,c]) > > > instead of d? > > > > I'ld be more interested in how expensive it is, per instance and in > > total, to _read_ deque([a,b,c]) instead of d? > > > > Speaking as someone who reads way more code than they write, I find the > > extra verbosity of "deque" to be quite helpful, and one fewer thing I > > have to try to remember when reading someone else's code. > > Isn't there a problem with ambiguity? Eg > f(d -e) Can we please let this pointless idea and the respective thread R.I.P. ? -- "If I have been able to see further, it was only because I stood on the shoulders of million monkeys." From collinw at gmail.com Thu May 24 02:27:44 2007 From: collinw at gmail.com (Collin Winter) Date: Wed, 23 May 2007 17:27:44 -0700 Subject: [Python-ideas] [Python-Dev] nodef In-Reply-To: <1b151690705231708v19ab6f5mb647007d6bcd1cea@mail.gmail.com> References: <1b151690705231708v19ab6f5mb647007d6bcd1cea@mail.gmail.com> Message-ID: <43aa6ff70705231727i2b70b9a5hd4800018a23b052b@mail.gmail.com> [moving to python-ideas, where it belongs] On 5/23/07, Martin Blais wrote: > I often have the need for a generic object to use as the default value > for a function parameter, where 'None' is a valid value for the > parameter. For example: > > _sentinel = object() > > def first(iterable, default=_sentinel): > """Return the first element of the iterable, otherwise the default value (if > specified). > """ > for elem in iterable: # thx to rhettinger for optim. > return elem > if default is _sentinel: > raise StopIteration > return default > > Here, 'default' could legally accept None, so I cannot use that as the > default value, nor anything else as far as I'm concerned (I don't know > what lives in the iterable, so why should I make assumptions?). > Sometimes in the past I've create generic objects, declared a class, > e.g.: > > class NoDef: pass > def foo(default=NoDef): > ... > > and lately I've even started using the names of builtin functions (it > bothers me a little bit though, that I do that). > > I think Python needs a builtin for this very purpose. I propose > 'nodef', a unique object whose sole purpose is to serve as a default > value. It should be unique, in the same sense that 'None' is unique. I've run into this situation several times before, and I've never felt that defining my own sentinel was unduly taxing. Having a built-in would only save a single line, the initial "sentinel = object()". Collin Winter From terry at jon.es Thu May 24 02:56:53 2007 From: terry at jon.es (Terry Jones) Date: Thu, 24 May 2007 02:56:53 +0200 Subject: [Python-ideas] [Python-Dev] nodef In-Reply-To: Your message at 17:27:44 on Wednesday, 23 May 2007 References: <1b151690705231708v19ab6f5mb647007d6bcd1cea@mail.gmail.com> <43aa6ff70705231727i2b70b9a5hd4800018a23b052b@mail.gmail.com> Message-ID: <18004.58069.315719.640582@terry-jones-computer.local> Adding nodef would be another step on the road to anarchy and nihilism. It wouldn't be long before people began using nodef as a possible value for a function, and then where would we be? Besides, using xxx = object() seems like a safer bet. Your code is unlikely to be accidentally called by someone else using your semi-private xxx object. If there were a documented official nodef object, someone would eventually call you with nodef instead of None. Terry From showell30 at yahoo.com Sat May 26 18:06:25 2007 From: showell30 at yahoo.com (Steve Howell) Date: Sat, 26 May 2007 09:06:25 -0700 (PDT) Subject: [Python-ideas] SQL-like way to manipulate Python data structures Message-ID: <914604.8688.qm@web33509.mail.mud.yahoo.com> I find myself often writing somewhat tedious code in Python that is just slicing/aggregating fairly simple data structures like a list of dictionaries. Here is something that I'm trying to express, roughly: charges = sum float(charge) from events on setup, install group by name Here is the Python code that I wrote: def groupDictBy(lst, keyField): dct = {} for item in lst: keyValue = item[keyField] if keyValue not in dct: dct[keyValue] = [] dct[keyValue].append(item) return dct dct = groupDictBy(events, 'name') for name in dct: events = dct[name] charges = {} for bucket in ('setup', 'install'): charges[bucket] = sum( [float(event['charge']) for event in events if event['bucket'] == bucket]) Comments are welcome on improving the code itself, but I wonder if Python 3k (or 4k?) couldn't have some kind of native SQL-like ways of manipulating lists and dictionaries. I don't have a proposal myself, just wonder if others have felt this kind of pain, and maybe it will spark a Pythonic solution. ____________________________________________________________________________________Sick sense of humor? Visit Yahoo! TV's Comedy with an Edge to see what's on, when. http://tv.yahoo.com/collections/222 From arno at marooned.org.uk Sat May 26 18:58:53 2007 From: arno at marooned.org.uk (Arnaud Delobelle) Date: Sat, 26 May 2007 17:58:53 +0100 Subject: [Python-ideas] SQL-like way to manipulate Python data structures In-Reply-To: <914604.8688.qm@web33509.mail.mud.yahoo.com> References: <914604.8688.qm@web33509.mail.mud.yahoo.com> Message-ID: <4BB75E2A-92F8-48D2-81DB-427ACA86AC8F@marooned.org.uk> On 26 May 2007, at 17:06, Steve Howell wrote: > I find myself often writing somewhat tedious code in > Python that is just slicing/aggregating fairly simple > data structures like a list of dictionaries. > > Here is something that I'm trying to express, roughly: > > charges = > sum float(charge) from events > on setup, install > group by name I don't really understand that :) > Here is the Python code that I wrote: > > def groupDictBy(lst, keyField): > dct = {} > for item in lst: > keyValue = item[keyField] > if keyValue not in dct: > dct[keyValue] = [] > dct[keyValue].append(item) > return dct > isn't that itertools.groupby? > dct = groupDictBy(events, 'name') > for name in dct: > events = dct[name] > charges = {} > for bucket in ('setup', 'install'): > charges[bucket] = sum( > [float(event['charge']) for > event in events > if event['bucket'] == bucket]) from itertools import groupby from operator import itemgetter charges = {} for name, n_evts in groupby(events, itemgetter('name')): charges[name] = dict((bucket, sum(float(e['charge']) for e in b_evts) for bucket, b_evts in groupby(n_evts, itemgetter('bucket')) if bucket in ('setup', 'install')) The last line can be omitted if the only two existing buckets are 'setup' and 'install'. Untested! I've changed your code slightly as in your snippet 'charges' is reset to {} at each iteration of the loop. -- Arnaud From blais at furius.ca Thu May 24 16:42:34 2007 From: blais at furius.ca (Martin Blais) Date: Thu, 24 May 2007 07:42:34 -0700 Subject: [Python-ideas] [Python-Dev] nodef In-Reply-To: <43aa6ff70705231727i2b70b9a5hd4800018a23b052b@mail.gmail.com> References: <1b151690705231708v19ab6f5mb647007d6bcd1cea@mail.gmail.com> <43aa6ff70705231727i2b70b9a5hd4800018a23b052b@mail.gmail.com> Message-ID: <1b151690705240742u63103adel34b5c8b98eb004e6@mail.gmail.com> On 5/23/07, Collin Winter wrote: > [moving to python-ideas, where it belongs] > > > I think Python needs a builtin for this very purpose. I propose > > 'nodef', a unique object whose sole purpose is to serve as a default > > value. It should be unique, in the same sense that 'None' is unique. > > I've run into this situation several times before, and I've never felt > that defining my own sentinel was unduly taxing. Having a built-in > would only save a single line, the initial "sentinel = object()". There is another benefit to a builtin 'nodef', BTW, which is that of a consistent meaning for the word. Having a consistent name for this concept--across all programs, if it were in the language--makes it more obvious what you're trying to achieve. Otherwise, you decide to use 'sentinel', I choose 'NoDef', Barry uses 'missing', and we're all speaking a different "language". Thought I do admit that the possibility of misuse of a builtin 'nodef' is slightly troubling. I guess object() is our (gensym), I did not know that. cheers, From arno at marooned.org.uk Sat May 26 21:30:35 2007 From: arno at marooned.org.uk (Arnaud Delobelle) Date: Sat, 26 May 2007 20:30:35 +0100 Subject: [Python-ideas] [Python-Dev] nodef In-Reply-To: <1b151690705240742u63103adel34b5c8b98eb004e6@mail.gmail.com> References: <1b151690705231708v19ab6f5mb647007d6bcd1cea@mail.gmail.com> <43aa6ff70705231727i2b70b9a5hd4800018a23b052b@mail.gmail.com> <1b151690705240742u63103adel34b5c8b98eb004e6@mail.gmail.com> Message-ID: <2A826EFD-045D-42AA-8B7F-7BE413B95E85@marooned.org.uk> On 24 May 2007, at 15:42, Martin Blais wrote: > On 5/23/07, Collin Winter wrote: >> [moving to python-ideas, where it belongs] >> >>> I think Python needs a builtin for this very purpose. I propose >>> 'nodef', a unique object whose sole purpose is to serve as a default >>> value. It should be unique, in the same sense that 'None' is >>> unique. >> >> I've run into this situation several times before, and I've never >> felt >> that defining my own sentinel was unduly taxing. Having a built-in >> would only save a single line, the initial "sentinel = object()". > > There is another benefit to a builtin 'nodef', BTW, which is that of a > consistent meaning for the word. Having a consistent name for this > concept--across all programs, if it were in the language--makes it > more obvious what you're trying to achieve. Otherwise, you decide to > use 'sentinel', I choose 'NoDef', Barry uses 'missing', and we're all > speaking a different "language". Just as you find that 'None' is sometimes a valid value for a function parameter (and this is the reason why you would like 'nodef'), if there was a 'nodef' builtin you would sometimes find that it is a meaningful value for a function parameter. Would you then advocate the creation of a 'really_nodef' builtin? And then a 'this_time_i_really_mean_it_nodef' builtin? This is why a 'nodef' keyword is not a good idea. 'None' is useful because often you expect an argument of a certain type (e.g. a list, so you know it should not be 'None'). -- Arnaud From showell30 at yahoo.com Sun May 27 00:11:55 2007 From: showell30 at yahoo.com (Steve Howell) Date: Sat, 26 May 2007 15:11:55 -0700 (PDT) Subject: [Python-ideas] SQL-like way to manipulate Python data structures In-Reply-To: <4BB75E2A-92F8-48D2-81DB-427ACA86AC8F@marooned.org.uk> Message-ID: <403979.10572.qm@web33503.mail.mud.yahoo.com> --- Arnaud Delobelle wrote: > > On 26 May 2007, at 17:06, Steve Howell wrote: > > > I find myself often writing somewhat tedious code > in > > Python that is just slicing/aggregating fairly > simple > > data structures like a list of dictionaries. > > > > Here is something that I'm trying to express, > roughly: > > > > charges = > > sum float(charge) from events > > on setup, install > > group by name > > I don't really understand that :) > Let me try again: select name, bucket, sum(float(charge)) from events where bucket in ('install', 'setup') group by name, bucket The idea here is that events is a list of Python dictionaries keyed by fields "name", "bucket", and "charge", and I only care about install/setup charges. Here is a rough Python statement of what I'm trying to do: charges = {} for name, n_evts in groupby(events, itemgetter('name')): print name print dict([(bucket, sum([float(e['charge']) for e in b_evts])) for bucket, b_evts in groupby(n_evts, itemgetter('bucket')) if bucket in ('setup', 'install')]) > > Here is the Python code that I wrote: > > > > def groupDictBy(lst, keyField): > > dct = {} > > for item in lst: > > keyValue = item[keyField] > > if keyValue not in dct: > > dct[keyValue] = [] > > dct[keyValue].append(item) > > return dct > > > > isn't that itertools.groupby? > The problem with itertools.groupby is that it assumes sorted lists. So the code below does not behave how you might expect. It reports Joe's charges twice, and it loses Steve's $50 install charge. from itertools import groupby from operator import itemgetter events = [ {'name': 'Joe', 'bucket': 'install', 'charge': 100}, {'name': 'Joe', 'bucket': 'setup', 'charge': 20}, {'name': 'Steve', 'bucket': 'install', 'charge': 50}, {'name': 'Steve', 'bucket': 'setup', 'charge': 30}, {'name': 'Steve', 'bucket': 'install', 'charge': 1000}, {'name': 'Steve', 'bucket': 'upgrade', 'charge': 440}, {'name': 'Joe', 'bucket': 'setup', 'charge': 40}, ] charges = {} for name, n_evts in groupby(events, itemgetter('name')): print name print dict([(bucket, sum([float(e['charge']) for e in b_evts])) for bucket, b_evts in groupby(n_evts, itemgetter('bucket')) if bucket in ('setup', 'install')]) ____________________________________________________________________________________Pinpoint customers who are looking for what you sell. http://searchmarketing.yahoo.com/ From arno at marooned.org.uk Sun May 27 11:03:14 2007 From: arno at marooned.org.uk (Arnaud Delobelle) Date: Sun, 27 May 2007 10:03:14 +0100 Subject: [Python-ideas] positional only arguments decorator In-Reply-To: References: Message-ID: <75AAE6B2-8D9D-43CF-A151-DF0C92964BA7@marooned.org.uk> On 21 May 2007, at 19:30, Steven Bethard wrote: > Ok, looks like there's not much chance of agreeing on a syntax, so > here's a decorator that covers the two use cases I know of:: > > * matching the signature of dict() and dict.update() > * allowing arguments to have their names changed without worrying > about backwards compatibility (e.g. ``def func(sequence)`` changing to > ``def func(iterable)``) I propose a slightly different solution. It may be a bit of a hack, but I don't see why it should not be safe. This solution allows you to use * and ** in order to write a definition like: >>> @posonly ... def update(self, container=None, **kwargs): ... return self, container, kwargs ... >>> update('self') ('self', None, {}) >>> update('self', 'container') ('self', 'container', {}) >>> update('self', self='abc', container='xyz', foo='bar') ('self', None, {'self': 'abc', 'foo': 'bar', 'container': 'xyz'}) >>> Or: >>> @posonly ... def foo(x, y=1, *args, **kwargs): ... return x, y, args, kwargs ... >>> foo('hey') ('hey', 1, (), {}) >>> foo(*'spam') ('s', 'p', ('a', 'm'), {}) >>> foo(577, x=314, args=1618, kwargs=2718) (577, 1, (), {'x': 314, 'args': 1618, 'kwargs': 2718}) >>> Without * or ** it gives the following behaviour: >>> @posonly ... def f(abc, xyz=42): ... return abc, xyz ... >>> f(3) (3, 42) >>> f(4, 5) (4, 5) >>> f(abc=3) Traceback (most recent call last): File "", line 1, in ? File "qrg.py", line 147, in posf raise TypeError('posonly function %s() got keyword argument' TypeError: posonly function f() got keyword argument >>> f() Traceback (most recent call last): File "", line 1, in ? File "qrg.py", line 152, in posf return flat_f(*args, **kwargs) TypeError: f() takes at least 1 argument (0 given) >>> This is achieved by 'flattening' the function first. Here is the code: import new import inspect def flattened(f): """Changes a function f(...[, *y] [, **z]) to f(...[, y=None] [, z=None])""" fc = f.func_code defaults = f.func_defaults flags = fc.co_flags argcount = fc.co_argcount has_varargs = flags & 4 if has_varargs: flags ^= 4 argcount += 1 if defaults: defaults += (None,) has_varkwargs = flags & 8 if has_varkwargs: flags ^= 8 argcount += 1 if defaults: defaults += (None,) flat_code = new.code(argcount, fc.co_nlocals, fc.co_stacksize, flags, fc.co_code, fc.co_consts, fc.co_names, fc.co_varnames, fc.co_filename, fc.co_name, fc.co_firstlineno, fc.co_lnotab) flat_f = new.function(flat_code, f.func_globals, f.func_name, defaults, f.func_closure) return flat_f def posonly(f): "posonly(f) makes the arguments of f positional only" f_args, f_varargs, f_varkwargs, f_defaults = inspect.getargspec(f) f_nargs = len(f_args) f_name = f.__name__ flat_f = flattened(f) def posf(*args, **kwargs): if f_varkwargs: kwargs = {f_varkwargs: kwargs} elif kwargs: raise TypeError('posonly function %s() got keyword argument' % f_name) if f_varargs: kwargs[f_varargs] = args[f_nargs:] args = args[:f_nargs] return flat_f(*args, **kwargs) posf.__name__ = f_name return posf -- Arnaud From stephen at xemacs.org Sun May 27 13:35:03 2007 From: stephen at xemacs.org (Stephen J. Turnbull) Date: Sun, 27 May 2007 20:35:03 +0900 Subject: [Python-ideas] [Python-Dev] nodef In-Reply-To: <1b151690705240742u63103adel34b5c8b98eb004e6@mail.gmail.com> References: <1b151690705231708v19ab6f5mb647007d6bcd1cea@mail.gmail.com> <43aa6ff70705231727i2b70b9a5hd4800018a23b052b@mail.gmail.com> <1b151690705240742u63103adel34b5c8b98eb004e6@mail.gmail.com> Message-ID: <87zm3q33fc.fsf@uwakimon.sk.tsukuba.ac.jp> Martin Blais writes: > There is another benefit to a builtin 'nodef', BTW, which is that of a > consistent meaning for the word. Having a consistent name for this > concept--across all programs, if it were in the language You can have a consistent name for the *concept*, but having a consistent name for the *object* across all programs defeats its purpose. From steven.bethard at gmail.com Sun May 27 17:37:41 2007 From: steven.bethard at gmail.com (Steven Bethard) Date: Sun, 27 May 2007 09:37:41 -0600 Subject: [Python-ideas] positional only arguments decorator In-Reply-To: <75AAE6B2-8D9D-43CF-A151-DF0C92964BA7@marooned.org.uk> References: <75AAE6B2-8D9D-43CF-A151-DF0C92964BA7@marooned.org.uk> Message-ID: On 5/27/07, Arnaud Delobelle wrote: > > On 21 May 2007, at 19:30, Steven Bethard wrote: > > > Ok, looks like there's not much chance of agreeing on a syntax, so > > here's a decorator that covers the two use cases I know of:: > > > > * matching the signature of dict() and dict.update() > > * allowing arguments to have their names changed without worrying > > about backwards compatibility (e.g. ``def func(sequence)`` changing to > > ``def func(iterable)``) > > I propose a slightly different solution. It may be a bit of a hack, > but I don't see why it should not be safe. This solution allows you > to use * and ** in order to write a definition like: > > >>> @posonly > ... def update(self, container=None, **kwargs): > ... return self, container, kwargs > ... > >>> update('self') > ('self', None, {}) > >>> update('self', 'container') > ('self', 'container', {}) > >>> update('self', self='abc', container='xyz', foo='bar') > ('self', None, {'self': 'abc', 'foo': 'bar', 'container': 'xyz'}) Cool! Yes, it's hackish, but at least the results are pretty. ;-) STeVe -- I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a tiny blip on the distant coast of sanity. --- Bucky Katt, Get Fuzzy From arno at marooned.org.uk Mon May 28 13:22:45 2007 From: arno at marooned.org.uk (Arnaud Delobelle) Date: Mon, 28 May 2007 12:22:45 +0100 Subject: [Python-ideas] positional only arguments decorator In-Reply-To: <75AAE6B2-8D9D-43CF-A151-DF0C92964BA7@marooned.org.uk> References: <75AAE6B2-8D9D-43CF-A151-DF0C92964BA7@marooned.org.uk> Message-ID: <6444B195-5B3A-49D9-BEB3-85FDEA6B234A@marooned.org.uk> On 27 May 2007, at 10:03, Arnaud Delobelle wrote: [...] > This is achieved by 'flattening' the function first. Here is the > code: > > import new > import inspect [...] Well it turns out there can be problems as my code does not initialise the co_freevars and co_cellvars of the code objects it creates. I blame it on the python doc (;-) which shows the signature of new.code as: code(argcount, nlocals, stacksize, flags, codestring, constants, names, varnames, filename, name, firstlineno, lnotab) Missing out on the last two optional arguments (freevars and cellvars). I only found that out by looking at Object/codeobject.c (which shows how clever I am, since I could have simply typed 'help (code.new)'). Moreover the file Lib/new.py says that the 'new' module is now deprecated, and that 'import types' should be used instead. So here is the modified code. The 'posonly' decorator is used in exactly the same way as I've described in my previous email. Compared with the previous version, I have tried to reduce the overhead caused by making a function 'posonly' to a minimum (this is why there are three definitions of 'posf'). Note that when a posonly function is called incorrectly , there should be a helpful error message, which is the 'builtin' one most of the time. Please tell me if it is not appropriate to send code to the list as I'm doing. ----------------------------------------------- from types import CodeType, FunctionType import inspect code_args = ( 'argcount', 'nlocals', 'stacksize', 'flags', 'code', 'consts', 'names', 'varnames', 'filename', 'name', 'firstlineno', 'lnotab', 'freevars', 'cellvars' ) function_args = ('code', 'globals', 'name', 'defaults', 'closure') def copy_code(code_obj, **kwargs): "Make a copy of a code object, maybe changing some attributes" for arg in code_args: if not kwargs.has_key(arg): kwargs[arg] = getattr(code_obj, 'co_%s' % arg) return CodeType(*map(kwargs.__getitem__, code_args)) def copy_function(function_obj, **kwargs): "Make a copy of a function object, maybe changing some attributes" for arg in function_args: if not kwargs.has_key(arg): kwargs[arg] = getattr(function_obj, 'func_%s' % arg) return FunctionType(*map(kwargs.__getitem__, function_args)) def rename_function(f, name): f.__name__ = name f.func_code = copy_code(f.func_code, name=name) def flattened(f): """Changes a function f(...[, *y] [, **z]) to f(...[, y=None] [, z=None])""" fc = f.func_code defaults = f.func_defaults flags = fc.co_flags argcount = fc.co_argcount for bit in 4, 8: if flags & bit: flags ^= bit argcount += 1 if defaults: defaults += (None,) flat_code = copy_code(fc, argcount=argcount, flags=flags) flat_f = copy_function(f, code=flat_code, defaults=defaults) return flat_f def posonly(f): "posonly(f) makes the arguments of f positional only" f_args, f_varargs, f_varkwargs, f_defaults = inspect.getargspec(f) f_nargs = len(f_args) f_name = f.__name__ flat_f = flattened(f) if f_varargs and f_varkwargs: def posf(*args, **kwargs): kwargs = {f_varkwargs: kwargs} kwargs[f_varargs] = args[f_nargs:] args = args[:f_nargs] return flat_f(*args, **kwargs) elif f_varkwargs: # and not f_varargs def posf(*args, **kwargs): kwargs = {f_varkwargs: kwargs} if len(args) > f_nargs: msg = '%s() takes at most %i arguments (%i given)' raise TypeError(msg % (f_name, f_nargs, len(args))) return flat_f(*args, **kwargs) else: # not f_varkwargs def posf(*args): return f(*args) rename_function(posf, f_name) return posf ----------------------------------------------- -- Arnaud From aahz at pythoncraft.com Mon May 28 22:23:11 2007 From: aahz at pythoncraft.com (Aahz) Date: Mon, 28 May 2007 13:23:11 -0700 Subject: [Python-ideas] SQL-like way to manipulate Python data structures In-Reply-To: <914604.8688.qm@web33509.mail.mud.yahoo.com> References: <914604.8688.qm@web33509.mail.mud.yahoo.com> Message-ID: <20070528202311.GC18819@panix.com> On Sat, May 26, 2007, Steve Howell wrote: > > Comments are welcome on improving the code itself, but I wonder if > Python 3k (or 4k?) couldn't have some kind of native SQL-like ways of > manipulating lists and dictionaries. I don't have a proposal myself, > just wonder if others have felt this kind of pain, and maybe it will > spark a Pythonic solution. What's wrong with sqlite? -- Aahz (aahz at pythoncraft.com) <*> http://www.pythoncraft.com/ "Look, it's your affair if you want to play with five people, but don't go calling it doubles." --John Cleese anticipates Usenet From showell30 at yahoo.com Mon May 28 23:57:44 2007 From: showell30 at yahoo.com (Steve Howell) Date: Mon, 28 May 2007 14:57:44 -0700 (PDT) Subject: [Python-ideas] SQL-like way to manipulate Python data structures In-Reply-To: <20070528202311.GC18819@panix.com> Message-ID: <314501.96528.qm@web33514.mail.mud.yahoo.com> --- Aahz wrote: > > What's wrong with sqlite? Nothing, but I want Python itself to give me the SQL syntax to manipulate lists-of-dictionaries like lists of dictionaries, without having to go through some a module. In the example that I gave earlier in the thread, what would the sqlite solution look like? To transform any particular list of dicitionaries into another list of dictionaries, would I have to do a create-table in sqlite, or does it already have some kind of mode where it can work directly on a Python dataset? ____________________________________________________________________________________ Be a PS3 game guru. Get your game face on with the latest PS3 news and previews at Yahoo! Games. http://videogames.yahoo.com/platform?platform=120121 From rrr at ronadam.com Tue May 29 00:49:30 2007 From: rrr at ronadam.com (Ron Adam) Date: Mon, 28 May 2007 17:49:30 -0500 Subject: [Python-ideas] dict.fromkeys() better as dict().setkeys() ? (and other suggestions) Message-ID: <465B5C7A.7070306@ronadam.com> The dictionary fromkeys method seems out of place as well as miss-named. IMHO In the current 2.5 branch it occurs only twice. (excluding tests) ---- $ grep -r "fromkeys" Lib/*.py Lib/httplib.py: header_names = dict.fromkeys([k.lower() for k in headers]) Lib/UserDict.py: def fromkeys(cls, iterable, value=None): ---- In httplib.py, it is used as a set to remove duplicates. There are enough correct uses of it in the wild to keep the behavior, but it can be done in a better way. I feel it really should be called set_keys and implemented as a method that operates on the current dictionary instead of being a constructor for a new dictionary. That will allow you to add keys with a default value to an already existing dictionary, or to create a new one with a dictionary constructor. dict().set_keys(s, v=None) # The current fromkeys behavior. I think this reads better and can be used in a wider variety of situations. It could be useful for setting an existing dictionary to a default state. # reset status of items. status.set_keys(status.keys(), v=0) Or more likely, resetting a partial sub set of the keys to some initial state. The reason I started looking at this is I wanted to split a dictionary into smaller dictionaries and my first thought was that fromkeys would do that. But of course it doesn't. What I wanted was to be able to specify the keys and get the values from the existing dictionary into the new dictionary without using a for loop to iterate over the keys. d = dict(1='a', 2='b', 3='c', 4='d', 5='e') d_odds = d.from_keys([1, 3, 5]) # new dict of items 1, 3, 5 d_evens = d.from_keys([2, 4]) # new dict of items 2, 4 There currently isn't a way to split a dictionary without iterating it's contents even if you know the keys you need before hand. A from_keys method would be the inverse complement of the update method. A del_keys method could replace the clear method. del_keys would be more useful as it could operate on a partial set of keys. d.delkeys(d.keys()) # The current clear method behavior. Some potentially *very common* uses: # This first one works now, but I included it for completeness. ;-) mergedicts(d1, d2): """ Combine two dictionaries. """ dd = dict(d1) return dd.update(d2) splitdict(d, keys): """ Split dictionary d using keys. """ keys_rest = set(d.keys()) - set(keys) return d.from_keys(keys), d.from_keys(keys_rest) split_from_dict(d, keys): """ Removes and returns a subdict of d with keys. """ dd = d.from_keys(keys) d.del_keys(keys) return dd copy_items(d1, d2, keys): """ Copy items from dictionary d1 to d2. """ d2.update(d1.from_keys(keys)) # I really like this! move_items(d1, d2, keys): """ Move items from dictionary d1 to d2. """ d2.update(d1.from_keys(keys)) d1.del_keys(keys) I think the set_keys, from_keys, and del_keys methods could add both performance and clarity benefits to python. So to summarize... 1. Replace existing fromkeys method with a set_keys method. 2. Add a partial copy items from_keys method. 3. Replace the clear method with a del_keys method. So this replaces two methods and adds one more. Overall I think the usefulness of these would be very good. I also think it will work very well with the python 3000 keys method returning an iterator. (And still be two fewer methods than we currently have.) Any thoughts? Cheers, Ron From jcarlson at uci.edu Tue May 29 01:56:17 2007 From: jcarlson at uci.edu (Josiah Carlson) Date: Mon, 28 May 2007 16:56:17 -0700 Subject: [Python-ideas] dict.fromkeys() better as dict().setkeys() ? (and other suggestions) In-Reply-To: <465B5C7A.7070306@ronadam.com> References: <465B5C7A.7070306@ronadam.com> Message-ID: <20070528162407.869C.JCARLSON@uci.edu> Ron Adam wrote: > There are enough correct uses of it in the wild to keep the behavior, but > it can be done in a better way. > > I feel it really should be called set_keys and implemented as a method that > operates on the current dictionary instead of being a constructor for a new > dictionary. That will allow you to add keys with a default value to an > already existing dictionary, or to create a new one with a dictionary > constructor. > > dict().set_keys(s, v=None) # The current fromkeys behavior. The problem with that is that when a method mutates an object, it shouldn't return the object. Your new .set_keys() method violates this behavior that is used in lists, sets, dicts, deques, arrays, etc. I don't have time to comment on the rest at the moment, will do when I get a chance. - Josiah From aahz at pythoncraft.com Tue May 29 02:14:22 2007 From: aahz at pythoncraft.com (Aahz) Date: Mon, 28 May 2007 17:14:22 -0700 Subject: [Python-ideas] SQL-like way to manipulate Python data structures In-Reply-To: <314501.96528.qm@web33514.mail.mud.yahoo.com> References: <20070528202311.GC18819@panix.com> <314501.96528.qm@web33514.mail.mud.yahoo.com> Message-ID: <20070529001422.GA14967@panix.com> On Mon, May 28, 2007, Steve Howell wrote: > --- Aahz wrote: >> >> What's wrong with sqlite? > > Nothing, but I want Python itself to give me the SQL syntax to > manipulate lists-of-dictionaries like lists of dictionaries, without > having to go through some a module. > > In the example that I gave earlier in the thread, what would the > sqlite solution look like? To transform any particular list of > dicitionaries into another list of dictionaries, would I have to do > a create-table in sqlite, or does it already have some kind of mode > where it can work directly on a Python dataset? You'd have to convert your data into sqlite tables, of course, but: * It's not much work * Your specific needs for operating on data are likely to be different from everyone else's -- the reason SQL works is precisely because it imposes constraints on data format To the extent that Python provides anything roughly comparable to SQL, use listcomps and genexps. Think of it this way: if Python requires you to use a library for regex manipulation, what makes SQL-like data processing sufficiently special that it belongs in the language itself? -- Aahz (aahz at pythoncraft.com) <*> http://www.pythoncraft.com/ "Look, it's your affair if you want to play with five people, but don't go calling it doubles." --John Cleese anticipates Usenet From rrr at ronadam.com Tue May 29 02:21:48 2007 From: rrr at ronadam.com (Ron Adam) Date: Mon, 28 May 2007 19:21:48 -0500 Subject: [Python-ideas] dict.fromkeys() better as dict().setkeys() ? (and other suggestions) In-Reply-To: <20070528162407.869C.JCARLSON@uci.edu> References: <465B5C7A.7070306@ronadam.com> <20070528162407.869C.JCARLSON@uci.edu> Message-ID: <465B721C.3080106@ronadam.com> Josiah Carlson wrote: > Ron Adam wrote: >> There are enough correct uses of it in the wild to keep the behavior, but >> it can be done in a better way. >> >> I feel it really should be called set_keys and implemented as a method that >> operates on the current dictionary instead of being a constructor for a new >> dictionary. That will allow you to add keys with a default value to an >> already existing dictionary, or to create a new one with a dictionary >> constructor. >> >> dict().set_keys(s, v=None) # The current fromkeys behavior. > > The problem with that is that when a method mutates an object, it > shouldn't return the object. Your new .set_keys() method violates this > behavior that is used in lists, sets, dicts, deques, arrays, etc. Huh? Where does it return an object? > I don't have time to comment on the rest at the moment, will do when I > get a chance. > > - Josiah Ok :-) Ron From rrr at ronadam.com Tue May 29 02:29:07 2007 From: rrr at ronadam.com (Ron Adam) Date: Mon, 28 May 2007 19:29:07 -0500 Subject: [Python-ideas] dict.fromkeys() better as dict().setkeys() ? (and other suggestions) In-Reply-To: <465B721C.3080106@ronadam.com> References: <465B5C7A.7070306@ronadam.com> <20070528162407.869C.JCARLSON@uci.edu> <465B721C.3080106@ronadam.com> Message-ID: <465B73D3.9010603@ronadam.com> Ron Adam wrote: > Josiah Carlson wrote: >> Ron Adam wrote: >>> There are enough correct uses of it in the wild to keep the behavior, but >>> it can be done in a better way. >>> >>> I feel it really should be called set_keys and implemented as a method that >>> operates on the current dictionary instead of being a constructor for a new >>> dictionary. That will allow you to add keys with a default value to an >>> already existing dictionary, or to create a new one with a dictionary >>> constructor. >>> >>> dict().set_keys(s, v=None) # The current fromkeys behavior. >> The problem with that is that when a method mutates an object, it >> shouldn't return the object. Your new .set_keys() method violates this >> behavior that is used in lists, sets, dicts, deques, arrays, etc. > > Huh? Where does it return an object? Whoops, Ok I see it now. So the example should be... d = dict() d.set_keys(s, v=none) I think that would work fine. >> I don't have time to comment on the rest at the moment, will do when I >> get a chance. >> >> - Josiah > > Ok :-) > > Ron > > > _______________________________________________ > Python-ideas mailing list > Python-ideas at python.org > http://mail.python.org/mailman/listinfo/python-ideas > > From adam at atlas.st Tue May 29 02:29:49 2007 From: adam at atlas.st (Adam Atlas) Date: Mon, 28 May 2007 20:29:49 -0400 Subject: [Python-ideas] SQL-like way to manipulate Python data structures In-Reply-To: <914604.8688.qm@web33509.mail.mud.yahoo.com> References: <914604.8688.qm@web33509.mail.mud.yahoo.com> Message-ID: <86BD9376-372F-4CE4-9A38-7575A0E60B9B@atlas.st> On 26 May 2007, at 12.06, Steve Howell wrote: > Here is the Python code that I wrote: > > def groupDictBy(lst, keyField): > dct = {} > for item in lst: > keyValue = item[keyField] > if keyValue not in dct: > dct[keyValue] = [] > dct[keyValue].append(item) > return dct I think this is basically equivalent to itertools.groupby. You could do: for name, events in itertools.groupby(events, lambda e: e ['name']): ... Untested, but I'm pretty sure that's what you're doing here. The main difference is that it returns an iterable of 2-tuples instead of a dictionary (but you can just pass it straight to dict() if need be), and that it requires you to pass it a key function (here a simple lambda) instead of a dictionary key. > dct = groupDictBy(events, 'name') > for name in dct: > events = dct[name] > charges = {} > for bucket in ('setup', 'install'): > charges[bucket] = sum( > [float(event['charge']) for > event in events > if event['bucket'] == bucket]) I'm not quite sure what the intended function of this is. You group dct by the 'name' field, but for each iteration of the loop, you're setting the `charges` variable anew, basically throwing away the value produced by any previous iteration. That's not intended, is it? Second, it looks almost like the inner loop could also be an itertools.groupby call. Grouping by 'bucket'. Ignoring the previous paragraph, I think it would be something like this: for name, events in itertools.groupby(events, lambda e: e['name']): charges = dict([(bucket, sum([float(event['charge']) for event in v])) for bucket, v in itertools.groupby(events, lambda e: e ['bucket'])]) And of course if you meant to have 'charges' be an array or a dict or something, with a value for each iteration of the outer loop, then this could be made into a one-liner by changing the for loop into a list comprehension. It's not as terse as SQL, but it gets the job done. > Comments are welcome on improving the code itself, but > I wonder if Python 3k (or 4k?) couldn't have some kind > of native SQL-like ways of manipulating lists and > dictionaries. I don't have a proposal myself, just > wonder if others have felt this kind of pain, and > maybe it will spark a Pythonic solution. I don't really have an opinion for now, but if this does happen, I think the best way would be to have a new 'table' type supporting operations like this. (I think a stdlib module would do; I don't think this is quite important enough to warrant a global builtin type. And filling `dict` itself with these methods could get cluttersome.) I started writing a paragraph here about what types of methods it could have, returning various types of iterators, but then I realized that I was basically describing SQLAlchemy. So I think we shouldn't reinvent the wheel there; it would be an interesting exercise to see if SQLAlchemy could be made to operate on native Python data structures, though. From jcarlson at uci.edu Tue May 29 02:41:33 2007 From: jcarlson at uci.edu (Josiah Carlson) Date: Mon, 28 May 2007 17:41:33 -0700 Subject: [Python-ideas] dict.fromkeys() better as dict().setkeys() ? (and other suggestions) In-Reply-To: <465B721C.3080106@ronadam.com> References: <20070528162407.869C.JCARLSON@uci.edu> <465B721C.3080106@ronadam.com> Message-ID: <20070528173945.869F.JCARLSON@uci.edu> Ron Adam wrote: > Josiah Carlson wrote: > > Ron Adam wrote: > >> There are enough correct uses of it in the wild to keep the behavior, but > >> it can be done in a better way. > >> > >> I feel it really should be called set_keys and implemented as a method that > >> operates on the current dictionary instead of being a constructor for a new > >> dictionary. That will allow you to add keys with a default value to an > >> already existing dictionary, or to create a new one with a dictionary > >> constructor. > >> > >> dict().set_keys(s, v=None) # The current fromkeys behavior. > > > > The problem with that is that when a method mutates an object, it > > shouldn't return the object. Your new .set_keys() method violates this > > behavior that is used in lists, sets, dicts, deques, arrays, etc. > > Huh? Where does it return an object? If you are looking to replace dict.fromkeys(...), then dict().set_keys (...) must return the dictionary that was just created and mutated. - Josiah From jcarlson at uci.edu Tue May 29 03:18:22 2007 From: jcarlson at uci.edu (Josiah Carlson) Date: Mon, 28 May 2007 18:18:22 -0700 Subject: [Python-ideas] dict.fromkeys() better as dict().setkeys() ? (and other suggestions) In-Reply-To: <465B5C7A.7070306@ronadam.com> References: <465B5C7A.7070306@ronadam.com> Message-ID: <20070528174325.86A2.JCARLSON@uci.edu> Ron Adam wrote: > The dictionary fromkeys method seems out of place as well as miss-named. IMHO It is perfectly named (IMNSHO ;), create a dictionary from the keys provided; dict.fromkeys() . > There are enough correct uses of it in the wild to keep the behavior, but > it can be done in a better way. I wasn't terribly convinced by your later arguments, so I'm -1. > I think this reads better and can be used in a wider variety of situations. > > It could be useful for setting an existing dictionary to a default state. > > # reset status of items. > status.set_keys(status.keys(), v=0) This can be done today: status.update((i, 0) for i in status.keys()) #or status.update(dict.fromkeys(status, 0)) > Or more likely, resetting a partial sub set of the keys to some initial state. > > > The reason I started looking at this is I wanted to split a dictionary into > smaller dictionaries and my first thought was that fromkeys would do that. > But of course it doesn't. Changing the bahvior of dict.fromkeys() is not going to happen. We can remove it, we can add a new method, but changing will lead to not so subtle breakage as people who were used to the old behavior try to use the updated method. Note that this isn't a matter of "it's ok to break in 3.0", because dict.fromkeys() is not seen as being a design mistake by any of the 'heavy hitters' in python-dev or python-3000 that I have heard (note that I am certainly not a 'heavy hitter'). > What I wanted was to be able to specify the keys and get the values from > the existing dictionary into the new dictionary without using a for loop to > iterate over the keys. > > d = dict(1='a', 2='b', 3='c', 4='d', 5='e') > > d_odds = d.from_keys([1, 3, 5]) # new dict of items 1, 3, 5 > d_evens = d.from_keys([2, 4]) # new dict of items 2, 4 > > There currently isn't a way to split a dictionary without iterating it's > contents even if you know the keys you need before hand. Um... def from_keys(d, iterator): return dict((i, d[i]) for i in iterator) > A del_keys method could replace the clear method. del_keys would be more > useful as it could operate on a partial set of keys. > > d.delkeys(d.keys()) # The current clear method behavior. I can't remember ever needing something like this that wasn't handled by d.clear() . > Some potentially *very common* uses: > > # This first one works now, but I included it for completeness. ;-) > > mergedicts(d1, d2): > """ Combine two dictionaries. """ > dd = dict(d1) > return dd.update(d2) dict((i, d2.get(i, d1.get(i))) for i in itertools.chain(d1,d2)) > splitdict(d, keys): > """ Split dictionary d using keys. """ > keys_rest = set(d.keys()) - set(keys) > return d.from_keys(keys), d.from_keys(keys_rest) I can't think of a simple one-liner for this one that wouldn't duplicate work. > split_from_dict(d, keys): > """ Removes and returns a subdict of d with keys. """ > dd = d.from_keys(keys) > d.del_keys(keys) > return dd dict((i, d.pop(i, None)) for i in keys) > copy_items(d1, d2, keys): > """ Copy items from dictionary d1 to d2. """ > d2.update(d1.from_keys(keys)) # I really like this! d2.update((i, d1[i]) for i in keys) > move_items(d1, d2, keys): > """ Move items from dictionary d1 to d2. """ > d2.update(d1.from_keys(keys)) > d1.del_keys(keys) d2.update((i, d1.pop(i, None)) for i in keys) > I think the set_keys, from_keys, and del_keys methods could add both > performance and clarity benefits to python. Performance, sometimes, for some use-cases. Clarity? Maybe. Your split* functions are a bit confusing to me, and I've never really needed any of the functions that you list. > So to summarize... > > 1. Replace existing fromkeys method with a set_keys method. > 2. Add a partial copy items from_keys method. > 3. Replace the clear method with a del_keys method. Not all X line functions should be builtins. If you find that you are doing the above more often than you think you should, create a module with all of the related functionality that automatically patches the builtins on import and place it in the Python cheeseshop. If people find that the functionality helps them, then we should consider it for inclusion. As it stands, most of the methods you offer have a very simple one-line version that is already very efficient. > So this replaces two methods and adds one more. Overall I think the > usefulness of these would be very good. I don't find the current dictionary API to be lacking in any way other than "what do I really need to override to get functionality X", but that is a documentation issue more than anything. > I also think it will work very well with the python 3000 keys method > returning an iterator. (And still be two fewer methods than we currently > have.) I'm sorry, but I can't really see how your changes would add to Python's flexibility without cluttering up interfaces and confusing current users. - Josiah From rrr at ronadam.com Tue May 29 06:04:06 2007 From: rrr at ronadam.com (Ron Adam) Date: Mon, 28 May 2007 23:04:06 -0500 Subject: [Python-ideas] dict.fromkeys() better as dict().setkeys() ? (and other suggestions) In-Reply-To: <20070528174325.86A2.JCARLSON@uci.edu> References: <465B5C7A.7070306@ronadam.com> <20070528174325.86A2.JCARLSON@uci.edu> Message-ID: <465BA636.8070501@ronadam.com> Josiah Carlson wrote: > Ron Adam wrote: >> The dictionary fromkeys method seems out of place as well as miss-named. IMHO > > It is perfectly named (IMNSHO ;), create a dictionary from the keys > provided; dict.fromkeys() . That's ok, I won't hold it against you. ;-) What about it's being out of place? Is this case like 'sorted' vs 'sort' for lists? I'm ok with leaving it names as is if that's a real problem. Another name for the mutate with keys method can be found. That may reduce possible confusion as well. >> There are enough correct uses of it in the wild to keep the behavior, but >> it can be done in a better way. > > I wasn't terribly convinced by your later arguments, so I'm -1. Yes, I'm not the most influential writer. I'm not sure I can convince you it's better if you already think it's not. That has more to do with your personal preference. So lets look at how much it's actually needed in the current (and correct) form. (These are rough estimates, I can try to come up with more accurate statistics if that is desired.) Doing a search on google code turns up 300 hits for "lang:python \.fromkeys\(". Looking at a sample of those, it looks like about 80% use it as a set() constructor to remove duplicates. (For compatibility reason with python 2.3 code, or for pytohn 2.3 and earlier code.) Is there a way to narrow this down to python 2.4 and later? (anyone?) A bit more sampling, it looks like about 8 of 10 of those remaining 20% can be easily converted to the following form without any trouble. d = dict() d.set_keys(keys, v=value) That would leave about 12 cases (YMV) that need the inline functionality. For those a simple function can do it. def dict_from_keys(keys, v=value): d = dict() d.set_keys(keys, v) return d Is 12 cases out of about 315,000 python files a big enough need to keep the current behavior? 315,000 is the number returned from google code for all python files, 'lang:python'. (I'm sure there are some duplicates) Is this more convincing. ;-) (If anyone can come up with better numbers, that would be cool.) >> I think this reads better and can be used in a wider variety of situations. >> >> It could be useful for setting an existing dictionary to a default state. >> >> # reset status of items. >> status.set_keys(status.keys(), v=0) > > This can be done today: Of course all of the examples I gave can be done today. But they nearly all require iterating in python in some form. > status.update((i, 0) for i in status.keys()) > #or > status.update(dict.fromkeys(status, 0)) The first example requires iterating over the keys. The second example works if you want to initialize all the keys. In which case, there is no reason to use the update method. dict.fromkeys(status, 0) is enough. >> Or more likely, resetting a partial sub set of the keys to some initial state. >> >> >> The reason I started looking at this is I wanted to split a dictionary into >> smaller dictionaries and my first thought was that fromkeys would do that. >> But of course it doesn't. > > Changing the bahvior of dict.fromkeys() is not going to happen. We can > remove it, we can add a new method, but changing will lead to not so > subtle breakage as people who were used to the old behavior try to use > the updated method. > > Note that this isn't a matter of "it's ok to break in 3.0", because > dict.fromkeys() is not seen as being a design mistake by any of the > 'heavy hitters' in python-dev or python-3000 that I have heard (note > that I am certainly not a 'heavy hitter'). Then lets find a different name. >> What I wanted was to be able to specify the keys and get the values from >> the existing dictionary into the new dictionary without using a for loop to >> iterate over the keys. >> >> d = dict(1='a', 2='b', 3='c', 4='d', 5='e') >> >> d_odds = d.from_keys([1, 3, 5]) # new dict of items 1, 3, 5 >> d_evens = d.from_keys([2, 4]) # new dict of items 2, 4 >> >> There currently isn't a way to split a dictionary without iterating it's >> contents even if you know the keys you need before hand. > > Um... > > def from_keys(d, iterator): > return dict((i, d[i]) for i in iterator) (iterating) Yep as I said just above this. """There currently isn't a way to split a dictionary without iterating it's contents ...""" Lists have __getslice__, __setslice__, and __delslice__. It could be argued that those can be handled just as well with iterators and loops as well. Of course we see them as seq[s:s+x], on both lists and strings. So why not have an equivalent for dictionaries. We can't slice them, but we do have key lists to use in the same way. >> A del_keys method could replace the clear method. del_keys would be more >> useful as it could operate on a partial set of keys. >> >> d.delkeys(d.keys()) # The current clear method behavior. > > I can't remember ever needing something like this that wasn't handled by > d.clear() . All or nothing. d = dict() works just as well. BTW, google code give 500 hits for "\.clear\(". But it very un-clear how many of those are false positives due to other objects having a clear method. It's probably a significant percentage in this case. >> Some potentially *very common* uses: >> >> # This first one works now, but I included it for completeness. ;-) >> >> mergedicts(d1, d2): >> """ Combine two dictionaries. """ >> dd = dict(d1) >> return dd.update(d2) > > dict((i, d2.get(i, d1.get(i))) for i in itertools.chain(d1,d2)) (iterating) And I'd prefer to define the function in this case for readability reasons. >> splitdict(d, keys): >> """ Split dictionary d using keys. """ >> keys_rest = set(d.keys()) - set(keys) >> return d.from_keys(keys), d.from_keys(keys_rest) > > I can't think of a simple one-liner for this one that wouldn't duplicate > work. :-) This is one of the main motivators. >> split_from_dict(d, keys): >> """ Removes and returns a subdict of d with keys. """ >> dd = d.from_keys(keys) >> d.del_keys(keys) >> return dd > > dict((i, d.pop(i, None)) for i in keys) (iterating) >> copy_items(d1, d2, keys): >> """ Copy items from dictionary d1 to d2. """ >> d2.update(d1.from_keys(keys)) # I really like this! > > d2.update((i, d1[i]) for i in keys) (iterating) >> move_items(d1, d2, keys): >> """ Move items from dictionary d1 to d2. """ >> d2.update(d1.from_keys(keys)) >> d1.del_keys(keys) > > d2.update((i, d1.pop(i, None)) for i in keys) (iterating) >> I think the set_keys, from_keys, and del_keys methods could add both >> performance and clarity benefits to python. > > Performance, sometimes, for some use-cases. Clarity? Maybe. Your > split* functions are a bit confusing to me, and I've never really needed > any of the functions that you list. I think sometime our need is determined by what is available for use. So if it's not available, our minds filter it out from the solutions we consider. That way, we don't need the things we don't have or can't get. My minds "need filter" seems to be broken in that respect. I often need things I don't have. But sometimes that works out to be good. ;-) >> So to summarize... >> >> 1. Replace existing fromkeys method with a set_keys method. >> 2. Add a partial copy items from_keys method. >> 3. Replace the clear method with a del_keys method. > > Not all X line functions should be builtins. Of course I knew someone would point this out. I'm not requesting the above example functions be builtins. Only the changes to the dict methods be considered. They would allow those above functions to work in a more efficient way and I'd be happy to add those functions to my own library. With these methods in most cases the functions wouldn't even be needed. You would just use the methods in combinations with each other directly and the result would still be readable without a lot of 'code' overhead. Also consider this from a larger view. List has __getslice__, __setslice__, and __delslice__. Set has numerous methods that operate on more than one element. Dictionaries are suppose to be highly efficient, but they only have limited methods that can operate on more than one item at a time, so you end up iterating over the keys to do nearly everything. So as an alternative, leave fromkeys and clear alone and add... getkeys(keys) -> dict setkeys(keys, v=None) delkeys(keys) Where these offer the equivalent of list slice functionality to dictionaries. If you find that you are > doing the above more often than you think you should, create a module > with all of the related functionality that automatically patches the > builtins on import and place it in the Python cheeseshop. If people > find that the functionality helps them, then we should consider it for > inclusion. As it stands, most of the methods you offer have a very > simple one-line version that is already very efficient. Iterators and for loops are fairly efficient for small dictionaries, but iterating can still be considerable slower than the equivalent C code if they are large dictionaries. >> So this replaces two methods and adds one more. Overall I think the >> usefulness of these would be very good. > > I don't find the current dictionary API to be lacking in any way other > than "what do I really need to override to get functionality X", but > that is a documentation issue more than anything. >> I also think it will work very well with the python 3000 keys method >> returning an iterator. (And still be two fewer methods than we currently >> have.) > > I'm sorry, but I can't really see how your changes would add to Python's > flexibility without cluttering up interfaces and confusing current users. I think it cleans up the API more than it clutters it up. It coverts two limited use methods to be more general, and adds one more that works with the already existing update method nicely. In both cases of the two existing methods, fromkeys and clear, your arguments, that there all ready exists easy one line functions to do this, would be enough of a reason to not have them in the first place. So do you feel they should be removed? I plan on doing a search of places where these things can make a difference in making the code more readable and/or faster. Cheers, Ron From showell30 at yahoo.com Tue May 29 13:06:24 2007 From: showell30 at yahoo.com (Steve Howell) Date: Tue, 29 May 2007 04:06:24 -0700 (PDT) Subject: [Python-ideas] SQL-like way to manipulate Python data structures In-Reply-To: <20070529001422.GA14967@panix.com> Message-ID: <77963.57573.qm@web33501.mail.mud.yahoo.com> --- Aahz wrote: > Think of it this way: if Python requires you to use > a library for regex > manipulation, what makes SQL-like data processing > sufficiently special > that it belongs in the language itself? There is a difference. Regexes would never leverage python expressions *inside* the regex, even if they were more directly integrated into the language like Perl. (And, for the record, I prefer Python's philosophy to make regexes a module, but I do appreciate the short name, re, and the fact that it's battery included). In the case of SQL, I can imagine something like this: def convert_to_euros(salary): ... result_set = [[[ select deptno, total(convert_to_euros(salary)) from emp where country = 'France' group by deptno ]]] # where emp is a list of dictionaries Obviously, I understand that you can solve this problem in Python now, but you either have to do this: 1) Use more bulky way to describe the expression: sql(..., criteria=lambda row: row['country'] == 'France') 2) Rely on some library to parse the SQL for you, which is good enough for the year 2007, but I wonder why the Python interpreter itself couldn't interpret the SQL to bytecode (at startup time) just as easily as, say, SQLAlchemy or sqlite, does at runtime. ____________________________________________________________________________________Pinpoint customers who are looking for what you sell. http://searchmarketing.yahoo.com/ From showell30 at yahoo.com Tue May 29 14:07:48 2007 From: showell30 at yahoo.com (Steve Howell) Date: Tue, 29 May 2007 05:07:48 -0700 (PDT) Subject: [Python-ideas] proposal to add rowexpr as a keyword Message-ID: <422478.77150.qm@web33501.mail.mud.yahoo.com> ABSTRACT: I propose the following syntax: rowexpr: convert_to_euros(salary) > 50000 and deptno = 10 Rowexpr returns a function object that can be called with one argument, row, and the items "salary" and "deptno" are used to derefence row. RATIONALE: A lot of time people write Python code that works with other small interpreters, such as SQL engines, math libraries, etc., that have an expression syntax of their own. To use SQL as an example, I may want my SQL engine to use this Python expression: where convert_to_euros(salary) > 50000 and deptno = 10 To interact with SQL engines, I could imagine code like the following: sql(..., lambda row: convert_to_euros(row['salary'] > 50000 and row['deptno'] = 10) # not concise sql(..., sql_parse('convert_to_euros(salary) > 50000 and deptno = 10') # requires sophisticated library sql(..., [and_op, [ge_op(func_call_op(convert_to_euros, 'salary'), 50000), eq_opt(itemgetter_op('deptno'), 10)]) # UGLY!!! SOLUTION: Let the Python interpreter build expression objects for you. You write: rowexpr: convert_to_euros(salary) > 50000 and deptno = 10 Python translates that into the same bytecode as: lambda row: convert_to_euros(row['salary'] > 50000 and row['deptno'] == 10 Benefits: 1) Allows smaller code. 2) Having Python translate the rowexpr creates an opportunity for better error messages, catching more things at startup time, etc. 3) In the particular case of SQL, it enable the development methodology that you might start off by writing code that processes data in memory, but with mostly SQL-like syntax, and then switch over to a real SQL database as scalability becomes a bigger concern. COMMON OBJECTIONS: 1) More syntax, of course. 2) Folks used to SQL would still need to adjust to differences between Python expressions (==) and SQL (=). 3) In the case of SQL, people may already be happy enough with current tools, and of course, interpreters external to Python can cache expressions, etc. OPEN QUESTIONS: Would a rowexpr be limited to dictionaries, or could it also try to access object attributes? ____________________________________________________________________________________Be a better Globetrotter. Get better travel answers from someone who knows. Yahoo! Answers - Check it out. http://answers.yahoo.com/dir/?link=list&sid=396545469 From bwinton at latte.ca Tue May 29 16:09:11 2007 From: bwinton at latte.ca (Blake Winton) Date: Tue, 29 May 2007 10:09:11 -0400 Subject: [Python-ideas] proposal to add rowexpr as a keyword In-Reply-To: <422478.77150.qm@web33501.mail.mud.yahoo.com> References: <422478.77150.qm@web33501.mail.mud.yahoo.com> Message-ID: <465C3407.6030903@latte.ca> Steve Howell wrote: > Let the Python interpreter build expression objects > for you. You write: > rowexpr: convert_to_euros(salary) > 50000 and > deptno = 10 > Python translates that into the same bytecode as: > lambda row: convert_to_euros(row['salary'] > 50000 and > row['deptno'] == 10 I'm sorry, why would that not be translated into: lambda row: row['convert_to_euros'](row['salary'] > row['50000'] row['and'] row['deptno'] == row['10'] ? Specifically, how would python know what to dereference and what not to? What if there were two things, named the same, one in the row and one in the namespace? (i.e. a variable named 'salary') How would you escape things which would have been dereferenced but you didn't want to be? (i.e. "rowexpr: convert_to_euros(salary) > salary") I guess I'm kind of wasting my time here, since the introduction of a new keyword for this application really isn't going to happen, based on other decisions I've seen Guido make, but I do think that you need to think a little more about how the implementation of this feature would work. (Or perhaps you've done that thinking, and you just need to fill in the proposal with that information.) Thanks, Blake. From george.sakkis at gmail.com Tue May 29 17:03:38 2007 From: george.sakkis at gmail.com (George Sakkis) Date: Tue, 29 May 2007 11:03:38 -0400 Subject: [Python-ideas] proposal to add rowexpr as a keyword In-Reply-To: <465C3407.6030903@latte.ca> References: <422478.77150.qm@web33501.mail.mud.yahoo.com> <465C3407.6030903@latte.ca> Message-ID: <91ad5bf80705290803l7d6cade1s52ee8eceecc7b985@mail.gmail.com> On 5/29/07, Blake Winton wrote: > Steve Howell wrote: > > Let the Python interpreter build expression objects > > for you. You write: > > rowexpr: convert_to_euros(salary) > 50000 and > > deptno = 10 > > Python translates that into the same bytecode as: > > lambda row: convert_to_euros(row['salary'] > 50000 and > > row['deptno'] == 10 > > I'm sorry, why would that not be translated into: > > lambda row: row['convert_to_euros'](row['salary'] > row['50000'] > row['and'] row['deptno'] == row['10'] > > ? Specifically, how would python know what to dereference and what not > to? What if there were two things, named the same, one in the row and > one in the namespace? (i.e. a variable named 'salary') How would you > escape things which would have been dereferenced but you didn't want to > be? (i.e. "rowexpr: convert_to_euros(salary) > salary") > > I guess I'm kind of wasting my time here, since the introduction of a > new keyword for this application really isn't going to happen, based on > other decisions I've seen Guido make, but I do think that you need to > think a little more about how the implementation of this feature would > work. (Or perhaps you've done that thinking, and you just need to fill > in the proposal with that information.) Indeed, such half baked ideas have no chance of being taken seriously as language additions. Take a look at packages such as buzhug [1] and (especially) SqlAlchemy [2], not only because they might end up solving your problem but also to appreciate the complexity involved in supporting arbitrary SQL-like expressions at the language level, since you clearly underestimate it or haven't quite thought about it. George [1] http://buzhug.sourceforge.net/ [2] http://www.sqlalchemy.org/docs/ -- "If I have been able to see further, it was only because I stood on the shoulders of million monkeys." From stargaming at gmail.com Tue May 29 18:12:23 2007 From: stargaming at gmail.com (Stargaming) Date: Tue, 29 May 2007 18:12:23 +0200 Subject: [Python-ideas] SQL-like way to manipulate Python data structures In-Reply-To: <314501.96528.qm@web33514.mail.mud.yahoo.com> References: <20070528202311.GC18819@panix.com> <314501.96528.qm@web33514.mail.mud.yahoo.com> Message-ID: Steve Howell schrieb: > --- Aahz wrote: > >>What's wrong with sqlite? > > > Nothing, but I want Python itself to give me the SQL > syntax to manipulate lists-of-dictionaries like lists > of dictionaries, without having to go through some a > module. Are there any non-SQL use cases for SQL syntax? And how would all those DBs adapt? With yet another interface? And if you allow me to add, I consider all your examples kinda unpythonic. From jcarlson at uci.edu Tue May 29 18:35:41 2007 From: jcarlson at uci.edu (Josiah Carlson) Date: Tue, 29 May 2007 09:35:41 -0700 Subject: [Python-ideas] dict.fromkeys() better as dict().setkeys() ? (and other suggestions) In-Reply-To: <465BA636.8070501@ronadam.com> References: <20070528174325.86A2.JCARLSON@uci.edu> <465BA636.8070501@ronadam.com> Message-ID: <20070529000414.86A5.JCARLSON@uci.edu> Ron Adam wrote: > Josiah Carlson wrote: > > Ron Adam wrote: > >> The dictionary fromkeys method seems out of place as well as miss-named. IMHO > > > > It is perfectly named (IMNSHO ;), create a dictionary from the keys > > provided; dict.fromkeys() . > > That's ok, I won't hold it against you. ;-) > > What about it's being out of place? Is this case like 'sorted' vs 'sort' > for lists? Sorted returns a list because it is the only mutable ordered sequence in Python, hence the only object that makes sense to return from a sorted function. > >> There are enough correct uses of it in the wild to keep the behavior, but > >> it can be done in a better way. > > > > I wasn't terribly convinced by your later arguments, so I'm -1. > > Yes, I'm not the most influential writer. > > I'm not sure I can convince you it's better if you already think it's not. > That has more to do with your personal preference. So lets look at how > much it's actually needed in the current (and correct) form. [snip] > Is 12 cases out of about 315,000 python files a big enough need to keep the > current behavior? 315,000 is the number returned from google code for all > python files, 'lang:python'. (I'm sure there are some duplicates) > > > Is this more convincing. ;-) Not to me, as I use dict.fromkeys(), and going from a simple expression to an assignment then mutate is unnecessary cognitive load. It would have been more convincing had you offered... dict((i, v) for i in keys) But then again, basically every one of your additions is a one line expression. I would also consider the above myself, if it weren't for the fact that I'm supporting a Python 2.3 codebase. Please see my discussion below of *removing* functionality. > >> I think this reads better and can be used in a wider variety of situations. > >> > >> It could be useful for setting an existing dictionary to a default state. > >> > >> # reset status of items. > >> status.set_keys(status.keys(), v=0) > > > > This can be done today: > > Of course all of the examples I gave can be done today. But they nearly > all require iterating in python in some form. Premature optimization... Note that you don't know where you are getting your data, so the overhead of looping and setting data may be inconsequential to the overall running of the update. Since you basically use the "but it iterates in Python rather than C" for the rest of your arguments, I'm going to stick with my belief that you are prematurely optimizing. Until you can show significant use-cases in the wild, and show that the slowdown of these functions in Python compared to C is sufficient to render the addition of the functions in your own personal library useless, I'm going to stick with my -1. > > status.update((i, 0) for i in status.keys()) > > #or > > status.update(dict.fromkeys(status, 0)) > > The first example requires iterating over the keys. The second example > works if you want to initialize all the keys. In which case, there is no > reason to use the update method. dict.fromkeys(status, 0) is enough. I was pointing out how you would duplicate exactly the functionality you were proposing for dict.set_keys(). It is very difficult for me to offer you alternate implementations for your own use, or as reasons why I don't believe they should be added, if you move the target ;). > >> Or more likely, resetting a partial sub set of the keys to some initial state. > >> > >> > >> The reason I started looking at this is I wanted to split a dictionary into > >> smaller dictionaries and my first thought was that fromkeys would do that. > >> But of course it doesn't. > > > > Changing the bahvior of dict.fromkeys() is not going to happen. We can > > remove it, we can add a new method, but changing will lead to not so > > subtle breakage as people who were used to the old behavior try to use > > the updated method. > > > > Note that this isn't a matter of "it's ok to break in 3.0", because > > dict.fromkeys() is not seen as being a design mistake by any of the > > 'heavy hitters' in python-dev or python-3000 that I have heard (note > > that I am certainly not a 'heavy hitter'). > > Then lets find a different name. Usually we find substantial use-cases for which this new functionality would be useful, _then_ we argue about names (usually for months ;). The only exception to this is in 3rd party modules posted in the cheeseshop, but then we don't usually hash out the details of it here, as it is a 3rd party module. > >> What I wanted was to be able to specify the keys and get the values from > >> the existing dictionary into the new dictionary without using a for loop to > >> iterate over the keys. > >> > >> d = dict(1='a', 2='b', 3='c', 4='d', 5='e') > >> > >> d_odds = d.from_keys([1, 3, 5]) # new dict of items 1, 3, 5 > >> d_evens = d.from_keys([2, 4]) # new dict of items 2, 4 > >> > >> There currently isn't a way to split a dictionary without iterating it's > >> contents even if you know the keys you need before hand. > > > > Um... > > > > def from_keys(d, iterator): > > return dict((i, d[i]) for i in iterator) > > (iterating) > > Yep as I said just above this. > > """There currently isn't a way to split a dictionary without iterating > it's contents ...""" You aren't splitting the dictionary. You are fetching certain values from the dictionary based on the contents of a provided iterator. The *only* thing you gain from the iterator vs. built-in method is a bit of speed. But if speed is your only argument, for a group of functions that I don't remember anyone having ever asked for before, then you better check your rationale. In the standard library there exists the deque type in collections. Why does Python have a deque? Because it was discovered over 10+ years of Python use that pretty much everyone needs a queue, with a large portion of those needing a double ended queue (put the just fetched item back at the front). Because there were so many users, and because it was used in *many* performance critical applications, it was implemented in C by Raymond Hettinger and became the first member of the collections module. A similar thing happened with default dictionaries and it being faked many times by many different people, implemented and tossed into the collections module again. As for iteration over a sequence to generate a new sequence, you need to do this regardless of whether it is in C or Python. The *only* difference between the C and Python versions of this is a difference in speed, but again, use-cases before naming and optimization. I like to see things "in the wild". > Lists have __getslice__, __setslice__, and __delslice__. It could be > argued that those can be handled just as well with iterators and loops as > well. Of course we see them as seq[s:s+x], on both lists and strings. So > why not have an equivalent for dictionaries. We can't slice them, but we > do have key lists to use in the same way. Your function examples are a bit like adding set manipulation functionality through functional programming-like functions. Take your merge operations as an example. With sets, it's spelled s1 | s2. It is a bit round-about, but your from_keys functionality is a bit like s1 - (s1 - s2), or really set(s2) because sets have no associated values. Anyways. > >> A del_keys method could replace the clear method. del_keys would be more > >> useful as it could operate on a partial set of keys. > >> > >> d.delkeys(d.keys()) # The current clear method behavior. > > > > I can't remember ever needing something like this that wasn't handled by > > d.clear() . > > All or nothing. d = dict() works just as well. Not when you want to mutate a dictionary. > And I'd prefer to define the function in this case for readability reasons. > > > >> splitdict(d, keys): > >> """ Split dictionary d using keys. """ > >> keys_rest = set(d.keys()) - set(keys) > >> return d.from_keys(keys), d.from_keys(keys_rest) > > > > I can't think of a simple one-liner for this one that wouldn't duplicate > > work. > > :-) > > This is one of the main motivators. I've never needed to do this. And I've never seen source that needed to do this either. So whether this is a main motivator for you doesn't sway me. [snip your pointing out that iteration happens in Python and not C] > >> I think the set_keys, from_keys, and del_keys methods could add both > >> performance and clarity benefits to python. > > > > Performance, sometimes, for some use-cases. Clarity? Maybe. Your > > split* functions are a bit confusing to me, and I've never really needed > > any of the functions that you list. > > I think sometime our need is determined by what is available for use. So > if it's not available, our minds filter it out from the solutions we > consider. That way, we don't need the things we don't have or can't get. > > My minds "need filter" seems to be broken in that respect. I often need > things I don't have. But sometimes that works out to be good. ;-) Yeah, I don't buy your 'need filter' reasoning. Typically people resist doing things that are difficult or inconvenient to do. Take decoration for example. Before decorator syntax, decoration was a pain in the butt. Yeah, you wrote the same number of lines of code, but there was such a disconnect from the signature of the function/method (and class in 2.6) that it was just too inconvenient to write, maintain, and understand. In the case of dictionaries, all but two or three of the things you would like to offer is available via a very simple dict(generator expression). If people aren't thinking of ways to use generator expressions to make their lives easier (this is the case in multiple threads daily in comp.lang.python), is that Python's fault, or is it the developer's? I like to think of Python's syntax and semantics as just rich enough for people to write what they want and to understand it quickly, but not so rich that you need to spend time thinking what something means (the Perl argument). Adding functionality to existing objects needs to do a few things, not the least of which is solving a problem that happens in the wild, but also that it doesn't overly burdon those who implement similar functionality. Remember, dictionaries are *the* canonical mapping interface, and anyone who implements a complete mapping interface necessarily would need to implement the 3 methods you propose. For what? To clean up the interface? I'm sorry, but to add 3 methods, even with the assmuption that two previous methods were going to be removed, in order to "clean up" the interface doesn't convince me. Please find me real-world use-cases where your new methods would improve readability. ... Also, I develop software for fun and profit. Since basically everyone else here probably does some selection of the same, I'm sure that they will tell you pretty much the same thing: if we restricted our needs to what we already have, software wouldn't get written, or would only be proposed by marketing. > >> So to summarize... > >> > >> 1. Replace existing fromkeys method with a set_keys method. > >> 2. Add a partial copy items from_keys method. > >> 3. Replace the clear method with a del_keys method. > > > > Not all X line functions should be builtins. > > Of course I knew someone would point this out. I'm usually the one to invoke it. Maybe I have less tolerance to arguably trivial additions to Python than others. > I'm not requesting the > above example functions be builtins. Only the changes to the dict methods > be considered. They would allow those above functions to work in a more > efficient way and I'd be happy to add those functions to my own library. > > With these methods in most cases the functions wouldn't even be needed. > You would just use the methods in combinations with each other directly and > the result would still be readable without a lot of 'code' overhead. My single expression replacements were to show that the functions aren't needed now, as most are *easily* implemented in Python 2.5 in a straightforward manner. > Also consider this from a larger view. List has __getslice__, > __setslice__, and __delslice__. Set has numerous methods that operate on > more than one element. Lists are ordered sequences, dictionaries are not. Sets are not mappings, they are sets (which is why they have set operations). Dictionaries are a mapping from keys to values, used as both an arbitrary data store as well as data and method member lookups on objects. The most common use-cases of dictionaries *don't* call for any of the additional functionality that you have offered. If they did, then it would have already been added. > Dictionaries are suppose to be highly efficient, but they only have limited > methods that can operate on more than one item at a time, so you end up > iterating over the keys to do nearly everything. Iteration is a fundamental building block in Python. That's why for loops, iterators, generators, generator expressions, list comprehensions, etc., all use iteration over an iterator to do their work. Building more functionality into dictionaries won't make them easier to use, it will merely add more methods that you think will help. Is there anyone else who likes this idea? Please speak up. > So as an alternative, leave fromkeys and clear alone and add... > > getkeys(keys) -> dict > setkeys(keys, v=None) > delkeys(keys) > > Where these offer the equivalent of list slice functionality to dictionaries. getkeys/setkeys/delkeys seem to me like they should be named getitems/setitems/delitems, because they are getting/setting/deleting the entire key->value association, not merely the keys. > > If you find that you are > > doing the above more often than you think you should, create a module > > with all of the related functionality that automatically patches the > > builtins on import and place it in the Python cheeseshop. If people > > find that the functionality helps them, then we should consider it for > > inclusion. As it stands, most of the methods you offer have a very > > simple one-line version that is already very efficient. > > Iterators and for loops are fairly efficient for small dictionaries, but > iterating can still be considerable slower than the equivalent C code if > they are large dictionaries. Lets find out. >>> d = dict.fromkeys(xrange(10000000)) >>> import time >>> if 1: ... t = time.time() ... e = dict(d) ... print time.time()-t ... 1.21899986267 >>> del e >>> if 1: ... t = time.time() ... e = dict(d.iteritems()) ... print time.time()-t ... 2.75 >>> del e >>> if 1: ... t = time.time() ... e = dict((i,j) for i,j in d.iteritems()) ... print time.time()-t ... 6.95399999619 >>> del e >>> if 1: ... t = time.time() ... e = dict((i, d[i]) for i in d) ... print time.time()-t ... 7.54699993134 >>> Those all seem to be pretty reasonable timings to me. In the best case you are talking about 6.2 times faster to use the C rather than Python version. > >> So this replaces two methods and adds one more. Overall I think the > >> usefulness of these would be very good. > > > > I don't find the current dictionary API to be lacking in any way other > > than "what do I really need to override to get functionality X", but > > that is a documentation issue more than anything. > > >> I also think it will work very well with the python 3000 keys method > >> returning an iterator. (And still be two fewer methods than we currently > >> have.) > > > > I'm sorry, but I can't really see how your changes would add to Python's > > flexibility without cluttering up interfaces and confusing current users. > > I think it cleans up the API more than it clutters it up. It coverts two > limited use methods to be more general, and adds one more that works with > the already existing update method nicely. But you propose a further half dozen functions. If you aren't proposing them for inclusion, why bother including them in your proposal, especially when they have very simple replacements that are, arguably, easier to understand than the function bodies you provided. > In both cases of the two existing methods, fromkeys and clear, your > arguments, that there all ready exists easy one line functions to do this, > would be enough of a reason to not have them in the first place. So do you > feel they should be removed? We don't remove functionality in Python unless there is a good reason. Typically that reason is because the functionality is broken, the old functionality is not considered "Pythonic", or generally because a group of people believe there is a better way. Guido is more or less happy with dictionaries as-is (except for the keys(), values(), and items() methods, which are changing), and no one in python-dev has complained about dictionary functionalty that I can remember. As such, even if you think that your changes would clean up dictionary methods, it is unlikely to happen precisely because *others* aren't mentioning, "dictionaries need to be cleaned up". > I plan on doing a search of places where these things can make a difference > in making the code more readable and/or faster. I don't care about faster. Show me code that is easier to understand. I will mention that all of your functionality smells very much like a functional programming approach to Python. This makes a difference because some functional programming tools (reduce, map, filter, ...) are slated for removal in Python 3.0, so adding functional programming tools (when we are removing others), is unlikely to gain much traction. - Josiah From jimjjewett at gmail.com Tue May 29 20:23:55 2007 From: jimjjewett at gmail.com (Jim Jewett) Date: Tue, 29 May 2007 14:23:55 -0400 Subject: [Python-ideas] dict.fromkeys() better as dict().setkeys() ? (and other suggestions) In-Reply-To: <20070529000414.86A5.JCARLSON@uci.edu> References: <20070528174325.86A2.JCARLSON@uci.edu> <465BA636.8070501@ronadam.com> <20070529000414.86A5.JCARLSON@uci.edu> Message-ID: On 5/29/07, Josiah Carlson wrote: > Ron Adam wrote: > > Josiah Carlson wrote: > > > dict.fromkeys() is not seen as being a design mistake ermm.... I think at least a few see it as something of a leftover, for using dicts as sets. The docs also (weakly) support this view. This isn't quite the only use case, but I doubt fromkeys would be added today (given both sets and subclasses of defaultdict); there just isn't quite enough discomfort to remove it. > > >> splitdict(d, keys): > > >> """ Split dictionary d using keys. """ > > >> keys_rest = set(d.keys()) - set(keys) > > >> return d.from_keys(keys), d.from_keys(keys_rest) > > > I can't think of a simple one-liner for this one that wouldn't > > > duplicate work. *this* is the core of a useful idea. list (and set and generator) comprehensions can't partition very well, because they have only a single output. There isn't a good way to say: list_a = [x for x in src if pred(a)] src = [x for x in src if not pred(a)] list_b = [x for x in src if pred(b)] src = [x for x in src if not pred(b)] list_c = [x for x in src if pred(c)] list_other = [x for x in src if not pred(c)] On the other hand, you can do it (inefficiently) as above, or you can write an (ugly) version using a custom function, so the solution would have to be pretty good before it justified complicating the comprehension APIs. > unlikely to happen precisely because *others* aren't mentioning, > "dictionaries need to be cleaned up". Not in so many words; Raymond is very reluctant to add anything, because the API is already fairly large. Guido's ABC for mappings (http://svn.python.org/view/sandbox/trunk/abc/) is explicitly a small subset of what dict offers (and doesn't include fromkeys). That said, saying "too large, this isn't needed" is still a far cry from "so we'll remove it", let alone "and add this stuff to replace it". -jJ From rrr at ronadam.com Tue May 29 22:21:05 2007 From: rrr at ronadam.com (Ron Adam) Date: Tue, 29 May 2007 15:21:05 -0500 Subject: [Python-ideas] Dictionary group key/value modificaton methods. In-Reply-To: <20070529000414.86A5.JCARLSON@uci.edu> References: <20070528174325.86A2.JCARLSON@uci.edu> <465BA636.8070501@ronadam.com> <20070529000414.86A5.JCARLSON@uci.edu> Message-ID: <465C8B31.4080805@ronadam.com> Ok, I'm going to try to summarize this a bit so we don't go around in circles on details that are adjacent to the issue I'm trying to address. + Adding methods to "copyitems", "seteach", and "delitems"; to do partial group operations on dictionaries in C rather than iterating in python can possibly have as much as a %500 percent performance increase over iterating in python to do the same thing. - It needs to be shown that these situations occur often enough to result in a meaningful benefit. (It doesn't replace the need to iterate dictionaries as there are many cases where that's exactly what you need.) + The methods add some improvements to readability over the iterator form. - There is not a significant reduction in lines of code, so again it needs to be shown that this would be useful often enough to be a significant benefit. Providing there are enough use cases to demonstrate a significant benefit, we will then need to address the following issues. + What to call them. + The details of the implementation. Most of the arguments against fit into the following categories... - Changes the status quo - It's premature optimization - Adds additional complexity to dictionaries - Personal preference These are subjective but still important issues, and these will need to be addressed after it is demonstrated there is sufficient use cases for these features, if each of these is relevant and to what degree. Some examples: # Combine two dictionaries. (works already) dd = dict(d1) dd.update(d2) # Split dictionary d using a key list. keys_rest = set(d.keys()) - set(keys) d1, d2 = d.getitems(keys), d.getitems(keys_rest) # Remove a subdict of d with keys. dd = d.getitems(keys) d.delitems(keys) # Copy items from dictionary d1 to d2. # # The getitems method returns a dictionary so it will # work directly with the update method. # d2.update(d1.getitems(keys)) # Move items from dictionary d1 to d2. d2.update(d1.getitems(keys)) d1.del_keys(keys) # Setting items to a specified value with a list of keys. d.seteach(keys, None) Use cases: ### TODO >> Josiah Carlson wrote: >>> Ron Adam wrote: >> Is 12 cases out of about 315,000 python files a big enough need to keep the >> current behavior? 315,000 is the number returned from google code for all >> python files, 'lang:python'. (I'm sure there are some duplicates) >> >> Is this more convincing. ;-) > > Not to me, as I use dict.fromkeys(), and going from a simple expression > to an assignment then mutate is unnecessary cognitive load. It would > have been more convincing had you offered... > > dict((i, v) for i in keys) Well, there you go. :-) > But then again, basically every one of your additions is a one line > expression. I would also consider the above myself, if it weren't for > the fact that I'm supporting a Python 2.3 codebase. Please see my > discussion below of *removing* functionality. This is probably something that is better suited for python 3000. But it's possible it could be back ported to 2.6. It would have no effect on python 2.5 and earlier. And probably minimal effect on 2.x in regards to 2.3 compatibility. I don't see .fromkeys() being removed in 2.x. > Until you can show significant use-cases in the > wild, and show that the slowdown of these functions in Python compared > to C is sufficient to render the addition of the functions in your own > personal library useless, I'm going to stick with my -1. Your own tests show a maximum speedup of 620%. My testing shows it is 300% to 500% over a range of sizes. I would still call that sufficient. And before you point it out... yes, only if it can be shown to be useful in a wide range of situations. I fully intend to find use cases. If I can't find any, then none of this will matter. > I was pointing out how you would duplicate exactly the functionality you > were proposing for dict.set_keys(). It is very difficult for me to > offer you alternate implementations for your own use, or as reasons why > I don't believe they should be added, if you move the target ;). But programming is full of moving targets. ;-) In any case, look at the overall picture and try not to prematurely shoot this down based on implementation details that can be changed as needed. And I'll attempt to do a use case study from the python library. > Until you can show significant use-cases > Usually we find substantial use-cases .... > ... that I don't remember anyone having ever asked for before > ... but again, use-cases ... > I've never needed to do this. > Please find me real-world use-cases ... > Show me code that is easier to understand. Ok, I get it. :-) >> Also consider this from a larger view. List has __getslice__, >> __setslice__, and __delslice__. Set has numerous methods that operate on >> more than one element. > > Lists are ordered sequences, dictionaries are not. Sets are not > mappings, they are sets (which is why they have set operations). > Dictionaries are a mapping from keys to values, used as both an > arbitrary data store as well as data and method member lookups on > objects. The most common use-cases of dictionaries *don't* call for any > of the additional functionality that you have offered. > If they did, then it would have already been added. This statement isn't true. It only shows the resistance to these changes is greater than the efforts of those who have tried to introduce those changes. (not without good cause) To be clear, I in no way want the bar dropped to a lower level as to what is added to python or not added. I accept that sufficient benefit needs to be demonstrated, and will try to do that. Quality is more important than quantity in this case. >> Dictionaries are suppose to be highly efficient, but they only have limited >> methods that can operate on more than one item at a time, so you end up >> iterating over the keys to do nearly everything. > > Iteration is a fundamental building block in Python. That's why for > loops, iterators, generators, generator expressions, list comprehensions, > etc., all use iteration over an iterator to do their work. Building > more functionality into dictionaries won't make them easier to use, it > will merely add more methods that you think will help. Is there anyone > else who likes this idea? Please speak up. Lets rephrase this to be less subjective... Does anyone think having a approximately 500% improvement in some dictionary operations would be good if it can be done in a way that is both easier to read, use, and has enough use cases to be worth while? > getkeys/setkeys/delkeys seem to me like they should be named > getitems/setitems/delitems, because they are getting/setting/deleting the > entire key->value association, not merely the keys. Sounds good, how about... getitems, delitems, and seteach ? The update method corresponds to setitems, where setitems is the inverse operations to getitems. I don't see any reason to change update. d1.update(d2.getitems(keys)) So seteach, is a better name for a method that sets each key to a value. Cheers, Ron From showell30 at yahoo.com Tue May 29 23:28:11 2007 From: showell30 at yahoo.com (Steve Howell) Date: Tue, 29 May 2007 14:28:11 -0700 (PDT) Subject: [Python-ideas] SQL-like way to manipulate Python data structures In-Reply-To: Message-ID: <420674.70880.qm@web33510.mail.mud.yahoo.com> --- Stargaming wrote: > > Are there any non-SQL use cases for SQL syntax? Isn't that kind of a silly question? Of course not. SQL syntax only applies to relational data. Of course, such data doesn't have to exist in a "database" for the syntax to be useful. It just has to be relational. I would ask the opposite question--are there any cases where you manipulate basically relational data without the power of SQL? There are many answers there, and one them is Python. ____________________________________________________________________________________ Park yourself in front of a world of choices in alternative vehicles. Visit the Yahoo! Auto Green Center. http://autos.yahoo.com/green_center/ From showell30 at yahoo.com Tue May 29 23:38:17 2007 From: showell30 at yahoo.com (Steve Howell) Date: Tue, 29 May 2007 14:38:17 -0700 (PDT) Subject: [Python-ideas] proposal to add rowexpr as a keyword In-Reply-To: <465C3407.6030903@latte.ca> Message-ID: <642129.84253.qm@web33511.mail.mud.yahoo.com> Guys, please don't judge me too harshly on the basis of a quick sketch of an idea. I'm obviously skimming over a lot of ideas in a quick pass. FWIW I've built virtual machines before, and way back I worked at Oracle and at times had to debug their PL/SQL implementation, so it's not like I don't understand what I'm asking for. I am also fully aware of Python's culture and have fought against frivolous language additions myself, although I'm biased like everybody else by own experience, so one person's frivolous is another person's can't-live-without-it. I will respond to the main technical objection--how to scope these--in a separate reply. Thanks. ____________________________________________________________________________________Be a better Globetrotter. Get better travel answers from someone who knows. Yahoo! Answers - Check it out. http://answers.yahoo.com/dir/?link=list&sid=396545469 From showell30 at yahoo.com Tue May 29 23:55:07 2007 From: showell30 at yahoo.com (Steve Howell) Date: Tue, 29 May 2007 14:55:07 -0700 (PDT) Subject: [Python-ideas] proposal to add rowexpr as a keyword In-Reply-To: <465C3407.6030903@latte.ca> Message-ID: <777248.90724.qm@web33511.mail.mud.yahoo.com> --- Blake Winton wrote: > Steve Howell wrote: > > Let the Python interpreter build expression > objects > > for you. You write: > > rowexpr: convert_to_euros(salary) > 50000 and > > deptno = 10 > > Python translates that into the same bytecode as: > > lambda row: convert_to_euros(row['salary'] > 50000 > and > > row['deptno'] == 10 > My language here was imprecise. I should have said something to the effect of this: The interpreter would translate the "rowexpr" into bytecode that would execute the same way as the "lambda" example given the scope of the method convert_to_euros in the example above. Also, the bytecode would not be the "same" as the lambda; it would just have similar complexity. > I'm sorry, why would that not be translated into: > > lambda row: row['convert_to_euros'](row['salary'] > > row['50000'] > row['and'] row['deptno'] == row['10'] > I am suggesting that in a rowexpr expression, instead of the typical local scope being the default scope, "row" would be the local scope for dereferencing. Since I am proposing an expression syntax, does not the local scope go away? If you look at where salary, row, and deptno sit in the expression, it seems pretty clear to me that a well-defined scoping scheme would try to dereference row by default for all those tokens, and probably give up there, throwing an exception. The convert_to_euros token in the expression obviously poses a thornier problem. Do you prefer row.convert_to_euros, if such a think exists, or do you go right to what would be the typical scope of a similar lambda expression, and prefer, say, the definition of "def convert_to_euros" that sits at the module level? I would think the latter. The interpreter surely can evaluate such an expression and determine that convert_to_euros is going to be used a callable. Now, whether convert_to_euros is actually callable at run time is another story, but if it isn't, an exception is thrown, and at least you're not debugging somebody else's library to figure out why. Python would just tell you. I don't mean to oversimplify this, which is why I'm batting it around on a forum with a lot of smart people. But clearly it could be done. Whether it *should* be done is, of course, a question for debate, and I accept this. ____________________________________________________________________________________Be a better Globetrotter. Get better travel answers from someone who knows. Yahoo! Answers - Check it out. http://answers.yahoo.com/dir/?link=list&sid=396545469 From showell30 at yahoo.com Wed May 30 00:05:50 2007 From: showell30 at yahoo.com (Steve Howell) Date: Tue, 29 May 2007 15:05:50 -0700 (PDT) Subject: [Python-ideas] SQL-like way to manipulate Python data structures In-Reply-To: Message-ID: <201431.56993.qm@web33507.mail.mud.yahoo.com> --- Stargaming wrote: > Steve Howell schrieb: > > --- Aahz wrote: > > > >>What's wrong with sqlite? > > > > > > Nothing, but I want Python itself to give me the > SQL > > syntax to manipulate lists-of-dictionaries like > lists > > of dictionaries, without having to go through some > a > > module. > > And how would all those DBs adapt? With yet another > interface? Where did I ever propose eliminating the interfaces that DB adapters already have? Or where did I propose any requirement to interface to the SQL syntax? The DB adapters would continue to move data from external/local databases to lists-of-dictionaries, objects, etc., as they do now. I'm just saying that once you pull data into Python, you should continue to have the option to manipulate relational data with SQL. Presumbably most people who use SQL databases already have to understand the syntax anyway. And those that don't can simply ignore it. ____________________________________________________________________________________ Moody friends. Drama queens. Your life? Nope! - their life, your story. Play Sims Stories at Yahoo! Games. http://sims.yahoo.com/ From jcarlson at uci.edu Wed May 30 00:41:40 2007 From: jcarlson at uci.edu (Josiah Carlson) Date: Tue, 29 May 2007 15:41:40 -0700 Subject: [Python-ideas] proposal to add rowexpr as a keyword In-Reply-To: <777248.90724.qm@web33511.mail.mud.yahoo.com> References: <465C3407.6030903@latte.ca> <777248.90724.qm@web33511.mail.mud.yahoo.com> Message-ID: <20070529152310.86AF.JCARLSON@uci.edu> Steve Howell wrote: > I don't mean to oversimplify this, which is why I'm > batting it around on a forum with a lot of smart > people. But clearly it could be done. Whether it > *should* be done is, of course, a question for debate, > and I accept this. You are proposing to insert a mini-language into Python so as to make certain relational data processing tasks easier. As you say, your particular proposal is pretty much just an alias for lambda where you don't specify the 'row' argument, names are acquired from the passed dictionary, and maybe you get some free enclosing scope goodies. Honestly, without explicit stating of where data is coming from, either via row['column'] or row.column, and the explicit naming of the argument to be passed (as in lambda argument: expression), it smells far too magical for Python. Never mind the fact that you will tend to get better performance by not using a lambda/your hacked lambda, as the direct execution will have fewer function calls... That is... pred = lambda row: (convert_to_euros(row['salary']) > 50000 and row['deptno'] == 10) a = [f(i) for i in rows if pred(i)] will run slower than b = [f(i) for i in rows if convert_to_euros(row['salary']) > 50000 and row['depno'] == 10] While the former *may* be easier to read (depending on who you are), the latter will be faster in all cases. The only way for the pred() version to be faster is if your rowexpr: variant was actually a macro expansion, but we don't do macro expansions in Python, so it will be slower. So, what do we have? Possible minor clarity win (but certainly not over lambdas), small length reduction over lambdas, slower execution compared to inlining the code (equal to lambda), more syntax. Put me down for -1. - Josiah From scott+python-ideas at scottdial.com Wed May 30 00:38:56 2007 From: scott+python-ideas at scottdial.com (Scott Dial) Date: Tue, 29 May 2007 18:38:56 -0400 Subject: [Python-ideas] SQL-like way to manipulate Python data structures In-Reply-To: <201431.56993.qm@web33507.mail.mud.yahoo.com> References: <201431.56993.qm@web33507.mail.mud.yahoo.com> Message-ID: <465CAB80.2020606@scottdial.com> Steve Howell wrote: > Presumbably most people who use SQL databases > already have to understand the syntax anyway. And > those that don't can simply ignore it. That simply will never be true. If there is new syntax added to Python, than the burden is on everyone to understand other people's code that uses such a feature. I'm very familiar with SQL and I am still not convinced that I want to see it in my Python. First of all, the concept of a relational table is ill-defined. I gather from your code that you believe this to be a list containing dictionaries, but why could this not be a tuple of tuples? For that matter, any iterable of iterables? Or how about using tuple'd indices, and so on.. It would be impossible to graft the SQL language onto all of the variations on the idea of a "table" in Python. Python does not have a relational table data structure, thus there cannot be a relational language used to address such a structure. It would not be wise to create a syntax that relies on a particular composition of data structures. -- Scott Dial scott at scottdial.com scodial at cs.indiana.edu From showell30 at yahoo.com Wed May 30 01:24:39 2007 From: showell30 at yahoo.com (Steve Howell) Date: Tue, 29 May 2007 16:24:39 -0700 (PDT) Subject: [Python-ideas] proposal to add rowexpr as a keyword In-Reply-To: <20070529152310.86AF.JCARLSON@uci.edu> Message-ID: <348829.53748.qm@web33502.mail.mud.yahoo.com> Josiah wrote: http://mail.python.org/pipermail/python-ideas/2007-May/000835.html Josiah, you are correct about all the following, and I apologize for any incorrect paraphrase: 1) I am proposing to add a mini-language within Python. 2) I want relational data processing tasks to be easier within Python. 3) I want rowexpr to acquire names from the passed first argument (with sensible scoping rules, of course). 4) Point #4 essentially amounts to free enclosing scope goodies. 5) My proposal does indeed smell of magic. 6) I do want the code to be easier to read for me (with the full caveat that YMMV). 7) I want the small clarity win. 8) I think the only way to achieve this particular clarity win is to add syntax. You may be incorrect about the following, or I may just be understanding your points, but I'm not wrong about any of these, since I'm just characterizing my own feelings: 1) I don't want rowexpr to be pretty much an alias for lambda; I actually want it to be more powerful. 2) I'm not sweating performance here; I'm already using an interpreted language. I don't want Python to be faster for my day-to-day tasks; I want it to be more expressive. I even--and I'll dare say--want the language to be BIGGER. 3) I'm not ignorant of the resistance to macro expansions in Python, but I do think a year-2010 Python interpreter could compile SQL syntax directly into bytecode. ____________________________________________________________________________________Be a better Globetrotter. Get better travel answers from someone who knows. Yahoo! Answers - Check it out. http://answers.yahoo.com/dir/?link=list&sid=396545469 From showell30 at yahoo.com Wed May 30 01:39:12 2007 From: showell30 at yahoo.com (Steve Howell) Date: Tue, 29 May 2007 16:39:12 -0700 (PDT) Subject: [Python-ideas] proposal to add rowexpr as a keyword In-Reply-To: <348829.53748.qm@web33502.mail.mud.yahoo.com> Message-ID: <496892.28622.qm@web33501.mail.mud.yahoo.com> --- Steve Howell wrote: > 3) I want rowexpr to acquire names from the passed > first argument (with sensible scoping rules, of > course). > 4) Point #4 essentially amounts to free enclosing > scope goodies. er, point #3 > > You may be incorrect about the following, or I may > just be understanding your points [...] er, s/understanding/misunderstanding/ That wasn't a Freudian slip. See careless typing above (where I disrespectfully agree with you ;) ____________________________________________________________________________________Get the Yahoo! toolbar and be alerted to new email wherever you're surfing. http://new.toolbar.yahoo.com/toolbar/features/mail/index.php From showell30 at yahoo.com Wed May 30 02:23:18 2007 From: showell30 at yahoo.com (Steve Howell) Date: Tue, 29 May 2007 17:23:18 -0700 (PDT) Subject: [Python-ideas] SQL-like way to manipulate Python data structures In-Reply-To: <465CAB80.2020606@scottdial.com> Message-ID: <431939.73532.qm@web33502.mail.mud.yahoo.com> --- Scott Dial wrote: > Steve Howell wrote: > > Presumbably most people who use SQL databases > > already have to understand the syntax anyway. And > > those that don't can simply ignore it. > > That simply will never be true. If there is new > syntax added to Python, > than the burden is on everyone to understand other > people's code that > uses such a feature. I'm very familiar with SQL and > I am still not > convinced that I want to see it in my Python. I fully concede to working under the premise that most Python programmers know SQL, and you're a perfect example, I guess, but I realize there are exceptions, and I don't deny that as a tradeoff, just like I don't deny that any expansion of a language's functionality reduces comprehension for average users. Written any decorators lately? > First > of all, the concept > of a relational table is ill-defined. > SQL's been around for at least 20 years, as has the concept of a relational table. So it's not exactly ill-defined. Start here, if you disagree: http://en.wikipedia.org/wiki/Relational_model > I gather from your code that you believe this to be > a list containing > dictionaries, but why could this not be a tuple of > tuples? In the code that I posted, I don't "believe" that I'm dealing with a list of dictionaries, I "know" because I wrote it. You can check it out yourself. But I agree with your implied premise that the Python interpreter doesn't know what it's dealing with, and I fully accept in my proposal that Python, not some third-party library, would properly throw an exception when it found my data not to fit the relational model, just as generator expressions sometimes throw run-time expressions, just as lambdas throw run-time expressions, etc. I'm ok with that. > For that > matter, any iterable of iterables? Or how about > using tuple'd indices, > and so on.. It would be impossible to graft the SQL > language onto all of > the variations on the idea of a "table" in Python. > I'm not proposing to graft SQL on to all variations of the "table" in Python, just the ones that conform to a relational model. > Python does not have a relational table data > structure, thus there > cannot be a relational language used to address such > a structure. Python certainly expresses data structures that don't fit the relational model, but please explain to me how a list of dictionaries doesn't fit the relational model. And don't bore me with the explanation that dictionaries can be heterogeneous; I'd just have Python throw an exception there. ____________________________________________________________________________________ Expecting? Get great news right away with email Auto-Check. Try the Yahoo! Mail Beta. http://advision.webevents.yahoo.com/mailbeta/newmail_tools.html From jcarlson at uci.edu Wed May 30 02:31:40 2007 From: jcarlson at uci.edu (Josiah Carlson) Date: Tue, 29 May 2007 17:31:40 -0700 Subject: [Python-ideas] proposal to add rowexpr as a keyword In-Reply-To: <348829.53748.qm@web33502.mail.mud.yahoo.com> References: <20070529152310.86AF.JCARLSON@uci.edu> <348829.53748.qm@web33502.mail.mud.yahoo.com> Message-ID: <20070529165018.86B2.JCARLSON@uci.edu> Steve Howell wrote: > Josiah wrote: > You may be incorrect about the following, or I may > just be understanding your points, but I'm not wrong > about any of these, since I'm just characterizing my > own feelings: > > 1) I don't want rowexpr to be pretty much an alias > for lambda; I actually want it to be more powerful. Technically speaking, lambda is sufficient for turing completeness, so the only thing to be gained is a reduction in what you write. As you offer... predicate = rowexpr: manipulation(column1) > value1 and \ column2 < value2 predicate = lambda row: manipulation(row['column1']) > value1 and \ row['column2'] < value) Is that reduction worthwhile? I personally don't think so, but my list comprehensions tend to have fairly minimal predicates. One thing to take into consideration is that Guido has previously shot down 'order by' syntax in list comprehensions and generator expressions because he didn't think that they were Pythonic (I seem to remember 'ugly' and 'worthless', but maybe that was my response to them). > 2) I'm not sweating performance here; I'm already > using an interpreted language. I don't want Python to > be faster for my day-to-day tasks; I want it to be > more expressive. I even--and I'll dare say--want the > language to be BIGGER. That's fine, but realize that Python 3.0 is moving towards a smaller, clearer language; see the dictionary changes, range/xrange, exception handling, etc. > 3) I'm not ignorant of the resistance to macro > expansions in Python, but I do think a year-2010 > Python interpreter could compile SQL syntax directly > into bytecode. It could, but I would happily bet you $100 that it won't. If you are really intent on getting this, despite the arguments against it (from everyone so far), you could add your own syntax with logix, which will handle arbitrary SQL statement and compile it into Python bytecode (given sufficient information on how to do so). Yes, that's a cop-out, but sometimes the only way people get the language that they want is if they can add syntax at their whim. I've personally found that while I disagree with Guido on very many things related to Python, I'm usually too lazy to bother to add syntax I think I may need when I'm able to (with very minimal effort) write a helper function or two to do basically everything I need in lieu of syntax. - Josiah From showell30 at yahoo.com Wed May 30 02:43:35 2007 From: showell30 at yahoo.com (Steve Howell) Date: Tue, 29 May 2007 17:43:35 -0700 (PDT) Subject: [Python-ideas] proposal to add rowexpr as a keyword In-Reply-To: <20070529165018.86B2.JCARLSON@uci.edu> Message-ID: <446905.76199.qm@web33503.mail.mud.yahoo.com> --- Josiah Carlson wrote: > Technically speaking, lambda is sufficient for > turing completeness [...] ...as is Perl, or machine code, to pick sort of opposite ends of the spectrum :) > Is that reduction worthwhile? I personally don't > think so, but my list > comprehensions tend to have fairly minimal > predicates. One thing to > take into consideration is that Guido has previously > shot down 'order by' > syntax in list comprehensions and generator > expressions because he > didn't think that they were Pythonic (I seem to > remember 'ugly' and > 'worthless', but maybe that was my response to > them). > :) I am only expressing my own aesthetics, and I would certainly defer to Guido on most matters aesthetic, since he's written an aesthetically beautiful language. But having said that, I don't want my proposal automatically lumped in with every proposal that Guido has found unaesthetic, or rejected, and I believe he has even been known to change his mind from time to time. For all the real-world warts of SQL, I think SQL is a very aesthetically pleasing way to express transformations of relational data structures, and Python contains relational data structures, and therefore I think Python can benefit from using SQL as just one way of expressing relational transformations (and I'm still a little bit TIMTOWTDI from my Perl days, I fully admit). I fully concede all the obvious objections--more syntax, more ways to do it, difficulty of implementing it within the VM, ability of people to already manipulate relational data structures more cleanly than me in Python, etc. I'm not asking for this in Fall 2007, BTW, I'm expressing this as a vision for a bigger, better Python, maybe year 2010, even though smaller is usually better. And syntactically, I am only extending the language by one keyword, or one new way of triple-quoting. For my own use, native SQL would benefit the clarity of my (already working, but sometimes ugly) code more than some other additions proposed in Py3k, but YMMV. ____________________________________________________________________________________ Finding fabulous fares is fun. Let Yahoo! FareChase search your favorite travel sites to find flight and hotel bargains. http://farechase.yahoo.com/promo-generic-14795097 From aahz at pythoncraft.com Wed May 30 02:49:51 2007 From: aahz at pythoncraft.com (Aahz) Date: Tue, 29 May 2007 17:49:51 -0700 Subject: [Python-ideas] proposal to add rowexpr as a keyword In-Reply-To: <446905.76199.qm@web33503.mail.mud.yahoo.com> References: <20070529165018.86B2.JCARLSON@uci.edu> <446905.76199.qm@web33503.mail.mud.yahoo.com> Message-ID: <20070530004951.GA17586@panix.com> On Tue, May 29, 2007, Steve Howell wrote: > > For all the real-world warts of SQL, I think SQL is a very > aesthetically pleasing way to express transformations of relational > data structures, and Python contains relational data structures, and > therefore I think Python can benefit from using SQL as just one way > of expressing relational transformations (and I'm still a little bit > TIMTOWTDI from my Perl days, I fully admit). Aside from the standard featuritis objection, my objection stems almost entirely from the difficulty of defining appropriate data structures on which to operate. SQL works partly because data in SQL tables is already *by definition* in a relational format -- which won't be true in Python, causing all kinds of runtime errors that IMO are inappropriate for SQL. -- Aahz (aahz at pythoncraft.com) <*> http://www.pythoncraft.com/ "as long as we like the same operating system, things are cool." --piranha From showell30 at yahoo.com Wed May 30 02:58:28 2007 From: showell30 at yahoo.com (Steve Howell) Date: Tue, 29 May 2007 17:58:28 -0700 (PDT) Subject: [Python-ideas] proposal to add rowexpr as a keyword In-Reply-To: <20070529165018.86B2.JCARLSON@uci.edu> Message-ID: <711641.42448.qm@web33506.mail.mud.yahoo.com> --- Josiah Carlson wrote: > It could, but I would happily bet you $100 that it > won't. Maybe not by 2010, but I'll make a gentlemen's bet that native SQL is in Python by 2005. > If you are > really intent on getting this, despite the arguments > against it (from > everyone so far), you could add your own syntax with > logix, which will > handle arbitrary SQL statement and compile it into > Python bytecode > (given sufficient information on how to do so). Ok, the logix approach to introducing new syntax is good to know. I thought my pain would at least resonate with a few people, but it obviously has not so far. > Yes, that's a cop-out, but sometimes the only way > people get the > language that they want is if they can add syntax at > their whim. I've > personally found that while I disagree with Guido on > very many things > related to Python, I'm usually too lazy to bother to > add syntax I think > I may need when I'm able to (with very minimal > effort) write a helper > function or two to do basically everything I need in > lieu of syntax. > As I said in another reply, I have working code, so I don't NEED the syntax, just want it, think it's a good idea, and I hope I've picked the correct forum in expressing a sort of wouldn't-it-be-great-if-Python-did-this suggestion. My progression in programming has always been to think that the current paradigm was brilliant (even in my C++ days!), and then only to discover there were even better paradigms. ____________________________________________________________________________________Yahoo! oneSearch: Finally, mobile search that gives answers, not web links. http://mobile.yahoo.com/mobileweb/onesearch?refer=1ONXIC From showell30 at yahoo.com Wed May 30 03:00:02 2007 From: showell30 at yahoo.com (Steve Howell) Date: Tue, 29 May 2007 18:00:02 -0700 (PDT) Subject: [Python-ideas] proposal to add rowexpr as a keyword Message-ID: <180820.85412.qm@web33509.mail.mud.yahoo.com> --- Steve Howell wrote: > > --- Josiah Carlson wrote: > > It could, but I would happily bet you $100 that it > > won't. > > Maybe not by 2010, but I'll make a gentlemen's bet > that native SQL is in Python by 2005. > ...when I come back in my time machine. 2015 ____________________________________________________________________________________Sick sense of humor? Visit Yahoo! TV's Comedy with an Edge to see what's on, when. http://tv.yahoo.com/collections/222 From showell30 at yahoo.com Wed May 30 03:12:25 2007 From: showell30 at yahoo.com (Steve Howell) Date: Tue, 29 May 2007 18:12:25 -0700 (PDT) Subject: [Python-ideas] proposal to add rowexpr as a keyword In-Reply-To: <20070529165018.86B2.JCARLSON@uci.edu> Message-ID: <588847.47591.qm@web33506.mail.mud.yahoo.com> --- Josiah Carlson wrote: > > [...] you could add your own syntax with > logix [...] Or PyPy. Despite our disagreement, you are helping me to expand my thinking. Thank you. ____________________________________________________________________________________ Park yourself in front of a world of choices in alternative vehicles. Visit the Yahoo! Auto Green Center. http://autos.yahoo.com/green_center/ From talin at acm.org Wed May 30 03:22:01 2007 From: talin at acm.org (Talin) Date: Tue, 29 May 2007 18:22:01 -0700 Subject: [Python-ideas] Idea: The DSL operator. Message-ID: This is in response to the various suggestions for embedding SQL syntax in Python and various other suggestions made over the years. Note that this suggestion is only a starting point for discussion, I don't have any illusion that the idea as presented here would have strong support. I'm fully aware that the actual proposal given below looks "butt-ugly", but maybe someone can invent something better. Background: Python is frequently used as a foundation for Domain Specific Languages (DSLs). Examples include SQLObject, SCons, and many others. These are all examples of a mini-language which is constructed on top of the Python syntax, using operator overloading. The DSL is often embedded within Python code (as in the case of SQLObject), and can be invoked programmatically from regular (non-DSL) Python code. However, there are some limitations on what can be expressed. For example, in current interpreters, it is not possible to override the 'and' and 'or' operator. While there currently is a PEP that proposes adding this capability, there is some disagreement as to how much this would impact the efficiency of the non-override case. The reason is because in the non-override case, the compiler is able to take advantage of the "shortcut" properties of these operators; If the operators can be overridden (which is a post-compiler operation), then the compiler would no longer be able to make these optimization assumptions. A similar limitation in DSLs is the treatment of unbound identifiers. Identifiers which have already been bound to objects are not a problem, since you can simply override the various operators of those objects. However, for identifiers which have not yet been assigned to a variable, a number of ugly hacks are required. Typically what is done is to have a set of "special" objects which act as placeholders for unbound variable names, for example _x, _y, _z, and so on. Unfortunately, this requires the person writing the DSL expression to pre-declare unbound variables, which is exactly the opposite of how regular Python works. Another method that is sometimes used is to declare unbound variables as attributes of some general "unbound variable" object, so you can say something like Query.x, Query.y, and so forth. But again, this is rather wordy and robs the DSL of its ability to concisely express a particular semantic intent, which is the whole point of DSLs in the first place. Another limitation of Python's ability to represent DSLs is that you cannot override the assignment operator. My idea is to alleviate these problems by giving DSLs some help at the parsing level. By informing the parser that a given expression is a DSL, we can relax some of the normal assumptions of the Python syntax, and instead require the DSL interpreter to handle them, which allows the DSL to have greater flexibility. Two things we want to avoid: First, we want to avoid "programmable syntax", meaning that we cannot define DSL-specific semantics at parse time. The reason for this is that DSLs are generally defined in their own specific imported modules, and the Python parser has no knowledge of imports, and therefore has no access to the DSL's syntax rules. Secondly, we want to avoid conflicts between multiple DSLs. So for example, if I am using two different DSLs in the same module, we can't have two different meanings for "and", for example. The solution to both of these concerns is to say that the parser's support for DSLs is completely generic - in other words, we can tell the parser that a given expression is a DSL, but we can tell it nothing specific about that *particular* DSL. Instead, it is up to the DSL interpreter - which operates at runtime, not parse time - to take up where the parser left off. This is similar to PJE's suggestion of a way to "quote" Python syntax, returning an AST. In such a scheme, the Python parser doesn't completely compile the quoted expression to Python byte code, but instead produces an AST (or AST-like data structure which might not exactly be an AST), which is then interpreted by the DSL. So far this all seems reasonable enough to my ear :) Next is the part where I go mad. (As my friend Sara said to me recently, "I'm not a mad scientist - I'm a mad natural philosopher.") For purposes of dicussion I am going to introduce the token '??' (two consecutive question marks) as the "DSL operator", in other words a signal to the parser that a given expression is a DSL. I'm sure that there could be a long and intense bikeshed discussion debating the specific operator syntax, but for now I'll choose ?? since it's unambiguously parsable. The '??' operator can be used in one of three ways. First, you can declare an entire expression as a DSL: a = ??(c + d) The parser will take all of the tokens inside the parenthesized group and return them as an AST, it will not attempt to generate code to evaluate any of the operators within the group. There's an extra bit of syntactic sugar: If the DSL expression is the only argument to a function, you can combine the function call and the DSL quote: func??(c+d) Meaning "pass the AST for 'c + d' to the function 'func'". For most DSLs, the 'func' will actually be the name of the DSL, so the typical use pattern will be 'name_of_dsl??(expr)'. The second use is to quote an identifier: a = ??c + d Now, you would think that this would quote the variable 'c' and attempt to add it to 'd', but this is not the way it works. Instead, the ?? operator invokes a kind of operator overloading that happens at the parser level, meaning that any attempt to create an expression that operates on a quoted variable also gets quoted. This only affects binary and unary operators, not functions calls, array references or assignment. So in this case, the entire expression "??c + d" gets quoted. The third way a DSL operator can be used is to quote an operator: a = c ??= d Again, this allows us to generate the AST "c = d" and assign it to the variable "a". (I recognize that these last two syntactical variations would make the interpretation of regular Python ASTs significantly more complex, which is a serious drawback. Part of the motivation for both of these variations is to deal with the 'and', 'or' and '=' problem, by overriding the Python compiler's normal treatment of these operators. However, it may be that the first form alone is sufficient, which would be relatively easy to handle in the Python compiler I think - you would simply have the AST.c module look for a DSL operator, and don't call the normal AST processing steps for arguments to that operator.) Some examples of DSLs using the operator: An SQL query as a DSL: query = SQL??(name == "John" and age > 25) result_iter = query.execute() Syntax for an algebraic solver: @arity??(x + x) def reduce(x): return 2 * x @arity??(x + 0) def reduce(x): return x @arity??(x * 0) def reduce(x): return 0 @arity??(x * 1) def reduce(x): return x @arity??(x * a + y * a) def reduce(x): return (x+y)*a # (and so on for all the other reduce() rules) print(reduce??((a+b*3) + (a+b*3))) >>> a*2+b*6 (In the above, we define a function 'reduce' that is similar to a generic function, except that the dispatch logic is based on the form of the AST being passed as an argument, using a one-way unification algorithm to do argument pattern matching.) I realize that there are some aspects of this proposal that may seem silly, and that's true, and the only reason I'm even suggesting this at all is that much of what I'm writing here is already been suggested or at least implied by previous discussions. Flame on! -- -- Talin From showell30 at yahoo.com Wed May 30 03:22:16 2007 From: showell30 at yahoo.com (Steve Howell) Date: Tue, 29 May 2007 18:22:16 -0700 (PDT) Subject: [Python-ideas] proposal to add rowexpr as a keyword In-Reply-To: <20070530004951.GA17586@panix.com> Message-ID: <998077.51447.qm@web33510.mail.mud.yahoo.com> --- Aahz wrote: > Aside from the standard featuritis objection, my > objection stems almost > entirely from the difficulty of defining appropriate > data structures on > which to operate. SQL works partly because data in > SQL tables is already > *by definition* in a relational format -- which > won't be true in Python, > causing all kinds of runtime errors that IMO are > inappropriate for SQL. In theory, I obviously agree, as a list can be full of all kinds of heterogeneous structures, and the fact that it can be is one of the beauties of Python, and certainly trying to apply native, byte-code interpreted SQL to such structures would certainly lead to run-time errors that even unit tests couldn't even catch in theory, much less practice. But, in my own day-to-day practice (I've recently been working on a billing system, which is not rocket science, just tedious), I find myself constantly calling into my DB API, which returns me a list of dictionaries, and the transformation from database to network to API to Python doesn't diminish the relational perfectness of the data whatsoever. Then I find myself transforming the SQL result set in many ways in Python. Some of those transformations are non-relational, which is the whole reason to bring the data into Python in the first place. But other transforms are relational, and that's where I want SQL. Which raises the natural question--to the extent that I want to do more relational transforms on the data that I already have, why don't I just farm that back out to my relational database? The two-part answer is that 1) of course I can, but 2) I don't want to, because I already have the data in Python. Answer #3 is Peoplesoft. If you've never worked with a really awkward database structure in the real world, please count yourself lucky, and I'll buy you drinks at your 30th birthday party. Do you understand at least my motivation, if not necessarily agreeing with the wisdom of my overall proposal? ____________________________________________________________________________________Looking for a deal? Find great prices on flights and hotels with Yahoo! FareChase. http://farechase.yahoo.com/ From showell30 at yahoo.com Wed May 30 03:51:39 2007 From: showell30 at yahoo.com (Steve Howell) Date: Tue, 29 May 2007 18:51:39 -0700 (PDT) Subject: [Python-ideas] Idea: The DSL operator. In-Reply-To: Message-ID: <574890.98074.qm@web33503.mail.mud.yahoo.com> Talin wrote: > An SQL query as a DSL: > query = SQL??(name == "John" and age > 25) > result_iter = query.execute() Can you flesh this out with the added complication that my SQL?? thingy wants to include in its expression some kind of Python function that sits at the module level, such convert_birthday_to_age? My fear is that even with an AST at my DSL library's disposal, I would still want hints from Python as to better ways to scope things in the AST given to me, and without actually changing the Python bytecode, I still have my hands tied. Or am I being too pessimistic? Or does your proposal already account for that? ____________________________________________________________________________________Pinpoint customers who are looking for what you sell. http://searchmarketing.yahoo.com/ From rrr at ronadam.com Wed May 30 04:12:56 2007 From: rrr at ronadam.com (Ron Adam) Date: Tue, 29 May 2007 21:12:56 -0500 Subject: [Python-ideas] dict.fromkeys() better as dict().setkeys() ? (and other suggestions) In-Reply-To: References: <20070528174325.86A2.JCARLSON@uci.edu> <465BA636.8070501@ronadam.com> <20070529000414.86A5.JCARLSON@uci.edu> Message-ID: <465CDDA8.50102@ronadam.com> Jim Jewett wrote: > On 5/29/07, Josiah Carlson wrote: >> Ron Adam wrote: >> > Josiah Carlson wrote: > *this* is the core of a useful idea. list (and set and generator) > comprehensions can't partition very well, because they have only a > single output. There isn't a good way to say: > > list_a = [x for x in src if pred(a)] > src = [x for x in src if not pred(a)] > list_b = [x for x in src if pred(b)] > src = [x for x in src if not pred(b)] > list_c = [x for x in src if pred(c)] > list_other = [x for x in src if not pred(c)] > > On the other hand, you can do it (inefficiently) as above, or you can > write an (ugly) version using a custom function, so the solution would > have to be pretty good before it justified complicating the > comprehension APIs. I can't see how it could be done with out as you say... complicating the comprehension APIs. However, I do think there could be very useful uses for a standard sorting structure of some sort. That's the sorting as in mail sorters, or category sorters, that produce several streams of output instead of just one. Would that be called a de-comprehension? Mabye something like the following as a starting point? # generate some random data import random import string def random_pnum(length): ok_digits = string.letters + string.digits digits = [random.choice(ok_digits) for n in range(length)] return ''.join(digits) src = [] for x in range(10): src.append(random_pnum(10)) # A de - comprehension generator def decomp(seq, *cmps): results = dict(((c.__name__, []) for c in cmps)) rest = [] for x in seq: for c in cmps: if c(x): results[c.__name__].append(x) break else: rest.append(x) for c in cmps: yield results[c.__name__] yield rest # Tests def a_g(s): return s[0].lower() in "abcdefg" def h_m(s): return s[0].lower() in "hijklm" def n_z(s): return s[0].lower() in "nopqrstuvwxyz" decmps = [a_g, h_m, n_z] ag, hm, nz, other = decomp(src, *decmps) print 'ag =', ag print 'hm =', hm print 'nz =', nz print 'other =', other ------------------- ag = ['c8WQe60G6J', 'EMY7O8qzTg'] hm = ['lDunyeOM98', 'LJuPg8ncZd'] nz = ['uhhuhd9YdO', 'qAuQvfTc6N', 'vpJz47pkP5', 'YOq6m4IXBn'] other = ['8JE6PuXxBz', '4ttyMdpuQY'] From showell30 at yahoo.com Wed May 30 04:15:17 2007 From: showell30 at yahoo.com (Steve Howell) Date: Tue, 29 May 2007 19:15:17 -0700 (PDT) Subject: [Python-ideas] dict.fromkeys() better as dict().setkeys() ? (and other suggestions) In-Reply-To: <465CDDA8.50102@ronadam.com> Message-ID: <43274.80903.qm@web33505.mail.mud.yahoo.com> --- Ron Adam wrote: > Would that be called a de-comprehension? > LOL ____________________________________________________________________________________ Expecting? Get great news right away with email Auto-Check. Try the Yahoo! Mail Beta. http://advision.webevents.yahoo.com/mailbeta/newmail_tools.html From showell30 at yahoo.com Wed May 30 04:32:16 2007 From: showell30 at yahoo.com (Steve Howell) Date: Tue, 29 May 2007 19:32:16 -0700 (PDT) Subject: [Python-ideas] dict.fromkeys() better as dict().setkeys() ? (and other suggestions) In-Reply-To: <465CDDA8.50102@ronadam.com> Message-ID: <297639.8702.qm@web33512.mail.mud.yahoo.com> --- Ron Adam wrote: > # Tests > > def a_g(s): > return s[0].lower() in "abcdefg" > > def h_m(s): > return s[0].lower() in "hijklm" > > def n_z(s): > return s[0].lower() in "nopqrstuvwxyz" > > decmps = [a_g, h_m, n_z] > ag, hm, nz, other = decomp(src, *decmps) > > print 'ag =', ag > print 'hm =', hm > print 'nz =', nz > print 'other =', other > > > ------------------- > > ag = ['c8WQe60G6J', 'EMY7O8qzTg'] > hm = ['lDunyeOM98', 'LJuPg8ncZd'] > nz = ['uhhuhd9YdO', 'qAuQvfTc6N', 'vpJz47pkP5', > 'YOq6m4IXBn'] > other = ['8JE6PuXxBz', '4ttyMdpuQY'] > Am I misunderstanding (de-comprehensing) something here? How does the code above return those result sets? Or, more specifically, why does ag include 'T' in its results set? ____________________________________________________________________________________ Sucker-punch spam with award-winning protection. Try the free Yahoo! Mail Beta. http://advision.webevents.yahoo.com/mailbeta/features_spam.html From rrr at ronadam.com Wed May 30 04:45:49 2007 From: rrr at ronadam.com (Ron Adam) Date: Tue, 29 May 2007 21:45:49 -0500 Subject: [Python-ideas] dict.fromkeys() better as dict().setkeys() ? (and other suggestions) In-Reply-To: <297639.8702.qm@web33512.mail.mud.yahoo.com> References: <297639.8702.qm@web33512.mail.mud.yahoo.com> Message-ID: <465CE55D.6060607@ronadam.com> Steve Howell wrote: > --- Ron Adam wrote: >> # Tests >> >> def a_g(s): >> return s[0].lower() in "abcdefg" >> >> def h_m(s): >> return s[0].lower() in "hijklm" >> >> def n_z(s): >> return s[0].lower() in "nopqrstuvwxyz" >> >> decmps = [a_g, h_m, n_z] >> ag, hm, nz, other = decomp(src, *decmps) >> >> print 'ag =', ag >> print 'hm =', hm >> print 'nz =', nz >> print 'other =', other >> >> >> ------------------- >> >> ag = ['c8WQe60G6J', 'EMY7O8qzTg'] >> hm = ['lDunyeOM98', 'LJuPg8ncZd'] >> nz = ['uhhuhd9YdO', 'qAuQvfTc6N', 'vpJz47pkP5', >> 'YOq6m4IXBn'] >> other = ['8JE6PuXxBz', '4ttyMdpuQY'] >> > > Am I misunderstanding (de-comprehensing) something > here? How does the code above return those result > sets? Or, more specifically, why does ag include 'T' > in its results set? The data in this case simulates 10 digit partnumbers which can include a-z, A-Z, and 0-9. It doesn't alter the data, it just sorts it into smaller groups according to some predefined tests. In this case.. it's only testing the first letter of each item. What is tested is entirely up to you. You could have lists of records as your data and test fields and divide the data according to that. Cheers, Ron From showell30 at yahoo.com Wed May 30 04:53:03 2007 From: showell30 at yahoo.com (Steve Howell) Date: Tue, 29 May 2007 19:53:03 -0700 (PDT) Subject: [Python-ideas] dict.fromkeys() better as dict().setkeys() ? (and other suggestions) In-Reply-To: <465CE55D.6060607@ronadam.com> Message-ID: <996023.85950.qm@web33501.mail.mud.yahoo.com> --- Ron Adam wrote: > Steve Howell wrote: > > --- Ron Adam wrote: > >> # Tests > >> > >> def a_g(s): > >> return s[0].lower() in "abcdefg" > >> > >> def h_m(s): > >> return s[0].lower() in "hijklm" > >> > >> def n_z(s): > >> return s[0].lower() in "nopqrstuvwxyz" > >> > >> decmps = [a_g, h_m, n_z] > >> ag, hm, nz, other = decomp(src, *decmps) > >> > >> print 'ag =', ag > >> print 'hm =', hm > >> print 'nz =', nz > >> print 'other =', other > >> > >> > >> ------------------- > >> > >> ag = ['c8WQe60G6J', 'EMY7O8qzTg'] > >> hm = ['lDunyeOM98', 'LJuPg8ncZd'] > >> nz = ['uhhuhd9YdO', 'qAuQvfTc6N', 'vpJz47pkP5', > >> 'YOq6m4IXBn'] > >> other = ['8JE6PuXxBz', '4ttyMdpuQY'] > >> > > > > Am I misunderstanding (de-comprehensing) something > > here? How does the code above return those result > > sets? Or, more specifically, why does ag include > 'T' > > in its results set? > > The data in this case simulates 10 digit partnumbers > which can include a-z, > A-Z, and 0-9. > > It doesn't alter the data, it just sorts it into > smaller groups according > to some predefined tests. In this case.. it's only > testing the first > letter of each item. > > What is tested is entirely up to you. You could > have lists of records as > your data and test fields and divide the data > according to that. > Ok, apologies for quoting away the parts of your code that probably answer my own question. But to your bigger question--I think you can set up a list comprehension that does partitioning by having the list comprension or generator expression simply return a list of tuples where the first element in the tuple is a value that suggest where it fits in the partition, then feed that tuple to dict() or whatever. But I don't have a specific code example to prove it. For simple binary partitions, there is the bool function. ____________________________________________________________________________________Choose the right car based on your needs. Check out Yahoo! Autos new Car Finder tool. http://autos.yahoo.com/carfinder/ From rrr at ronadam.com Wed May 30 05:30:19 2007 From: rrr at ronadam.com (Ron Adam) Date: Tue, 29 May 2007 22:30:19 -0500 Subject: [Python-ideas] dict.fromkeys() better as dict().setkeys() ? (and other suggestions) In-Reply-To: <996023.85950.qm@web33501.mail.mud.yahoo.com> References: <996023.85950.qm@web33501.mail.mud.yahoo.com> Message-ID: <465CEFCB.1020107@ronadam.com> Steve Howell wrote: > --- Ron Adam wrote: > >> Steve Howell wrote: >>> --- Ron Adam wrote: >>>> # Tests >>>> >>>> def a_g(s): >>>> return s[0].lower() in "abcdefg" >>>> >>>> def h_m(s): >>>> return s[0].lower() in "hijklm" >>>> >>>> def n_z(s): >>>> return s[0].lower() in "nopqrstuvwxyz" >>>> >>>> decmps = [a_g, h_m, n_z] >>>> ag, hm, nz, other = decomp(src, *decmps) >>>> >>>> print 'ag =', ag >>>> print 'hm =', hm >>>> print 'nz =', nz >>>> print 'other =', other >>>> >>>> >>>> ------------------- >>>> >>>> ag = ['c8WQe60G6J', 'EMY7O8qzTg'] >>>> hm = ['lDunyeOM98', 'LJuPg8ncZd'] >>>> nz = ['uhhuhd9YdO', 'qAuQvfTc6N', 'vpJz47pkP5', >>>> 'YOq6m4IXBn'] >>>> other = ['8JE6PuXxBz', '4ttyMdpuQY'] >>>> >>> Am I misunderstanding (de-comprehensing) something >>> here? How does the code above return those result >>> sets? Or, more specifically, why does ag include >> 'T' >>> in its results set? >> The data in this case simulates 10 digit partnumbers >> which can include a-z, >> A-Z, and 0-9. >> >> It doesn't alter the data, it just sorts it into >> smaller groups according >> to some predefined tests. In this case.. it's only >> testing the first >> letter of each item. >> >> What is tested is entirely up to you. You could >> have lists of records as >> your data and test fields and divide the data >> according to that. >> > > Ok, apologies for quoting away the parts of your code > that probably answer my own question. > > But to your bigger question--I think you can set up a > list comprehension that does partitioning by having > the list comprension or generator expression simply > return a list of tuples where the first element in the > tuple is a value that suggest where it fits in the > partition, then feed that tuple to dict() or whatever. > > But I don't have a specific code example to prove it. That would depend on what level of abstraction you want. I find python already handles the simple things fairly well, so I tend to look for the next level up now. That makes it a bit harder to find the balance between being too specific and too general. > For simple binary partitions, there is the bool > function. Or more likely you may have a method in a class that tests for a particular condition. pass, fail = decomp(list_of_classes, lambda x: x.test()) Cheers, Ron From showell30 at yahoo.com Wed May 30 05:31:49 2007 From: showell30 at yahoo.com (Steve Howell) Date: Tue, 29 May 2007 20:31:49 -0700 (PDT) Subject: [Python-ideas] dict.fromkeys() better as dict().setkeys() ? (and other suggestions) In-Reply-To: <465CDDA8.50102@ronadam.com> Message-ID: <695025.66300.qm@web33507.mail.mud.yahoo.com> --- Ron Adam wrote: > However, I do think there could be very useful uses > for a standard sorting > structure of some sort. That's the sorting as in > mail sorters, or category > sorters, that produce several streams of output > instead of just one. > > Would that be called a de-comprehension? > Here is some category-sorting code, FWIW, where every employee, Fred or not, gets a 50% raise, and employees are partitioned according to their Fredness. It doesn't use a general iterator, so maybe I'm missing your point. def partitions(lst): dct = {} for k, value in lst: dct.setdefault(k, []).append(value) return dct.items() def is_fred(emp): return 'Fred' in emp[0] emps = [ ('Fred Smith', 50), ('Fred Jones', 40), ('Joe Blow', 30), ] def pay_increase(salary): return salary * 0.5 emp_groups = partitions([(is_fred(emp), (emp[0], pay_increase(emp[1]))) for emp in emps]) for fredness, emps in emp_groups: print print 'is Fred?', fredness for name, pay_increase in emps: print name, pay_increase ---- is Fred? False Joe Blow 15.0 is Fred? True Fred Smith 25.0 Fred Jones 20.0 ____________________________________________________________________________________ Park yourself in front of a world of choices in alternative vehicles. Visit the Yahoo! Auto Green Center. http://autos.yahoo.com/green_center/ From gsakkis at rutgers.edu Wed May 30 05:58:58 2007 From: gsakkis at rutgers.edu (George Sakkis) Date: Tue, 29 May 2007 23:58:58 -0400 Subject: [Python-ideas] dict.fromkeys() better as dict().setkeys() ? (and other suggestions) In-Reply-To: <695025.66300.qm@web33507.mail.mud.yahoo.com> References: <465CDDA8.50102@ronadam.com> <695025.66300.qm@web33507.mail.mud.yahoo.com> Message-ID: <91ad5bf80705292058l40b74e57o80854b5a1a25da3@mail.gmail.com> On 5/29/07, Steve Howell wrote: > > --- Ron Adam wrote: > > > However, I do think there could be very useful uses > > for a standard sorting > > structure of some sort. That's the sorting as in > > mail sorters, or category > > sorters, that produce several streams of output > > instead of just one. > > > > Would that be called a de-comprehension? > > > > Here is some category-sorting code, FWIW, where every > employee, Fred or not, gets a 50% raise, and employees > are partitioned according to their Fredness. > > It doesn't use a general iterator, so maybe I'm > missing your point. > > (snipped) Or maybe you skipped homework on the itertools.groupby thread of c.l.py. ;-) George -- "If I have been able to see further, it was only because I stood on the shoulders of million monkeys." From rrr at ronadam.com Wed May 30 06:24:39 2007 From: rrr at ronadam.com (Ron Adam) Date: Tue, 29 May 2007 23:24:39 -0500 Subject: [Python-ideas] dict.fromkeys() better as dict().setkeys() ? (and other suggestions) In-Reply-To: <695025.66300.qm@web33507.mail.mud.yahoo.com> References: <695025.66300.qm@web33507.mail.mud.yahoo.com> Message-ID: <465CFC87.2030600@ronadam.com> Steve Howell wrote: > --- Ron Adam wrote: > >> However, I do think there could be very useful uses >> for a standard sorting >> structure of some sort. That's the sorting as in >> mail sorters, or category >> sorters, that produce several streams of output >> instead of just one. >> >> Would that be called a de-comprehension? >> > > Here is some category-sorting code, FWIW, where every > employee, Fred or not, gets a 50% raise, and employees > are partitioned according to their Fredness. > > It doesn't use a general iterator, so maybe I'm > missing your point. Since you aren't really creating two lists, the problem below doesn't really fit this particular solution. But maybe we can make it work from a different point of view. emps = { 'Fred Smith': 50.0, 'Fred Jones': 40.0, 'Joe Blow': 30, } def pay_increase(salary): return salary * 0.5 def is_fred(emp): return 'Fred' in emp[0] # give all Freds a raise freds, notfreds = decomp(emps.keys(), is_fred): for name in freds: emp[name] = pay_increas(emp[name]) # # Then we can use the freds list again to generate a report. # Of course in this case the following would work just as well... freds = [] for name in emps: if is_fred(name): emp[name] = pay_increas(emp[name]) freds.append(name) One reason to generating more than one list is if each list is going to be handled as batches, or in different ways, or at different times than you otherwise would by just iterating it. Cheers, Ron > def partitions(lst): > dct = {} > for k, value in lst: > dct.setdefault(k, []).append(value) > return dct.items() > > def is_fred(emp): > return 'Fred' in emp[0] > > > emps = [ > ('Fred Smith', 50), > ('Fred Jones', 40), > ('Joe Blow', 30), > ] > > def pay_increase(salary): return salary * 0.5 > > emp_groups = partitions([(is_fred(emp), > (emp[0], pay_increase(emp[1]))) for > emp in emps]) > > for fredness, emps in emp_groups: > print > print 'is Fred?', fredness > for name, pay_increase in emps: > print name, pay_increase > > ---- > > is Fred? False > Joe Blow 15.0 > > is Fred? True > Fred Smith 25.0 > Fred Jones 20.0 > > > > ____________________________________________________________________________________ > Park yourself in front of a world of choices in alternative vehicles. Visit the Yahoo! Auto Green Center. > http://autos.yahoo.com/green_center/ > > From arno at marooned.org.uk Wed May 30 12:41:51 2007 From: arno at marooned.org.uk (Arnaud Delobelle) Date: Wed, 30 May 2007 11:41:51 +0100 Subject: [Python-ideas] About list comprehension syntax Message-ID: <8C1BDF74-1DAB-4F64-A28E-16788C48AA95@marooned.org.uk> Hi List comprehensions (and generator expressions) come in two 'flavours' at the moment: (1) [f(x) for x in L], which stands for map(f, L). Let's call this a 'map comprehension' (2) [f(x) for x in L if p(x)], which stands for map(f, filter(p, L)). Let's call this a 'map-filter comprehension'. Now if one wants to write simply filter(p, L) as a list comprehension, one has to write: (3) [x for x in L if p(x)]. This could be called a 'filter comprehension'. the 'x for x in L' is not very nice IMHO, but it is often handy to use such expressions over 'filter(...)', eg building the sublist of a given list consisting of all the items of a given type could be written as: filter(lambda x: isinstance(x, FilteringType), heterogeneous_list) or: [x for x in heterogenous_list if isinstance(x, FilteringType)] I still prefer the list comprehension over the lambda/filter combination, but neither feels very satisfying (to me :) (not that one cannot use partial in the filter version) Why not just drop the 'x for' at the start of a 'filter comprehension' (or generator expression)? Thus (3) could be written more simply as: (3') [x in L if p(x)] This is consistent with common mathematical notation: * { f(x) | x \in L } means the set of all f(x) for x in L * { f(x) | x \in L, p(x) } means the set of all f(x) for x in L satisfying predicate p. * { x \in L | p(x) } means the set of all x in L satisfying predicate p. -- Arnaud From stargaming at gmail.com Wed May 30 15:45:27 2007 From: stargaming at gmail.com (Stargaming) Date: Wed, 30 May 2007 15:45:27 +0200 Subject: [Python-ideas] proposal to add rowexpr as a keyword In-Reply-To: <465C3407.6030903@latte.ca> References: <422478.77150.qm@web33501.mail.mud.yahoo.com> <465C3407.6030903@latte.ca> Message-ID: Blake Winton wrote: > Steve Howell wrote: > >>Let the Python interpreter build expression objects >>for you. You write: >> rowexpr: convert_to_euros(salary) > 50000 and >>deptno = 10 >>Python translates that into the same bytecode as: >>lambda row: convert_to_euros(row['salary'] > 50000 and >>row['deptno'] == 10 > > > I'm sorry, why would that not be translated into: > > lambda row: row['convert_to_euros'](row['salary'] > row['50000'] > row['and'] row['deptno'] == row['10'] Sticking to your logic, why would it be > instead of row['>']? This is, I guess, particularly simple with Python's tokenizer because neither 50000 nor and can be valid identifiers. > ? Specifically, how would python know what to dereference and what not > to? What if there were two things, named the same, one in the row and > one in the namespace? (i.e. a variable named 'salary') That's a harder one, indeed. Perhaps, nothing should be dereferenced (at ``compile'' time, don't know if that's a valid term in CPython's interpreter chain tho), as it is in a lambda-expression. > How would you > escape things which would have been dereferenced but you didn't want to > be? (i.e. "rowexpr: convert_to_euros(salary) > salary") ACK. If included (and I have major doubts it has a chance over 0.001%), it could just support "easy" expressions, such as lambdas do today. > I guess I'm kind of wasting my time here, since the introduction of a > new keyword for this application really isn't going to happen, based on > other decisions I've seen Guido make, but I do think that you need to > think a little more about how the implementation of this feature would > work. (Or perhaps you've done that thinking, and you just need to fill > in the proposal with that information.) Well, discussing in a mature manner can IMO never be a waste of time but I have to agree, I would not want this as a keyword either. A common idiom (aka stdlib module) *could* be handy, though. Regards, Stargaming From arno at marooned.org.uk Wed May 30 17:16:43 2007 From: arno at marooned.org.uk (Arnaud Delobelle) Date: Wed, 30 May 2007 16:16:43 +0100 Subject: [Python-ideas] positional only arguments decorator In-Reply-To: References: <75AAE6B2-8D9D-43CF-A151-DF0C92964BA7@marooned.org.uk> Message-ID: <870D2002-DA52-44EA-B42A-3239917544A7@marooned.org.uk> On 27 May 2007, at 16:37, Steven Bethard wrote: > On 5/27/07, Arnaud Delobelle wrote: >> >> On 21 May 2007, at 19:30, Steven Bethard wrote: >> >>> Ok, looks like there's not much chance of agreeing on a syntax, so >>> here's a decorator that covers the two use cases I know of:: >>> >>> * matching the signature of dict() and dict.update() >>> * allowing arguments to have their names changed without worrying >>> about backwards compatibility (e.g. ``def func(sequence)`` >>> changing to >>> ``def func(iterable)``) >> >> I propose a slightly different solution. It may be a bit of a hack, >> but I don't see why it should not be safe. This solution allows you >> to use * and ** in order to write a definition like: >> >>>>> @posonly >> ... def update(self, container=None, **kwargs): >> ... return self, container, kwargs >> ... >>>>> update('self') >> ('self', None, {}) >>>>> update('self', 'container') >> ('self', 'container', {}) >>>>> update('self', self='abc', container='xyz', foo='bar') >> ('self', None, {'self': 'abc', 'foo': 'bar', 'container': 'xyz'}) > > Cool! Yes, it's hackish, but at least the results are pretty. ;-) Wait! I think I've got a devastatingly simple solution. I've thought about this while looking at the PyEval_EvalCodeEx() function in Python/ceval.c. It turns out that the 'co_varnames' attribute of a code object is only used in order to 'slot in' arguments passed as keywords. So by adding a '@' to the names we make these arguments positional only (one could choose any decoration including a character which is illegal in identifiers). This method has two advantages: * there is **no** overhead at all in calling a positional only function. * the function keeps its original signature (positional only arguments are flagged with the trailing '@'). There is one 'drawback' (which could be considered a useful feature): * if x is positional, f(**{'x@':1}) will work. Here is the code. ------------------------------------------------------------------ from types import CodeType code_args = ( 'argcount', 'nlocals', 'stacksize', 'flags', 'code', 'consts', 'names', 'varnames', 'filename', 'name', 'firstlineno', 'lnotab', 'freevars', 'cellvars' ) def copy_code(code_obj, **kwargs): "Make a copy of a code object, maybe changing some attributes" for arg in code_args: if not kwargs.has_key(arg): kwargs[arg] = getattr(code_obj, 'co_%s' % arg) return CodeType(*map(kwargs.__getitem__, code_args)) def posonly(f): code = f.func_code varnames, nargs = code.co_varnames, code.co_argcount varnames = ( tuple(v+'@' for v in varnames[:nargs]) + varnames[nargs:] ) f.func_code = copy_code(code, varnames = varnames) return f ------------------------------------------------------------------ That's it! Example: >>> @posonly ... def update(self, container=None, **kwargs): ... return self, container, kwargs ... >>> update(1,2, self=3, container=4, x=5) (1, 2, {'x': 5, 'self': 3, 'container': 4}) >>> update(1) (1, None, {}) >>> help(update) # Notice the unobfuscated signature! Help on function update in module __main__: update(self@, container@=None, **kwargs) >>> # 'container' is still accessible by name: ... update(1, **{'container@':2}) (1, 2, {}) >>> -- Arnaud From tjreedy at udel.edu Wed May 30 18:30:47 2007 From: tjreedy at udel.edu (Terry Reedy) Date: Wed, 30 May 2007 12:30:47 -0400 Subject: [Python-ideas] About list comprehension syntax References: <8C1BDF74-1DAB-4F64-A28E-16788C48AA95@marooned.org.uk> Message-ID: "Arnaud Delobelle" wrote in message news:8C1BDF74-1DAB-4F64-A28E-16788C48AA95 at marooned.org.uk... | Hi | | List comprehensions (and generator expressions) come in two | 'flavours' at the moment: Actually, you can have 1 to many for clauses and 0 to many if clauses. | (1) [f(x) for x in L], which stands for map(f, L). Let's call this a | 'map comprehension' | | (2) [f(x) for x in L if p(x)], which stands for map(f, filter(p, L)). | Let's call this a 'map-filter comprehension'. | | Now if one wants to write simply filter(p, L) as a list | comprehension, one has to write: | | (3) [x for x in L if p(x)]. This could be called a 'filter | comprehension'. | | the 'x for x in L' is not very nice IMHO, but it is often handy to | use such expressions over 'filter(...)', eg building the sublist of a | given list consisting of all the items of a given type could be | written as: | | filter(lambda x: isinstance(x, FilteringType), heterogeneous_list) | | or: | | [x for x in heterogenous_list if isinstance(x, FilteringType)] | | I still prefer the list comprehension over the lambda/filter | combination, but neither feels very satisfying (to me :) (not that | one cannot use partial in the filter version) | | Why not just drop the 'x for' at the start of a 'filter | comprehension' (or generator expression)? Because such micro abbreviations are against the spirit of Python, which is designed for readability over writablilty. Even for a writer, it might take as much time to mentally deal with the exception and to simply type 'for x', which takes all of a second. Also, this breaks the mapping between for/if statements and clauses and makes the code ambiguous for both humans and the parser | Thus (3) could be written more simply as: | | (3') [x in L if p(x)] (x in L) is a legal expression already. (x in L) if p(x) looks like the beginning of (x in L) if p(x) else 'blah' . The whole thing looks like a list literal with an incompletely specified one element. | This is consistent with common mathematical notation: 'Common mathematical notation' is not codified and varies from writer to writer and even within the work of one writer. Humans make do and make guesses, but parser programs are less flexible. | * { f(x) | x \in L } means the set of all f(x) for x in L | * { f(x) | x \in L, p(x) } means the set of all f(x) for x in L | satisfying predicate p. | * { x \in L | p(x) } means the set of all x in L satisfying predicate p. I personally do not like the inconsistency of the last form, which flips '\in L' over the bar just because f(x) is the identify function. It would be OK though in a situation where that was the only set comprehension being used. But that is not the case with Python. Terry Jan Reedy From bjourne at gmail.com Wed May 30 18:36:57 2007 From: bjourne at gmail.com (=?ISO-8859-1?Q?BJ=F6rn_Lindqvist?=) Date: Wed, 30 May 2007 18:36:57 +0200 Subject: [Python-ideas] proposal to add rowexpr as a keyword In-Reply-To: <91ad5bf80705290803l7d6cade1s52ee8eceecc7b985@mail.gmail.com> References: <422478.77150.qm@web33501.mail.mud.yahoo.com> <465C3407.6030903@latte.ca> <91ad5bf80705290803l7d6cade1s52ee8eceecc7b985@mail.gmail.com> Message-ID: <740c3aec0705300936m3802e527oa5fc7524c0e27b55@mail.gmail.com> On 5/29/07, George Sakkis wrote: > Indeed, such half baked ideas have no chance of being taken seriously > as language additions. Remember that this list is called python-ideas for a reason. It is the place for half-baked ideas. -- mvh Bj?rn From jcarlson at uci.edu Wed May 30 18:45:24 2007 From: jcarlson at uci.edu (Josiah Carlson) Date: Wed, 30 May 2007 09:45:24 -0700 Subject: [Python-ideas] About list comprehension syntax In-Reply-To: <8C1BDF74-1DAB-4F64-A28E-16788C48AA95@marooned.org.uk> References: <8C1BDF74-1DAB-4F64-A28E-16788C48AA95@marooned.org.uk> Message-ID: <20070530094220.86D3.JCARLSON@uci.edu> Arnaud Delobelle wrote: > Why not just drop the 'x for' at the start of a 'filter > comprehension' (or generator expression)? Thus (3) could be written > more simply as: Explicit is better than implicit. Special cases aren't special enough to break the rules. There should be one-- and preferably only one --obvious way to do it. - Josiah From jcarlson at uci.edu Wed May 30 19:34:17 2007 From: jcarlson at uci.edu (Josiah Carlson) Date: Wed, 30 May 2007 10:34:17 -0700 Subject: [Python-ideas] proposal to add rowexpr as a keyword In-Reply-To: <740c3aec0705300936m3802e527oa5fc7524c0e27b55@mail.gmail.com> References: <91ad5bf80705290803l7d6cade1s52ee8eceecc7b985@mail.gmail.com> <740c3aec0705300936m3802e527oa5fc7524c0e27b55@mail.gmail.com> Message-ID: <20070530103147.86E2.JCARLSON@uci.edu> "BJ?rn Lindqvist" wrote: > On 5/29/07, George Sakkis wrote: > > Indeed, such half baked ideas have no chance of being taken seriously > > as language additions. > > Remember that this list is called python-ideas for a reason. It is the > place for half-baked ideas. Indeed, but when they are called out as half-baked (explicitly or implicitly), and are offered no love by others in the list, perhaps it's time to let them die. On the other hand, there is the other argument that comp.lang.python is the right place to post half-baked ideas, which are then baked, brought to python-ideas for another round of "you didn't put in blueberries", before making it to python-dev/python-3000 . - Josiah From arno at marooned.org.uk Wed May 30 19:31:55 2007 From: arno at marooned.org.uk (Arnaud Delobelle) Date: Wed, 30 May 2007 18:31:55 +0100 Subject: [Python-ideas] About list comprehension syntax In-Reply-To: References: <8C1BDF74-1DAB-4F64-A28E-16788C48AA95@marooned.org.uk> Message-ID: On 30 May 2007, at 17:30, Terry Reedy wrote: > > "Arnaud Delobelle" wrote in > message news:8C1BDF74-1DAB-4F64-A28E-16788C48AA95 at marooned.org.uk... > | Hi > | > | List comprehensions (and generator expressions) come in two > | 'flavours' at the moment: > > Actually, you can have 1 to many for clauses and 0 to many if clauses. That's true. I use that very seldom in fact. [...] > | > | Now if one wants to write simply filter(p, L) as a list > | comprehension, one has to write: > | > | (3) [x for x in L if p(x)]. This could be called a 'filter > | comprehension'. [...] > | Why not just drop the 'x for' at the start of a 'filter > | comprehension' (or generator expression)? > > Because such micro abbreviations are against the spirit of Python, > which is > designed for readability over writablilty. Even for a writer, it > might > take as much time to mentally deal with the exception and to simply > type > 'for x', which takes all of a second. I wasn't suggesting this to save myself from typing 5 characters. You'll find it strange but I actually find [x in L if p(x)] more readable than [x for x in L if p(x)]. To me it says that I'm filtering, not mapping. > Also, this breaks the mapping > between for/if statements and clauses and makes the code ambiguous > for both > humans and the parser > By ambiguous do you mean 'difficult to parse'? I didn't think it was ambiguous in the technical sense. > | Thus (3) could be written more simply as: > | > | (3') [x in L if p(x)] > > (x in L) is a legal expression already. (x in L) if p(x) looks > like the > beginning of (x in L) if p(x) else 'blah' . The whole thing looks > like a > list literal with an incompletely specified one element. I'm not sure I understand. I agree that x if (y in L if p(y)) else z doesn't look great. Neither does x if (y for y in L if p(y)) else z Well, the 'for' in the second one is a bit of a hint, I suppose. I wouldn't write either anyway. Most of the time when I write a list comprehension / generator expression it is to bind it to a name. > | This is consistent with common mathematical notation: > > 'Common mathematical notation' is not codified and varies from > writer to > writer and even within the work of one writer. Humans make do and > make > guesses, but parser programs are less flexible. Yet all modern mathematicians will understand the three forms without any hesitation and 'making guesses' (consciously at least). > | * { f(x) | x \in L } means the set of all f(x) for x in L > | * { f(x) | x \in L, p(x) } means the set of all f(x) for x in L > | satisfying predicate p. > | * { x \in L | p(x) } means the set of all x in L satisfying > predicate p. > > I personally do not like the inconsistency of the last form, which > flips > '\in L' over the bar just because f(x) is the identify function. In fact the last form is 'the consistent one', as the first two should really be written as: * { y \in M | \exists x \in L, y=f(x) } * { y \in M | \exists x \in L, p(x) and y=f(x) } (M being the codomain of f) ;oP Anyway, while I still like the idea, you've made me think about it as some sort of 'useless tinkering', which is probably is. -- Arnaud From showell30 at yahoo.com Thu May 31 01:40:02 2007 From: showell30 at yahoo.com (Steve Howell) Date: Wed, 30 May 2007 16:40:02 -0700 (PDT) Subject: [Python-ideas] how rowexpr would be implemented In-Reply-To: Message-ID: <230085.20835.qm@web33501.mail.mud.yahoo.com> --- Stargaming wrote: > > > ? Specifically, how would python know what to > dereference and what not > > to? What if there were two things, named the > same, one in the row and > > one in the namespace? (i.e. a variable named > 'salary') > > That's a harder one, indeed. Perhaps, nothing should > be dereferenced (at > ``compile'' time, don't know if that's a valid term > in CPython's > interpreter chain tho), as it is in a > lambda-expression. > > Admitting to not fully understanding the Python innards, here's some food for thought on how this would be done: 1) Not to diminish the parsing-into-AST stage, I won't cover that here, as other problems are trickier. Despite pretty different semantics, I think rowexpr would look a lot like lambda at the syntactic level. 2) You'd add a case to compiler_visit_expr for Rowexpr_kind in compile.c. 3) There's a pretty small method in compile.c called compiler_lambda that would be the model for compiler_rowexpr. The compiler_rowexp would generate an opcode that caused the single (implied, C++-"this"-like) arg to be popped, and possibly that opcode would have to be different than a normal opcode to pop one argument off the stack, so that ceval.c can do the right thing, but I'm not so sure. 4) You might need to add something to compiler_unit that is analogous to u_varnames, u_cellvars, u_freevars, etc., so that when you recursively call down to evaluate the expression in the rowexpr, the lower methods know to look in a different place to scope the words "salary," "convert_to_euros," and "dept" in the example expression 'where convert_to_euros(salary) > 50000 an dept = "software development"'. 5) The behavior of compiler_expr would NOT change for most operators, such as Num_kind, Str_kind, Attribute_kind, Subscript_kind, etc., as rowexpr doesn't change how any of those are intrerpreted compared to an expression in other scopes. 6) Compiler_expr eventually gets to building opcodes that give you salary, convert_to_euros, and dept, and those pieces of code need to look into compiler_unit to determine if they're part of the rowexpr, and do the right thing. 7) I'm sure there's more. I'm here to learn. ____________________________________________________________________________________Get the free Yahoo! toolbar and rest assured with the added security of spyware protection. http://new.toolbar.yahoo.com/toolbar/features/norton/index.php From showell30 at yahoo.com Thu May 31 02:29:20 2007 From: showell30 at yahoo.com (Steve Howell) Date: Wed, 30 May 2007 17:29:20 -0700 (PDT) Subject: [Python-ideas] proposal to add rowexpr as a keyword In-Reply-To: Message-ID: <860739.28878.qm@web33506.mail.mud.yahoo.com> --- Stargaming wrote: > > That's a harder one, indeed. Perhaps, nothing should > be dereferenced (at > ``compile'' time, don't know if that's a valid term > in CPython's > interpreter chain tho), as it is in a > lambda-expression. > Just tried a few examples, almost everything interesting happens at runtime: ======== PYTHON 2.3 Valid Python: salary = 2 print (lambda: salary)() # prints 2 --- Valid, but useless, Python (no errors) lambda: salary --- Run-time error: x = lambda: salary x() NameError: global name 'salary' is not defined --- Run-time error: x = lambda: convert_to_euros(salary) x() NameError: global name 'convert_to_euros' is not defined --- Run-time error: def convert_to_euros(amt): return amt.impossible salary = None x = lambda: convert_to_euros(salary) x() AttributeError: 'NoneType' object has no attribute 'impossible' --- Run-time error: def convert_to_euros(amt): raise 'this does not get here' row = None x = lambda row: convert_to_euros(row['salary']) x(row) TypeError: 'NoneType' object is unsubscriptable ======= THEORETICAL Valid Python: row = {'salary': 50000} def convert_to_euros(amt): return amt / 2 x = rowexpr: convert_to_euros(salary) print x(row) # prints 25000 --- Run-time error: def convert_to_euros(amt): raise 'this does not get here' row = None x = rowexpr: convert_to_euros(salary) x(row) TypeError: 'NoneType' object is unsubscriptable --- ____________________________________________________________________________________ Park yourself in front of a world of choices in alternative vehicles. Visit the Yahoo! Auto Green Center. http://autos.yahoo.com/green_center/ From santagada at gmail.com Thu May 31 03:20:33 2007 From: santagada at gmail.com (Leonardo Santagada) Date: Wed, 30 May 2007 22:20:33 -0300 Subject: [Python-ideas] Make a CPAN like system for Py3K Message-ID: <939F8BD5-04E0-4FFC-AFB3-0F9457DE96A3@gmail.com> I know about cheeseshop and I know about setuptools. But how about all this be standard tools on python 3.0, so we can have something like CPAN but better. With setuptools being default on py3k you can already easy_install everything, ok but then we can do even more. When the user run a python script, if it requires a version of a lib that he doesn't have it could download it and install in his home folder (something in the lines of ~/pythonlibs). This will make it much easier to distribute python programs. I think this is somewhat like what java webstart does. What do you guys think? Also why no one is talking about having a tool like setuptools in the stdlib? -- Leonardo Santagada "If it looks like a duck, and quacks like a duck, we have at least to consider the possibility that we have a small aquatic bird of the family anatidae on our hands." - Douglas Adams From adam at atlas.st Thu May 31 03:23:43 2007 From: adam at atlas.st (Adam Atlas) Date: Wed, 30 May 2007 21:23:43 -0400 Subject: [Python-ideas] Make a CPAN like system for Py3K In-Reply-To: <939F8BD5-04E0-4FFC-AFB3-0F9457DE96A3@gmail.com> References: <939F8BD5-04E0-4FFC-AFB3-0F9457DE96A3@gmail.com> Message-ID: <528310D8-9BA2-4674-BDE9-F5A3F432BF7A@atlas.st> If I remember correctly, setuptools is to be included starting already with Python 2.6. On 30 May 2007, at 21.20, Leonardo Santagada wrote: > I know about cheeseshop and I know about setuptools. But how about > all this be standard tools on python 3.0, so we can have something > like CPAN but better. With setuptools being default on py3k you can > already easy_install everything, ok but then we can do even more. > When the user run a python script, if it requires a version of a lib > that he doesn't have it could download it and install in his home > folder (something in the lines of ~/pythonlibs). This will make it > much easier to distribute python programs. I think this is somewhat > like what java webstart does. What do you guys think? Also why no one > is talking about having a tool like setuptools in the stdlib? From greg.ewing at canterbury.ac.nz Thu May 31 03:59:25 2007 From: greg.ewing at canterbury.ac.nz (Greg Ewing) Date: Thu, 31 May 2007 13:59:25 +1200 Subject: [Python-ideas] proposal to add rowexpr as a keyword In-Reply-To: <777248.90724.qm@web33511.mail.mud.yahoo.com> References: <777248.90724.qm@web33511.mail.mud.yahoo.com> Message-ID: <465E2BFD.3000405@canterbury.ac.nz> Steve Howell wrote: > I don't mean to oversimplify this, which is why I'm > batting it around on a forum with a lot of smart > people. But clearly it could be done. Whether it > *should* be done is, of course, a question for debate, > and I accept this. My objection this idea is that it's going in the opposite direction to what I'd like to see. In my opinion, having to embed one programming language inside another leads to ugly code. I would rather have an elegant way to deal with relational databases by writing Python code *instead* of SQL, than yet another mechanism for embedding SQL in Python. -- Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | Carpe post meridiem! | Christchurch, New Zealand | (I'm not a morning person.) | greg.ewing at canterbury.ac.nz +--------------------------------------+ From steven.bethard at gmail.com Thu May 31 04:22:01 2007 From: steven.bethard at gmail.com (Steven Bethard) Date: Wed, 30 May 2007 20:22:01 -0600 Subject: [Python-ideas] proposal to add rowexpr as a keyword In-Reply-To: <860739.28878.qm@web33506.mail.mud.yahoo.com> References: <860739.28878.qm@web33506.mail.mud.yahoo.com> Message-ID: On 5/30/07, Steve Howell wrote: > ======= THEORETICAL > > Valid Python: > > row = {'salary': 50000} > def convert_to_euros(amt): return amt / 2 > x = rowexpr: convert_to_euros(salary) > print x(row) # prints 25000 >>> def rowexpr(expr): ... def evaluate(row): ... d = dict(row) ... d.update(globals()) ... exec '__result__ = ' + expr in d ... return d['__result__'] ... return evaluate ... >>> def convert_to_euros(amt): ... return amt / 2 ... >>> x = rowexpr('convert_to_euros(salary)') >>> row = dict(salary=50000) >>> print x(row) 25000 STeVe -- I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a tiny blip on the distant coast of sanity. --- Bucky Katt, Get Fuzzy From showell30 at yahoo.com Thu May 31 04:33:33 2007 From: showell30 at yahoo.com (Steve Howell) Date: Wed, 30 May 2007 19:33:33 -0700 (PDT) Subject: [Python-ideas] proposal to add rowexpr as a keyword In-Reply-To: <465E2BFD.3000405@canterbury.ac.nz> Message-ID: <679178.87771.qm@web33514.mail.mud.yahoo.com> --- Greg Ewing wrote: > > I would rather have an elegant way to deal with > relational databases by writing Python code > *instead* > of SQL, than yet another mechanism for embedding > SQL in Python. > You're wanting to solve a slightly different problem than I was, but can you elaborate on this a bit? How do you currently interact with relational databases? Are you objecting to some ugliness of SQL itself, or do you want a more powerful abstraction? To the extent that I have to work with awkward legacy database structures, I find that my strategy is usually this: 1) Write minimal SQL to get most of the data that I need up front. 2) Manipulate the data many ways in Python. 3) Write minimal SQL to put data back in the database. ____________________________________________________________________________________ Be a PS3 game guru. Get your game face on with the latest PS3 news and previews at Yahoo! Games. http://videogames.yahoo.com/platform?platform=120121 From aahz at pythoncraft.com Thu May 31 04:59:33 2007 From: aahz at pythoncraft.com (Aahz) Date: Wed, 30 May 2007 19:59:33 -0700 Subject: [Python-ideas] proposal to add rowexpr as a keyword In-Reply-To: <998077.51447.qm@web33510.mail.mud.yahoo.com> References: <20070530004951.GA17586@panix.com> <998077.51447.qm@web33510.mail.mud.yahoo.com> Message-ID: <20070531025933.GA22999@panix.com> On Tue, May 29, 2007, Steve Howell wrote: > > Do you understand at least my motivation, if not necessarily agreeing > with the wisdom of my overall proposal? Sort of. I still think that your proposal deserves to be shot down for the same reasons that including regexes as part of the language should be shot down. I'm slightly less opposed to Talin's DSL idea, though. -- Aahz (aahz at pythoncraft.com) <*> http://www.pythoncraft.com/ "as long as we like the same operating system, things are cool." --piranha From aahz at pythoncraft.com Thu May 31 05:02:05 2007 From: aahz at pythoncraft.com (Aahz) Date: Wed, 30 May 2007 20:02:05 -0700 Subject: [Python-ideas] Idea: The DSL operator. In-Reply-To: References: Message-ID: <20070531030205.GB22999@panix.com> On Tue, May 29, 2007, Talin wrote: > > This is in response to the various suggestions for embedding SQL > syntax in Python and various other suggestions made over the years. Why not try to figure out a way to build a Quixote-like system into Python? IOW, any DSL should *not* go into Python files; instead, they should go into separate files that can be processed by the Python parser and then executed. -- Aahz (aahz at pythoncraft.com) <*> http://www.pythoncraft.com/ "as long as we like the same operating system, things are cool." --piranha From greg.ewing at canterbury.ac.nz Thu May 31 05:05:52 2007 From: greg.ewing at canterbury.ac.nz (Greg Ewing) Date: Thu, 31 May 2007 15:05:52 +1200 Subject: [Python-ideas] About list comprehension syntax In-Reply-To: <8C1BDF74-1DAB-4F64-A28E-16788C48AA95@marooned.org.uk> References: <8C1BDF74-1DAB-4F64-A28E-16788C48AA95@marooned.org.uk> Message-ID: <465E3B90.1030701@canterbury.ac.nz> Arnaud Delobelle wrote: > Why not just drop the 'x for' at the start of a 'filter > comprehension' (or generator expression)? Thus (3) could be written > more simply as: > > (3') [x in L if p(x)] It would be very nice, but could be difficult to parse, because there's no clue you're not looking at a normal list constructor until you get to the 'if'. -- Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | Carpe post meridiem! | Christchurch, New Zealand | (I'm not a morning person.) | greg.ewing at canterbury.ac.nz +--------------------------------------+ From showell30 at yahoo.com Thu May 31 05:24:59 2007 From: showell30 at yahoo.com (Steve Howell) Date: Wed, 30 May 2007 20:24:59 -0700 (PDT) Subject: [Python-ideas] proposal to add rowexpr as a keyword In-Reply-To: Message-ID: <928379.98919.qm@web33505.mail.mud.yahoo.com> --- Steven Bethard wrote: > >>> def rowexpr(expr): > ... def evaluate(row): > ... d = dict(row) > ... d.update(globals()) > ... exec '__result__ = ' + expr in d > ... return d['__result__'] > ... return evaluate > ... > >>> def convert_to_euros(amt): > ... return amt / 2 > ... > >>> x = rowexpr('convert_to_euros(salary)') > >>> row = dict(salary=50000) > >>> print x(row) > 25000 > Thanks. I tried it out with a slightly more involved expression. x = rowexpr( 'convert_to_euros(salary) ' 'if dept == "foo" else 0') rows = [dict(dept='foo', salary=i) for i in range(10000)] transform = [x(row) for row in rows] Here were my findings: 1) Not horribly slow. 3.4 seconds on my box for 10000 calls 2) I introduced a syntax error, and it was more clear than I thought it would be. It happens at runtime, of course, which is less than ideal, and it doesn't directly point me out to the line of code with the syntax error, but it does suggest the error: File "sql.py", line 14, in transform = [x(row) for row in rows] File "sql.py", line 5, in evaluate exec '__result__ = ' + expr in d File "", line 1 __result__ = convert_to_euros(salary) if dept = "foo" else 0 ^ SyntaxError: invalid syntax ____________________________________________________________________________________ Don't get soaked. Take a quick peak at the forecast with the Yahoo! Search weather shortcut. http://tools.search.yahoo.com/shortcuts/#loc_weather From jcarlson at uci.edu Thu May 31 06:30:55 2007 From: jcarlson at uci.edu (Josiah Carlson) Date: Wed, 30 May 2007 21:30:55 -0700 Subject: [Python-ideas] About list comprehension syntax In-Reply-To: <465E3B90.1030701@canterbury.ac.nz> References: <8C1BDF74-1DAB-4F64-A28E-16788C48AA95@marooned.org.uk> <465E3B90.1030701@canterbury.ac.nz> Message-ID: <20070530212851.86FB.JCARLSON@uci.edu> Greg Ewing wrote: > Arnaud Delobelle wrote: > > > Why not just drop the 'x for' at the start of a 'filter > > comprehension' (or generator expression)? Thus (3) could be written > > more simply as: > > > > (3') [x in L if p(x)] > > It would be very nice, but could be difficult to parse, > because there's no clue you're not looking at a normal > list constructor until you get to the 'if'. Even then it's not terribly clear except that there's a missing 'else' clause for conditionals... y = [x in L if p(x) else None] Will create a list of a single value in Python 2.5 . - Josiah From talin at acm.org Thu May 31 06:28:53 2007 From: talin at acm.org (Talin) Date: Wed, 30 May 2007 21:28:53 -0700 Subject: [Python-ideas] Idea: The DSL operator. In-Reply-To: <20070531030205.GB22999@panix.com> References: <20070531030205.GB22999@panix.com> Message-ID: <465E4F05.1070404@acm.org> Aahz wrote: > On Tue, May 29, 2007, Talin wrote: >> This is in response to the various suggestions for embedding SQL >> syntax in Python and various other suggestions made over the years. > > Why not try to figure out a way to build a Quixote-like system into > Python? IOW, any DSL should *not* go into Python files; instead, they > should go into separate files that can be processed by the Python parser > and then executed. That really depends on the DSL. Some DSLs want to be embedded - having to segregate SQL query statements into a separate file is a non-starter IMHO. -- Talin From showell30 at yahoo.com Thu May 31 06:37:49 2007 From: showell30 at yahoo.com (Steve Howell) Date: Wed, 30 May 2007 21:37:49 -0700 (PDT) Subject: [Python-ideas] proposal to add rowexpr as a keyword In-Reply-To: <20070531025933.GA22999@panix.com> Message-ID: <64476.28634.qm@web33514.mail.mud.yahoo.com> --- Aahz wrote: > On Tue, May 29, 2007, Steve Howell wrote: > > > > Do you understand at least my motivation, if not > necessarily agreeing > > with the wisdom of my overall proposal? > > Sort of. I still think that your proposal deserves > to be shot down for > the same reasons that including regexes as part of > the language should be > shot down. I'm slightly less opposed to Talin's DSL > idea, though. The more I think about the general themes in this discussion, the more I think PyPy is gonna be the proving ground for those kind of ideas. ____________________________________________________________________________________Shape Yahoo! in your own image. Join our Network Research Panel today! http://surveylink.yahoo.com/gmrs/yahoo_panel_invite.asp?a=7 From steven.bethard at gmail.com Thu May 31 07:38:40 2007 From: steven.bethard at gmail.com (Steven Bethard) Date: Wed, 30 May 2007 23:38:40 -0600 Subject: [Python-ideas] proposal to add rowexpr as a keyword In-Reply-To: <928379.98919.qm@web33505.mail.mud.yahoo.com> References: <928379.98919.qm@web33505.mail.mud.yahoo.com> Message-ID: On 5/30/07, Steve Howell wrote: > --- Steven Bethard wrote: > > >>> def rowexpr(expr): > > ... def evaluate(row): > > ... d = dict(row) > > ... d.update(globals()) > > ... exec '__result__ = ' + expr in d > > ... return d['__result__'] > > ... return evaluate > > ... [snip] > I tried it out with a slightly more involved > expression. > > x = rowexpr( > 'convert_to_euros(salary) ' > 'if dept == "foo" else 0') > rows = [dict(dept='foo', salary=i) for i in > range(10000)] > transform = [x(row) for row in rows] > > Here were my findings: > > 1) Not horribly slow. > > 3.4 seconds on my box for 10000 calls > > 2) I introduced a syntax error, and it was more clear > than I thought it would be. It happens at runtime, of > course, which is less than ideal You can get the syntax error a little earlier (at the time of the rowexpr() call) by using compile():: >>> def rowexpr(expr): ... code = compile('__result__ = ' + expr, '', 'exec') ... def evaluate(row): ... d = dict(globals()) ... d.update(row) ... exec code in d ... return d['__result__'] ... return evaluate ... >>> def convert_to_euros(amt): ... return amt / 2 ... >>> x = rowexpr('convert_to_euros(salary)') >>> row = dict(salary=50000) >>> print x(row) 25000 >>> rowexpr('convert_to_euros(salary) if dept = "foo" else 0') Traceback (most recent call last): File "", line 1, in File "", line 2, in rowexpr File "", line 1 __result__ = convert_to_euros(salary) if dept = "foo" else 0 ^ SyntaxError: invalid syntax STeVe -- I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a tiny blip on the distant coast of sanity. --- Bucky Katt, Get Fuzzy From greg.ewing at canterbury.ac.nz Thu May 31 08:23:14 2007 From: greg.ewing at canterbury.ac.nz (Greg Ewing) Date: Thu, 31 May 2007 18:23:14 +1200 Subject: [Python-ideas] proposal to add rowexpr as a keyword In-Reply-To: <679178.87771.qm@web33514.mail.mud.yahoo.com> References: <679178.87771.qm@web33514.mail.mud.yahoo.com> Message-ID: <465E69D2.4050100@canterbury.ac.nz> Steve Howell wrote: > You're wanting to solve a slightly different problem > than I was, but can you elaborate on this a bit? I know, it's more or less the complementary problem to what you're talking about. My point is that I don't like embedding SQL in my Python even when I'm dealing with a relational database, so I'm even less inclined to do so when dealing with Python data structures. I find that the existing features of the Python language do that well enough already. > Are you objecting to some ugliness of SQL itself, or > do you want a more powerful abstraction? Some of both. There's the general awkwardness involved whenever one language is embedded in another, plus the fact that I don't particularly like some aspects of SQL in particular. But often I also want a more powerful abstraction. The SQL that I need at a given point in the program isn't always fixed, and I need to generate it dynamically. As an example, in a recent project I needed to extract data from a number of tables to produce a report. The user has a variety of choices as to which fields are included in the report, and can optionally specify selection criteria for various fields, either a single value or a range of values. To accommodate this efficiently, I have to dynamically generate an SQL statement which includes or excludes 'where' clause terms of various sorts, and joins as necessary to pull in requested data from auxiliary tables. In this kind of application, there are few or no complete SQL statements written into the source, only fragments that get combined by an SQL-generation framework of some kind. So a facility like the one you suggest wouldn't help with this kind of problem. -- Greg From showell30 at yahoo.com Thu May 31 08:39:05 2007 From: showell30 at yahoo.com (Steve Howell) Date: Wed, 30 May 2007 23:39:05 -0700 (PDT) Subject: [Python-ideas] proposal to add rowexpr as a keyword In-Reply-To: <465E69D2.4050100@canterbury.ac.nz> Message-ID: <988912.85401.qm@web33508.mail.mud.yahoo.com> --- Greg Ewing wrote: > > To accommodate this efficiently, I have to > dynamically > generate an SQL statement which includes or excludes > 'where' clause terms of various sorts, and joins > as necessary to pull in requested data from > auxiliary > tables. > I can definitely relate to that sort of pain. ____________________________________________________________________________________Building a website is a piece of cake. Yahoo! Small Business gives you all the tools to get online. http://smallbusiness.yahoo.com/webhosting From bborcic at gmail.com Thu May 31 11:51:54 2007 From: bborcic at gmail.com (Boris Borcic) Date: Thu, 31 May 2007 11:51:54 +0200 Subject: [Python-ideas] About list comprehension syntax In-Reply-To: References: <8C1BDF74-1DAB-4F64-A28E-16788C48AA95@marooned.org.uk> Message-ID: Terry Reedy wrote: > "Arnaud Delobelle" ... > | Thus (3) could be written more simply as: > | > | (3') [x in L if p(x)] > > (x in L) is a legal expression already. That's the only real issue IMO - and I agree there is no acceptable solution. > (x in L) if p(x) looks like the > beginning of (x in L) if p(x) else 'blah' . The whole thing looks like a > list literal with an incompletely specified one element. > > | This is consistent with common mathematical notation: > > 'Common mathematical notation' is not codified and varies from writer to > writer and even within the work of one writer. Humans make do and make > guesses, but parser programs are less flexible. I guess it also depends on how much math (eg theorem proofs) one had to deal with. FWIW, it took me months to adapt to the correct Python listcomp/genexp syntax, after being bitten dozens of times by Python not accepting Arnaud's (3') form above. The latter was *much* more natural to my fingers. Cheers, BB From ali.sabil at gmail.com Thu May 31 15:15:11 2007 From: ali.sabil at gmail.com (Ali Sabil) Date: Thu, 31 May 2007 15:15:11 +0200 Subject: [Python-ideas] Attribute Docstrings and Annotations Message-ID: <6b4de4d80705310615j5cf712fdldb5e685d2c4a4a7a@mail.gmail.com> Hello all, I was looking into function annotations, that are to be introduced in Python3k, and I found this old message sent to this mailing list : http://mail.python.org/pipermail/python-ideas/2007-January/000037.html I would like to restart the discussion of attribute annotation, because in my opinion it can be a very powerful feature. I personally think about using it for SOAP message serialization, or any kind of XML serialization, the Idea would be to annotate various object attribues to be either marshaled as XML Elements or XML Attributes of the current Node that reflects the Object. Thank you, -- Ali -------------- next part -------------- An HTML attachment was scrubbed... URL: