Re: Question about consistency in python language
Also, you shouldn't use 1, I mean l, as a variable name. It gets confusing because l, I mean 1, looks a lot like 1, I mean l. I have seen the same warnning above significantly several times. Is this problem originally came from the similarities between 'l' and '1' or from bad looking news-browser? Forgive me if it is out of your interests. -James GOLD -- http://mail.python.org/mailman/listinfo/python-list
Re: Question about consistency in python language
Steve Holden wrote: Kay Schluehr wrote: Mike Meyer wrote: Yes, but the function sorted is more useful than a list method sorted in a duck typing language. I don't see what this has to do with duck typing? sorted() is simply a generic function accepting different types. I'm not aware that sorted() requires a specific interface of those types it accepts. Just because you aren't aware of something doesn't stop it being true. The argument must be iterable, and there's a specific protocol for that. The function sorted works on all iterators. I can do: Ah, so you *were* aware of it. I already responded to it two days ago in the reply to Terry. No need to rehash that. def t(n): for i in range(n): yield i ... print sorted(t(5)) and have it work. If sorted were a method of a class - the it'd have to be implemented again for every class iterable class. Either that, or you'd have to create an abstract parent of all iterable classes to add it to - which seems more appropriate for a BD language than Python. Instead of extending a class hierarchy it might even be possible to hook a trait into the class by means of a __traits__ attribute. http://fsl.cs.uiuc.edu/~mhills/presentations/TraitsPresentation.pdf Generators as well as lists and tuples would provide a sortable trait. The sorted() function could remain available for convenience. The advantage being ... ? Perhaps you have just discovered a really interesting hammer, and are seeing this problem as a nail? I also responded to traits as nice-to-have but not essential. And please don't aggressively consider me as childish as you might be yourself. Adding a __traits__ attribute should enable the user adding methods to builtins in a safe manner. This has the advantage that one can apply methods to string or integer literals or even replace methods without touching the C sources. A very typical use case is integer representation. In 95% of all my business applications I don't have much use for decimal integer representation but want a hex rep in different variants: 0x0F # current rep 15 int.__traits__.append(HexRepTrait) # used for delegation of # __repr__ to the Trait int.configure_format(HexRepTrait.HEXFORM_STD) # configure_format is a # hooked trait method 0x0F 0F 2*0x800 10 00 print 700 02 BC I know I can write wrapper classes, because I do this all the time, but that's not the point: Python is essentially not about boiler-plate. And no, I also don't want to fight for each method and keyword with Guido. And even if you do add the abstract class, how do you make my example work without explictly converting the iterator to a list type? I don't know how sorted() is implemented? A naive implementation would in fact be nothing else then: def sorted(iter): l = list(iter) l.sort() return l Kay That would indeed be a naïve implementation. And that's the real implementation: static PyObject * builtin_sorted(PyObject *self, PyObject *args, PyObject *kwds) { PyObject *newlist, *v, *seq, *compare=NULL, *keyfunc=NULL, *newargs; PyObject *callable; static char *kwlist[] = {iterable, cmp, key, reverse, 0}; long reverse; if (args != NULL) { if (!PyArg_ParseTupleAndKeywords(args, kwds, O|OOi:sorted, kwlist, seq, compare, keyfunc, reverse)) return NULL; } newlist = PySequence_List(seq); if (newlist == NULL) return NULL; callable = PyObject_GetAttrString(newlist, sort); if (callable == NULL) { Py_DECREF(newlist); return NULL; } newargs = PyTuple_GetSlice(args, 1, 4); if (newargs == NULL) { Py_DECREF(newlist); Py_DECREF(callable); return NULL; } v = PyObject_Call(callable, newargs, kwds); Py_DECREF(newargs); Py_DECREF(callable); if (v == NULL) { Py_DECREF(newlist); return NULL; } Py_DECREF(v); return newlist; } The crucial steps are the conversion from args to seq, the conversion from seq to newlist and finally calling PyObject_Call(callable, ...) where callable stores the sort method of newlist. By the way I don't see much use in implementing this trivial wrapper function in C except for the joy of refcounting ;) And now we take a look on how the PyPythonistas implemented sorted(): def sorted(lst, cmp=None, key=None, reverse=None): sorted(iterable, cmp=None, key=None, reverse=False) -- new sorted list sorted_lst = list(lst) sorted_lst.sort(cmp, key, reverse) return sorted_lst Surprise, surprise! The implementation is, of course, an implementation detail ;-) In this case it requires
Re: Question about consistency in python language
James wrote: [James Stroud wrote:] Also, you shouldn't use 1, I mean l, as a variable name. It gets confusing because l, I mean 1, looks a lot like 1, I mean l. I have seen the same warnning above significantly several times. Is this problem originally came from the similarities between 'l' and '1' or from bad looking news-browser? Forgive me if it is out of your interests. In many, many fonts 'l' and '1' look close enough to be easily mistaken for one another, especially for people whose vision isn't perfect. The problem exists in the fonts people view and edit code with, not just newsreaders. -- Robert Kern [EMAIL PROTECTED] In the fields of hell where the grass grows high Are the graves of dreams allowed to die. -- Richard Harter -- http://mail.python.org/mailman/listinfo/python-list
Re: Question about consistency in python language
Robert Kern [EMAIL PROTECTED] wrote in message news:[EMAIL PROTECTED] In many, many fonts 'l' and '1' look close enough to be easily mistaken for one another In the default font used by Outlook Express, displayed on my 1078x786 screen, the only difference I can see, using a magnifying glass on side-by-side characters (l1 = el-onel), is that 'el' is one pixel taller than the 'one'. The serifs appear the same, down to the anti-alias gray pixels. (To my surprise, this makes 'lbdk' a pixel taller than uppercase chars!) Now I know ;-). But 1 isolated from l is still difficult to distinguish. Terry J. Reedy -- http://mail.python.org/mailman/listinfo/python-list
Re: Question about consistency in python language
Kay Schluehr wrote: Mike Meyer wrote: Yes, but the function sorted is more useful than a list method sorted in a duck typing language. I don't see what this has to do with duck typing? sorted() is simply a generic function accepting different types. I'm not aware that sorted() requires a specific interface of those types it accepts. Just because you aren't aware of something doesn't stop it being true. The argument must be iterable, and there's a specific protocol for that. The function sorted works on all iterators. I can do: Ah, so you *were* aware of it. def t(n): for i in range(n): yield i ... print sorted(t(5)) and have it work. If sorted were a method of a class - the it'd have to be implemented again for every class iterable class. Either that, or you'd have to create an abstract parent of all iterable classes to add it to - which seems more appropriate for a BD language than Python. Instead of extending a class hierarchy it might even be possible to hook a trait into the class by means of a __traits__ attribute. http://fsl.cs.uiuc.edu/~mhills/presentations/TraitsPresentation.pdf Generators as well as lists and tuples would provide a sortable trait. The sorted() function could remain available for convenience. The advantage being ... ? Perhaps you have just discovered a really interesting hammer, and are seeing this problem as a nail? And even if you do add the abstract class, how do you make my example work without explictly converting the iterator to a list type? I don't know how sorted() is implemented? A naive implementation would in fact be nothing else then: def sorted(iter): l = list(iter) l.sort() return l Kay That would indeed be a naïve implementation. The implementation is, of course, an implementation detail ;-) In this case it requires that sort() then provides all the magic - the need for magic doesn't go away! regards Steve -- Steve Holden +44 150 684 7255 +1 800 494 3119 Holden Web LLC http://www.holdenweb.com/ -- http://mail.python.org/mailman/listinfo/python-list
Re: Question about consistency in python language
[EMAIL PROTECTED] wrote: Let's say I define a list of pairs as follows: l = [('d', 3), ('a', 2), ('b', 1)] Can anyone explain why this does not work? h = {}.update(l) and instead I have to go: h = {} h.update(l) to initialize a dictionary with the given list of pairs? when an analagous operation on strings works fine: s = .join([d,o,g]) Seems inconsistent. If you define sep = sep.join([d,o,g]) dog sep '' sep is preserved and a new dog string is generated. Since sep is immutable there is no way to manipulate it inplace. On the other hand there exists no sorted() method for tuples or lists like join() for strings but it is implemented as a function in Python24 that returns a new sorted container. I consider this as an inconsistency across builtin types. Consistent would be following usage pattern: l = [1,3,2] l.sorted() [1,2,3] # new sorted list l.sort()# sort list inplace l.appended(4) # new extended list [1,2,3,4] l.append(4) # appends an element to the same list l [1,2,3,4] Preserving the naming convention we would have .joined([d,o,g]) dog Kay -- http://mail.python.org/mailman/listinfo/python-list
Re: Question about consistency in python language
Dave Benjamin [EMAIL PROTECTED] writes: Mike Meyer wrote: Dave Benjamin [EMAIL PROTECTED] writes: Python is actually quite consistent in this regard: methods that modify an object in-place return None; Um, no. list.pop comes to mind as an immediate counterexample. It may be the only one... I've never had to look up the return type of pop though. The only thing even remotely ambigious about that term (at least, if you've learned what a stack is) is whether it mutates the object, but I don't think I've ever seen a pop that didn't (aside from toy examples in formal methods / ADT related classes). Eiffel STACK class has a pop that dosn't return a value - at least in SmartEiffel. On the other hand, Eiffel makes a *big* deal about the difference between command features - which change the state - and query features - which report on the state. That distinction even shows up in the threading model for Eiffel. os.system might be a better example, since the return value could be one of two obvious things: the status code, or the program's output. To me, os.system obviously returns the status code. Then again, I know it's just the unix system() routine, which I've know *much* longer than there's been a Python. The point is that what's obvious depends on where you're coming from. If your background is as a Unix developer, the result of os.system is obvious. If your background is Eiffel or some other strong ADT area, that pop has a result at all may surprise you. mike -- Mike Meyer [EMAIL PROTECTED] http://www.mired.org/home/mwm/ Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information. -- http://mail.python.org/mailman/listinfo/python-list
Re: Question about consistency in python language
Kay Schluehr [EMAIL PROTECTED] writes: If you define sep = sep.join([d,o,g]) dog sep '' sep is preserved and a new dog string is generated. Since sep is immutable there is no way to manipulate it inplace. On the other hand there exists no sorted() method for tuples or lists like join() for strings but it is implemented as a function in Python24 that returns a new sorted container. I consider this as an inconsistency across builtin types. Consistent would be following usage pattern: l = [1,3,2] l.sorted() [1,2,3] # new sorted list l.sort()# sort list inplace l.appended(4) # new extended list [1,2,3,4] l.append(4) # appends an element to the same list l [1,2,3,4] Yes, but the function sorted is more useful than a list method sorted in a duck typing language. The function sorted works on all iterators. I can do: def t(n): for i in range(n): yield i ... print sorted(t(5)) and have it work. If sorted were a method of a class - the it'd have to be implemented again for every class iterable class. Either that, or you'd have to create an abstract parent of all iterable classes to add it to - which seems more appropriate for a BD language than Python. And even if you do add the abstract class, how do you make my example work without explictly converting the iterator to a list type? mike -- Mike Meyer [EMAIL PROTECTED] http://www.mired.org/home/mwm/ Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information. -- http://mail.python.org/mailman/listinfo/python-list
Re: Question about consistency in python language
Kay Schluehr [EMAIL PROTECTED] wrote in message news:[EMAIL PROTECTED] On the other hand there exists no sorted() method for tuples or lists like join() for strings but it is implemented as a function in Python24 that returns a new sorted container. I consider this as an inconsistency across builtin types. The sorted function is not a list method because it is not only a list function or even only a tuple and list function or even only a string, tuple, list, array, or dict function. Its input is **any** iterable. The only way to have it both be general and a method would be to have an iterable type and to require that all iterables inherit from that type to reap the benefit of being an iterable. All the itertools functions are also functions and not methods of a hypothetical iterable type. 'Iterable' is a duck type and hence functions thereof must be functions and not methods. Terry J. Reedy -- http://mail.python.org/mailman/listinfo/python-list
Re: Question about consistency in python language
Mike Meyer wrote: Yes, but the function sorted is more useful than a list method sorted in a duck typing language. I don't see what this has to do with duck typing? sorted() is simply a generic function accepting different types. I'm not aware that sorted() requires a specific interface of those types it accepts. The function sorted works on all iterators. I can do: def t(n): for i in range(n): yield i ... print sorted(t(5)) and have it work. If sorted were a method of a class - the it'd have to be implemented again for every class iterable class. Either that, or you'd have to create an abstract parent of all iterable classes to add it to - which seems more appropriate for a BD language than Python. Instead of extending a class hierarchy it might even be possible to hook a trait into the class by means of a __traits__ attribute. http://fsl.cs.uiuc.edu/~mhills/presentations/TraitsPresentation.pdf Generators as well as lists and tuples would provide a sortable trait. The sorted() function could remain available for convenience. And even if you do add the abstract class, how do you make my example work without explictly converting the iterator to a list type? I don't know how sorted() is implemented? A naive implementation would in fact be nothing else then: def sorted(iter): l = list(iter) l.sort() return l Kay -- http://mail.python.org/mailman/listinfo/python-list
Re: Question about consistency in python language
Terry Reedy wrote: Kay Schluehr [EMAIL PROTECTED] wrote in message news:[EMAIL PROTECTED] On the other hand there exists no sorted() method for tuples or lists like join() for strings but it is implemented as a function in Python24 that returns a new sorted container. I consider this as an inconsistency across builtin types. The sorted function is not a list method because it is not only a list function or even only a tuple and list function or even only a string, tuple, list, array, or dict function. Its input is **any** iterable. The only way to have it both be general and a method would be to have an iterable type and to require that all iterables inherit from that type to reap the benefit of being an iterable. All the itertools functions are also functions and not methods of a hypothetical iterable type. 'Iterable' is a duck type and hence functions thereof must be functions and not methods. Terry J. Reedy So what? Then an iterable class providing the __iter__ method may be factored out as Mike reasonably suggested ( I was wrong with my remark about duck-typing. The __iter__ method may be the interface I claimed not being aware of ). Or a sortable trait gets used as I would slightly prefer - but it's not necassary. To be honest I'm not sure what all the BDFLs Javaesque interfaces and optional static typing blabla for Py3K should matter if it's not even possible to create obvious inheritance hierarchies in favour for accidental generic functions? Kay -- http://mail.python.org/mailman/listinfo/python-list
Question about consistency in python language
Let's say I define a list of pairs as follows: l = [('d', 3), ('a', 2), ('b', 1)] Can anyone explain why this does not work? h = {}.update(l) and instead I have to go: h = {} h.update(l) to initialize a dictionary with the given list of pairs? when an analagous operation on strings works fine: s = .join([d,o,g]) Seems inconsistent. thanks, Scott -- http://mail.python.org/mailman/listinfo/python-list
Re: Question about consistency in python language
This is the difference between mutable and immutable types. In this sense it is consistent. If you want to do the former in one shot: h = dict(l) Also, you shouldn't use 1, I mean l, as a variable name. It gets confusing because l, I mean 1, looks a lot like 1, I mean l. James On Thursday 08 September 2005 16:03, [EMAIL PROTECTED] wrote: Let's say I define a list of pairs as follows: l = [('d', 3), ('a', 2), ('b', 1)] Can anyone explain why this does not work? h = {}.update(l) and instead I have to go: h = {} h.update(l) to initialize a dictionary with the given list of pairs? when an analagous operation on strings works fine: s = .join([d,o,g]) Seems inconsistent. thanks, Scott -- James Stroud UCLA-DOE Institute for Genomics and Proteomics Box 951570 Los Angeles, CA 90095 http://www.jamesstroud.com/ -- http://mail.python.org/mailman/listinfo/python-list
Re: Question about consistency in python language
update updates the dictionary in place - it actually returns None, not the updated dict. However, you can construct a dictionary from a list of (key, value) pairs using dict(list). Example: l = [('foo', 'bar'), ('baz', 'qig')] d = dict(l) print d {'foo': 'bar', 'baz': 'qig'} -- http://mail.python.org/mailman/listinfo/python-list
Re: Question about consistency in python language
On 8 Sep 2005 16:03:12 -0700, [EMAIL PROTECTED] wrote: Let's say I define a list of pairs as follows: l = [('d', 3), ('a', 2), ('b', 1)] Can anyone explain why this does not work? h = {}.update(l) and instead I have to go: h = {} h.update(l) to initialize a dictionary with the given list of pairs? when an analagous operation on strings works fine: s = .join([d,o,g]) Seems inconsistent. Join isn't that good an analogy, because the inputs and outputs are immutable. list.sort is more comparable to dict.update. There is now a builtin sorted function that will take a list and return a sorted one. Perhaps there will come an updated function analogously for dictionaries, but I don't think the use is that common, and you can make your own. Several ways. If you want to start with an empty dict anyway, the dict constructor will accept a sequence of pairs (so long as the first of every pair is hashable, which is also required for update). E.g., dict([('d', 3), ('a', 2), ('b', 1)]) {'a': 2, 'b': 1, 'd': 3} or the sequence of pairs as a tuple expression dict((('d', 3), ('a', 2), ('b', 1))) {'a': 2, 'b': 1, 'd': 3} or sometimes it's handy to start with the keys and values as separate sequences and zip them together for the dict constructor dict(zip('dab', [3,2,1])) {'a': 2, 'b': 1, 'd': 3} or a generator expression dict((k,3-i) for i,k in enumerate('dab')) {'a': 2, 'b': 1, 'd': 3} though note that dict wants the sequence as a single argument: dict( ('d', 3), ('a', 2), ('b', 1) ) Traceback (most recent call last): File stdin, line 1, in ? TypeError: dict expected at most 1 arguments, got 3 def updated(d, seq): d=d.copy(); d.update(seq); return d ... updated({}, [('d', 3), ('a', 2), ('b', 1)]) {'a': 2, 'b': 1, 'd': 3} One rationale for not returning a reference to the mutated value from a mutating method is that it is too easy to think of it as a pure expression, and forget the persistent side effect of mutating the object. I think that was thought too bug-prone. Regards, Bengt Richter -- http://mail.python.org/mailman/listinfo/python-list
Re: Question about consistency in python language
[EMAIL PROTECTED] wrote: Let's say I define a list of pairs as follows: l = [('d', 3), ('a', 2), ('b', 1)] Can anyone explain why this does not work? h = {}.update(l) and instead I have to go: h = {} h.update(l) to initialize a dictionary with the given list of pairs? when an analagous operation on strings works fine: s = .join([d,o,g]) Seems inconsistent. Python is actually quite consistent in this regard: methods that modify an object in-place return None; methods that do not modify an object in-place return a new object instead. Since strings are immutable, they cannot be modified in-place, so it makes sense for the join method to return a new string. On the other hand, Python's dictionaries are imperative-style and so most operations on a dictionary modify an existing dictionary. I was initially bothered by the phenomenon of so many methods returning None because they could not be chained. But I have come to deeply appreciate this style for a couple of reasons. First, it makes it clear which methods are side-effecting (like update) and which are not (like sort). Second, it is not always clear what a good return value is for a mutator. Perhaps {}.update() should return the dictionary, making chaining convenient. Perhaps it should return the total number of items after updating. Or maybe it should return the number of new keys that were added, or a list of those keys. All of these are plausible behaviors; the problem is that update is not a function. Its job is to change something, not return something. Any possible return value would be a convenience for certain tasks and useless for other tasks. It's also hard to remember, in my opinion. For example, JavaScript has a push method on the Array object which behaves like Python's append method on lists: js var a = []; js a.push(5); 1 js a.push(6); 2 I bet you that almost nobody knows that push returns the new length of the Array. It could just as easily have returned a here. I could always write a.length, if I really needed to know the new length. This sort of thing becomes language trivia, and when I write in JavaScript I always ignore the result of push because, even if *I* know what it returns, chances are that my readers don't. Another reason that Python adopts the convention of returning None for mutators is that it discourages the use of side-effecting code in expressions. Mixing side-effects with expressions can lead to code that is hard to read and understand. This is often debated by those who know better and wish to write things like h.update(a).update(b) (method chaining) or while (line = file.readline()): Python's decision is pretty clear, and it's also evident in the division between statements and expressions. Regardless of whether you like Python's style decision or not, if you dig deeper I think you will find that it is pretty consistent, and that there are useful benefits to Python's way of handling side effects. Dave PS. If mutators had to return a value, I'd have them return self, probably 95% of the time. But then, it wouldn't be Python anymore. It'd be Ruby, maybe. -- http://mail.python.org/mailman/listinfo/python-list
Re: Question about consistency in python language
Dave Benjamin [EMAIL PROTECTED] writes: Python is actually quite consistent in this regard: methods that modify an object in-place return None; Um, no. list.pop comes to mind as an immediate counterexample. It may be the only one... mike -- Mike Meyer [EMAIL PROTECTED] http://www.mired.org/home/mwm/ Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information. -- http://mail.python.org/mailman/listinfo/python-list