Re: Coding style
Bruno Desthuilliers [EMAIL PROTECTED] schrieb: Carl Banks wrote: Bruno Desthuilliers wrote: I'm well aware of Python's semantics, and it's irrelvant to my argument. [...] If the language were designed differently, then the rules would be different. Totally true - and totally irrelevant IMHO. I strongly advise not to treat each others thoughts as irrelevant. Assuming the opposite is a base of every public dicussion forum. I assume here is a flaw in Python. To explain this, I'd like to make Bruno's point clearer. As usually, code tells more then thousand words (an vice versa :-)). Suppose you have two functions which somehow depend on the emptyness of a sequence. This is a stupid example, but it demonstrates at least the two proposed programming styles: -- def test1(x): ... if x: ... print Non-Empty ... else: ... print Empty ... def test2(x): ... if len(x) 0: ... print Non-Empty ... else: ... print Empty -- Bruno pointed out a subtle difference in the behaviour of those functions: -- a = [] test1(a) Empty test1(iter(a)) Non-Empty test2(a) Empty test2(iter(a)) Traceback (most recent call last): File stdin, line 1, in ? File stdin, line 2, in test2 TypeError: len() of unsized object -- While test1() returns a wrong/random result when called with an iterator, the test2() function breaks when beeing called wrongly. So if you accidently call test1() with an iterator, the program will do something unintended, and the source of that bug will be hard to find. So Bruno is IMHO right in calling that the source of a suptle bug. However, if you call test2() with an iterator, the program will cleanly break early enough with an exception. That is generally wanted in Python. You can see this all over the language, e.g. with dictionaries: -- d = { 'one': 1 } print d['one'] 1 print d['two'] Traceback (most recent call last): File stdin, line 1, in ? KeyError: 'two' -- Python could have been designed to return None when d['two'] has been called, as some other (bad) programming languages would. This would mean that the problem will occur later in the program, making it easy to produce a subtle bug. It would be some effort to figure out the real cause, i.e. that d had no entry for 'two'. Luckily, Python throws an exception (KeyError) just at the original place where the initial mistake occured. If you *want* to get None in case of a missing key, you'll have to say this explicitly: -- print d.get('two', None) None -- So maybe bool() should also break with an exception if an object has neither a __nonzero__ nor a __len__ method, instead of defaulting to True. Or a more strict variant of bool() called nonempty() should exist. Iterators don't have a meaningful Boolean representation, because phrases like is zero or is empty don't make sense for them. So instead of answering false, an iterator should throw an exception when beeing asked whether he's empty. If a function expects an object to have a certain protocol (e.g. sequence), and the given object doesn't support that protocol, an exception should be raised. This usually happens automatically when the function calls a non-existing method, and it plays very well with duck typing. test2() behaves that way, but test1() doesn't. The reason is a sluttery of Python. Python should handle that problem as strict as it handles a missing key in a dictionary. Unfortunately, it doesn't. I don't agree with Bruno that it's more natural to write if len(a) 0: ... instead of if a: ... But I think that this is a necessary kludge you need to write clean code. Otherwise you risk to create subtle bugs. This advise, however, only applies when your function wants a sequence, because only in that can expect len(a) to work. I also agree with Carl that if len(a) 0 is less universal than if a, because the latter also works with container-like objects that have a concept of emptiness, but not of length. However, this case is less likely to happen than shooting yourself in the foot by passing accidently an iterator to the function without getting an exception. I think, this flaw in Python is deep enough to justify the len() 0 kludge. IMHO, that flaw of Python should be documented in a PEP as it violates Python's priciple of beeing explicit. It also harms duck typing. Greets, Volker -- Volker Grabsch ---(())--- Administrator NotJustHosting GbR -- http://mail.python.org/mailman/listinfo/python-list
Re: Coding style
Bruno Desthuilliers [EMAIL PROTECTED] schrieb: PTY wrote: I was asking whether it was better style to use len() or not. FWIW, it's also more generic (you could have an object supporting pop() but not __len__()), less error-prone, While I agree with all other points, I don't think that it's less error-prone. See my other posting where I worked out this a flaw of Python. Greets, Volker -- Volker Grabsch ---(())--- Administrator NotJustHosting GbR -- http://mail.python.org/mailman/listinfo/python-list
Re: triple quoted strings as comments
Jorgen Grahn wrote: [...] developer had commented out about 50 lines of C++ code by just putting a /* at the top and a */ at the bottom. [...] (#if 0 in C and C++ are better choices, but only marginally. Best is to remove the code unless you are sure it's needed again soon. Works in all languages.) However, I'd only advise to do this if you are using a revision control. Otherwise, you'll end up having a lot of backup files hanging around which are even worse than multi-row comments. Or, even worse: If you don't create backup files before removing code ... Greets, Volker -- Volker Grabsch ---(())--- \frac{\left|\vartheta_0\times\{\ell,\kappa\in\Re\}\right|}{\sqrt [G]{-\Gamma(\alpha)\cdot\mathcal{B}^{\left[\oint\!c_\hbar\right]}}} -- http://mail.python.org/mailman/listinfo/python-list
Re: dynamic class instantiation
Kent Johnson wrote: Ognen Duzlevski wrote: I appreciate your comments. Basically, the reason why this code generator exists is the fact that I do not want to hard-code the resulting xml in any way. The users of the web/db framework of which this solution is part of might like the web page definition I offer them, but, some might want to extend it. While dom allows me to traverse an xml hierarchy - it does not allow me to give meaning to the tags. The only way to do that (for me) is to represent the tags as classes with containers containing other classes (tags) and so on. Since I do not know ahead of time what the tags will be - I need to generate the code to actually handle them. Can you suggest a better approach or did you already do that and I just missed it? :) Instead of generating Python code and importing it, you could create the classes directly. You would still have your own language but no code generator. While I agree that this is much better than code generation, why not go a step further? Your description language could be as well a subset of the Python language. So you could get rid of the parser, too. Add the meaning simply by creating subclasses in Python. This approach has the disadvantage of a slightly more complicated syntax of the definition files. However, the advantage is that this syntax would be valid Python code, so everyone who's learning it will also learn a small piece of Python, and thus reusable knowlege. Learning a special newly invented language (so-called DSL - domain specific language) is *not* resuable knowledge. The second advantage is a greater flexibility. You can use real Python code to model some more complex definition files. Otherwise, you'll have to enhance your definition language for every new feature or meta-feature you introduce. In this case, your own language would become more and more messy over time. Why don't you take a great, well-designed, simple, general purpose language which already exist? ... such as Python ;-) However, this is a completely different strategy: You wouldn't parse the defintion files. Instead, your definition files are Python modules which your application imports. This can be a security risk if you want these modules to be edited online. However, if your definition files are only put into a directory of the server, i.e. if you handle them just as your Python sources anyway, this won't be a disadvantage. (Instead, if would be a great advantage!) So you have to decide yourself: Do you really need the description files to be read in on-the-fly? Then stick with your own language. Are your definition files more like modules/extensions which are installes together with the source files? Then just *make* them source files, too, i.e. realize your description files simply as Python modules. Greets, Volker -- Volker Grabsch ---(())--- \frac{\left|\vartheta_0\times\{\ell,\kappa\in\Re\}\right|}{\sqrt [G]{-\Gamma(\alpha)\cdot\mathcal{B}^{\left[\oint\!c_\hbar\right]}}} -- http://mail.python.org/mailman/listinfo/python-list
Re: dynamic class instantiation
Ognen Duzlevski wrote: Kent Johnson [EMAIL PROTECTED] wrote: Ognen Duzlevski wrote: Say I got page as a string. How do I go about instantiating a class from this piece of information? To make it more obvious how do I create the page() class based on the page string I have? Use getattr(). Hi Kent, this is exactly what I was looking for. I can't believe I didn't think of getattr() myself! ;( However, remember that this solves your problem just temporarily. Your main problem is still a deep design failure. Code generators are relicts, hard to maintain, and usually just plain ugly. Your application isn't that special. I'm sure you could replace 2/3 of your code with something much simpler (and shorter!) just by not inventing a new language and using the power of Python instead. People often think that a new language simplifies their problem, and that code generation saves work. However, a the code of the code generator has to be maintained, too! That's what most people are realizing too late. Also, simple class inheritance, closures and similar mechanisms save a lot of work, too, they do their job even better than a code generator, and they are a charm to maintain. Even the magic (AKA meta-classes :-)) may be hard, but it's usually a much simpler and cleaner approach than a code generator. Don't generate Python code. Python is neither Java nor C, it's dynamic! Greets, Volker -- Volker Grabsch ---(())--- \frac{\left|\vartheta_0\times\{\ell,\kappa\in\Re\}\right|}{\sqrt [G]{-\Gamma(\alpha)\cdot\mathcal{B}^{\left[\oint\!c_\hbar\right]}}} -- http://mail.python.org/mailman/listinfo/python-list
Re: Python vs C for a mail server
Jens Theisen wrote: What do you do when you want to no if a certain method or function is actually used from somewhere, say foobar, it a language which allows (and even encourages) that it could be called by: getattr(obj, foo + bar)() No. The recommended way to do it is: obj.foobar() There is no systematic way to find this call. In C++, just commend out the definition and the compiler will tell you. In such a case I normally just grep for foobar. I did so (and I'll do so) in C/C++, Python, and any other language. Any programming language allows you to do strange/stupid stuff. But none of them encourages it. So I can't see your point in any way. Greets, Volker -- Volker Grabsch ---(())--- \frac{\left|\vartheta_0\times\{\ell,\kappa\in\Re\}\right|}{\sqrt [G]{-\Gamma(\alpha)\cdot\mathcal{B}^{\left[\oint\!c_\hbar\right]}}} -- http://mail.python.org/mailman/listinfo/python-list
Re: psexec and os.popen help
[EMAIL PROTECTED] wrote: popen3 did the trick. Use the modules subprocess ... it solves many problems, including the problem of too many similar functions. :-) These functions (execl, execv, popen, popen2, popen3, ...) are relicts from C and very unpythonic. It's IMHO always a better programming style to use subprocess. Greets, Volker -- Volker Grabsch ---(())--- \frac{\left|\vartheta_0\times\{\ell,\kappa\in\Re\}\right|}{\sqrt [G]{-\Gamma(\alpha)\cdot\mathcal{B}^{\left[\oint\!c_\hbar\right]}}} -- http://mail.python.org/mailman/listinfo/python-list
Re: Python linear algebra module -- requesting comments on interface
C. Barnes wrote: Hi, I'm in the process of writing a Python linear algebra module. The current targeted interface is: http://oregonstate.edu/~barnesc/temp/linalg/ Is this going to become free software. If yes, what license will you use? So my suggestions: In cases like these ones: random_matrix(m, n=-1) zero_matrix(m, n=-1) .. I think it's better to set the default value to None instead of a number: random_matrix(m, n=None) zero_matrix(m, n=None) IMHO, this is more intuitive and more pythonic. I also suggest to make the random function choosable: random_matrix(m, n=None, randfunc=random.random) random_vector(n, randfunc=random.random) This way it's more easy for those who want another range of numbers, or want another kind of distribution of the random numbers. At the top of your documentation, there is a link overview, which is broken: See _overview_ for a quick start. Greets, Volker -- Volker Grabsch ---(())--- \frac{\left|\vartheta_0\times\{\ell,\kappa\in\Re\}\right|}{\sqrt [G]{-\Gamma(\alpha)\cdot\mathcal{B}^{\left[\oint\!c_\hbar\right]}}} -- http://mail.python.org/mailman/listinfo/python-list
What license to choose for Python programs? (PSF License vs. GPL/LGPL)
Hi! I noticed that many packages in the PyPI are using the PSF License. Does this have a special reason? Is this the common standard license for Python libraries? I'm just asking because I'll release some bigger pieces of Python code to the Open Source Community. In my many projects before I just used GPL or LGPL. This didn't have a special reason. They are just standard OS licenses. I could also have used the BSD License, but I personally like the GPL/LGPL more. Of course I know that there are many, many other licenses out there. I'm not interested in comparing them all for their slight differences. I don't choose the license primarily for protecting my code. I want to choose the license according to the most common/appropriate way of the community. So if it is complicated to include an LGPL'ed Python library in the Python standard libraries, I'd release it under PSF License. I'd like to hear some opinions about that. What licenses do you use, and what's your personal reason for doing so? Also, a quick overview about the various licenses would be nice. Not a legal comparison, but a list about what type of code/programs/libs is usually released under which license. Thanks for your help, Volker -- Volker Grabsch ---(())--- \frac{\left|\vartheta_0\times\{\ell,\kappa\in\Re\}\right|}{\sqrt [G]{-\Gamma(\alpha)\cdot\mathcal{B}^{\left[\oint\!c_\hbar\right]}}} -- http://mail.python.org/mailman/listinfo/python-list
Re: idiom for constructor?
Peter Dembinski wrote: This is not a good use case for exec. Use setattr: OK, true. From the other side: what are the usual uses of 'exec'? An interactive Python interpreter. :-) No, seriously: Introspection is always better than exec. It is far less error phrone, especially because you don't need to deal with quoting issues, and because you have an initial syntax check of your Python code which is bypassed when using exec. Similarly, try to avoid system() whenever possible. Greets, -- Volker Grabsch ---(())--- \frac{\left|\vartheta_0\times\{\ell,\kappa\in\Re\}\right|}{\sqrt [G]{-\Gamma(\alpha)\cdot\mathcal{B}^{\left[\oint\!c_\hbar\right]}}} -- http://mail.python.org/mailman/listinfo/python-list
Multiple cmps chained one after another
Hello! Ich just found a very nice 'pythonic' solution for an often appearing problem. I didn't find it documented anywhere, so I'm posting it here. If this isn't new in any way, I'd really like to get to know it. Example problem: I have some datetime objects and want to sort them, as here: birthdays = [d1,d2,d3,d4] birthdays.sort() However, I don't want to sort them the default way. These are birthdays, so only the month and day do matter, not the year. E.g.: 2003-01-01 should be smaller than 1984-05-01 So I have to write the comparison on my own, e.g. def cmp_birthdays(d1,d2): if d1.month d2.month: return 1 if d1.month d2.month: return -1 if d1.day d2.day: return 1 if d1.day d2.day: return -1 return 0 ... birthdays.sort(cmp_birthdays) This implementation of cmp_birthdays is very ugly. Image you want to chain more than 2 values in that cmp_birthdays. I also want to use the builtin cmp function, not and . After thinking some minutes about it, I found a very nice solution: I have some cmps one aftter another. If one if them return 1 oder -1, it sould be returned. If it returns 0, the next cmp is used. In other words: I have a sequence of numbers, and want to get the first one that is not 0. (or return 0, if all numbers were 0) But this is exactly what the or operator does, due to short-circuit evaluation. In this example, that means: def cmp_bithdays(d1,d2): return cmp(d1.month,d2.month) or cmp(d1.day,d2.day) The generic pattern is: return cmp(...) or cmp (...) or cmp(...) or ... I'm not sure whether this pattern is already a common recipe, but I found it to be a very nice idea. :-) Any opinions? Greets, Volker -- Volker Grabsch ---(())--- \frac{\left|\vartheta_0\times\{\ell,\kappa\in\Re\}\right|}{\sqrt [G]{-\Gamma(\alpha)\cdot\mathcal{B}^{\left[\oint\!c_\hbar\right]}}} -- http://mail.python.org/mailman/listinfo/python-list
Re: Multiple cmps chained one after another
Steven Bethard wrote: Robert Kern wrote: def mykey(d): return (d.month, d.day) The point here is that rather than chaining cmp() calls with ors, you should just use a tuple -- the standard comparison order in tuples is exactly what you're looking for. That's an excellent idea! Thanks a lot. I really didn't think of the key= argument. Greets, -- Volker Grabsch ---(())--- \frac{\left|\vartheta_0\times\{\ell,\kappa\in\Re\}\right|}{\sqrt [G]{-\Gamma(\alpha)\cdot\mathcal{B}^{\left[\oint\!c_\hbar\right]}}} -- http://mail.python.org/mailman/listinfo/python-list
Re: Multiple cmps chained one after another
vincent wehren wrote: If you don't care about the year, why not just normalize the year to all be the same using the replace method of the date instance? That's a very bad idea. In my example, this would work, but in reality I don't sort datetime objects, of course! (Is there any real application where you want to do that?) Instead, I'm sorting Person objects using a birthday attribute. Since I use these Person objects also in other places, they should never be modified without just to be sorted. In general, the number side effects should always be minimized. datesNorm = [obj.replace(year=1900) for obj in (dates)] datesNorm.sort() This code would go bad especially in my situation, where my Person objects are SQLObjects, thus the normalisation would be written into the database. Okay, one could use transactions and rollback, but I think, my point is clear now. Nevertheless, I think you idea is very interesting. Is there any real application where normalizing just for sorting would be reasonable? Greets, -- Volker Grabsch ---(())--- \frac{\left|\vartheta_0\times\{\ell,\kappa\in\Re\}\right|}{\sqrt [G]{-\Gamma(\alpha)\cdot\mathcal{B}^{\left[\oint\!c_\hbar\right]}}} -- http://mail.python.org/mailman/listinfo/python-list
Re: Multiple cmps chained one after another
Peter Hansen wrote: Or just use the .timetuple() method on datetime objects and sort on the 8th element of the 9-element tuple, which is the day-of-the-year. An interesting idea. But wouldn't sorting by (dd.month,dd.day) be more effective? In other words: Does .timetuple() create a tuple, or does it just return a tuple which is present anyway? Greets, -- Volker Grabsch ---(())--- \frac{\left|\vartheta_0\times\{\ell,\kappa\in\Re\}\right|}{\sqrt [G]{-\Gamma(\alpha)\cdot\mathcal{B}^{\left[\oint\!c_\hbar\right]}}} -- http://mail.python.org/mailman/listinfo/python-list
Re: Multiple cmps chained one after another
vincent wehren wrote: | If you don't care about the year, why not just normalize the year | to all be the same using the replace method of the date instance? | | That's a very bad idea. In my example, this would work, but in reality | I don't sort datetime objects, of course! (Is there any real application | where you want to do that?) | | Instead, I'm sorting Person objects using a birthday attribute. | Since I use these Person objects also in other places, they should never | be modified without just to be sorted. In general, the number side effects | should always be minimized. Can you explain where you see a modification to the orginal object happening? (or in any of the other solutions proposed for that matter...) Sorry, my fault. I didn't read carefully enough. X-) Not here I hope: | datesNorm = [obj.replace(year=1900) for obj in (dates)] | datesNorm.sort() While you don't change the original objects, there's still a problem since you're sorting the normalized values. However, I want to sort the original list (i.e. the list of Person objects). But that's not a real problem if one normalizes in a key function: def key_birthday(d): return d.replace(year=1900) ... dates.sort(key=key_birthday) ..as suggested in other followups of my posting. | Nevertheless, I think you idea is very interesting. Is there any real | application where normalizing just for sorting would be reasonable? How about a case-insensitive sort of strings? (uppering being the normalization step) Or getting rid of accented / special characters before sorting. These sound like fairly straight-forward use cases to me ;) For your solution these are good examples. But my question was, whether normalizing first, and just sorting the normalized values (not the original values) is reasonable. I.e., when I sort some strings case-insensitive, I don't want my resulting (sorted) list to contain only lowercase string. But that's what I would get if I used the algorithm you described above. Greets, -- Volker Grabsch ---(())--- \frac{\left|\vartheta_0\times\{\ell,\kappa\in\Re\}\right|}{\sqrt [G]{-\Gamma(\alpha)\cdot\mathcal{B}^{\left[\oint\!c_\hbar\right]}}} -- http://mail.python.org/mailman/listinfo/python-list