TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Python quirks

9 pointsby ktfover 15 years ago

3 comments

makecheckover 15 years ago
As far as the "os" versus "os.path" question; this is hinted in the Python documentation for modules that "os.path" can be an alias of, such as "os.posixpath"; there, it recommends "import os" and then referring to "os.path". In other words, there's no need to "import os.path".
lephtover 15 years ago
Pretty good list, although I'm not sure how else you would expect 'finally' to function?
评论 #910946 未加载
thwartedover 15 years ago
This is kind of a weird list. I'm just learning python, but I don't know if any of these are quirks or just the result of not reading the documentation, or it not being like My Favorite Language(tm).<p><i>Sort returns nothing</i><p>I expect the result of calling the sort() method on an array to sort the array that it was called on. Since this example is calling sort on a literal array, there's no way to access the array after it's sorted.<p><i>Tuples constructor</i><p>I agree this is a quirk, as the result of the overlapping choice of parenthesis for the tuple literal and as expression precedence. The leading star on the <i>args argument puts all the arguments into a single variable as a tuple. foo(1,2) has two arguments, which sets args to (1,2), and the representation for that is "(1,2)". foo((1,2)) as only one argument, a two element tuple, and the representation for that is "((1,2),)", the last comma being needed to disambiguate this as one element tuple where the first element is also a tuple. In the second group, both foo(1) and foo((1)) have only one argument, in the latter case the argument is an arithmetic expression with no operators that evaluates to the number 1, and the literal representation for a single argument tuple, the args variable, is "(1,)".<p>The % operator takes two operands. The RHS operand is a list or tuple with the same number of elements as there are %expansions in the LHS. Only one %expansion is given in the format string on the LHS, but a two element tuple has been given on the RHS.<p></i>Print is magical*<p>print is a statement. pprint.pprint is a function. Function arguments must be enclosed in parens. This isn't perl.<p><i>Inconsistent get interface</i><p>This is documented, shows up in ipython's "help getattr". getattr takes an optional third argument that is returned if the attribute doesn't exist which would regularly raise an exception.<p><i>Inconsistent select/poll interface</i><p>The only thing that is inconsistent here is how the timeout value is specified compared to the underlying UNIX implementation these are wrappers for. In the UNIX interfaces, select and poll take a structure that allows both seconds and fractions of a second, and epoll takes an integer. While I suppose this is confusing, these all have different usage patterns and different APIs, so it's not like you can just replace the call to select with poll and not have to refactor the rest of the code. This could be cleaned up, but it's most likely not worth it since the ranges of the timeout values reflect the most common ranges people are expecting to use.<p><i>Circular Imports</i><p>This can be overcome by remembering that modules, classes and functions are defined at run time, that an object can be referenced even though it's not finished being executed.<p><i>999+1 is not 1000</i> and <i>What is the value of one?</i><p>I'm not sure why you'd use the <i>is</i> operator to test equality of integers, when <i>is</i> is meant to test object equality. In the same way it is suggested to <i>not</i> compare strings and numbers.<p><i>The order of unpacking</i><p>Using the same variable name multiple times on the LHS when unpacking should be undefined, because the reason to do that would be because you don't care about the values that are being unpacked into the same variable. I can not think of a reason you should be encouraged to write a function that takes multiple arguments that can not all be accessed, if you wanted to do that, you should define the function's arguments as <i>args so they get eaten up, it's more obvious that some of them are optional than using the same variable name that ends up hiding one.<p>The example of foo(a=1, b=2, </i>args, <i></i>kwargs) is definitely confusing, but then this would seem to be a confusing API anyway -- it would be best not to write a function like that. What I expect to happen here is that a and b have default arguments no matter what the kwargs are, but you can't specify a kwargs entry named a (as in foo(3,4,6, a=4)) without it raising "TypeError: foo() got multiple values for keyword argument 'a'".<p><i>Multi line strings</i><p>python statements don't end with semicolons, so you need to escape the newline, which would mark the end of the assignment expression in the first example. In the second, the RHS of the assignment is an expression enclosed in parens, which doesn't end until it forms a complete expression with the closing paren. Whitespace between strings concatenates the strings, so but the newline ending the expression in the first example needs to be escaped so it's interpreted as whitespace and not as the end of the statement.<p><i>Finally finally is interesting</i><p>Watch out for this. If try blocks are nested, it seems that a nested finally with a return keeps an enclosing except block from executing:<p><pre><code> def x(): try: try: print "try" raise Exception finally: print "finally" return 1 except: print "except" return 2 print x() </code></pre> I actually prefer to nest try blocks like this to get more control over the order of execution of the finally and except blocks and make it more obvious as to what the intended order of execution is.<p><i>List comprehensions, kind of.</i><p>I actually like having to explicitly have a literal list comprehension in the for-loop syntax. I'm not sure that the lack of punctuation increases readability: the <i>if</i> in the suggested (second) syntax kind of gets lost. For maximum readability, the list comprehension might be best split into a separate expression statement rather than trying to take on perl in the longest line department.<p>I actually find python to be much more consistent and does the expected thing much more often than some other languages (ahem, I'm looking at you, PHP). I just hope that as I go deeper, using it remains refreshing.