Live data from Hacker News

A few things to remember while coding in Python

satyajit.ranjeev.in

41–50 of 146 posts

Re: A few things to remember while coding in Python

#41

Generally most use this: freqs = {} for c in "abracadabra": try: freqs[c] += 1 except: freqs[c] = 1 If this is really the common idiom, I'd say this is a sign that professional programming has yet to fully mature as a field. Some may say a better solution would be: freqs = {} for c in "abracadabra": freqs[c] = freqs.get(c, 0) + 1 Okay, so I understood immediately what was going on with the 2nd bit of code. Rather go…

Well, yes, but I'd also like to think that code should raise the level of the programmers reading it. You shouldn't avoid language features just because some people don't know about them. That's as ridiculous as the folks who say "Don't use the ?: operator because folks who haven't taken Intro CS 101 may not be familiar with it." So you spent a couple seconds Googling defaultdict. Great, you now know what a defaultdi…

Well, yes, but I'd also like to think that code should raise the level of the programmers reading it...You should avoid gratuitous complexity

I have a different set of policies than most programmers, which arises from my observation that our field's priorities are out of whack with the actual cost-benefit.

Our greatest costs involve understanding systems, so our first priority should typically be to produce readable and understandable code.

You shouldn't avoid language features just because some people don't know about them.

One should pick language features to optimize for readability, which is entirely contextual. If your shop has a culture of using ?: to the point where it's like a coding standard then you should keep on doing that.

So long as code can be read and understood, programmers will learn. Better yet, if the culture of a shop is that use of language features and other tools are motivated by contextual cost-benefit, then programmers will learn from this example. As it is, programmers generally are more interested in showing off, having fun, and writing things as easily as possible. It's less common to have a culture of prioritizing reading.

Re: A few things to remember while coding in Python

#42

Earlier quoted context omitted.

You could also use the ,= operator, of course: varname ,= [...]

It appears to me that there is actually no such operator in Python; cf. http://docs.python.org/reference/simple_stmts.html#augmented... Superficially it looks like an operator, but I suspect that's merely because of whitespace freedom; i.e., a, = [0] is equivalent to a,=[0] and a ,= [0].

I assume it was a joke; a pop culture reference to this stack overflow question:

http://stackoverflow.com/questions/1642028/what-is-the-name-...

Re: A few things to remember while coding in Python

#43
post #18
post #5

It's worth explaining why mutable defaults are bad. The problem with mutable defaults is that they are evaluated once only when the function is defined. Each time the function is called you'll be using the same mutable variable that was created during function definition.

That seems like decidedly unexpected behaviour and makes default params far less useful.

The thing is, None is always a possible value for a parameter so it's actually more robust if functions are written to expect None.

If you say "f(x=[])" (assuming that worked without the actual side effects it has), someone could still say "x(None)" instead of "x()", causing the function to die. Since a robust program isn't able to avoid checking for None, it might as well set defaults there too.

There is another case where this is important; you might want the equivalent of "f(x=expensive_function_to_calculate_useful_default())", and you don't want that function called unless it needs to be. Only the x=None approach allows this to be deferred.

Re: A few things to remember while coding in Python

#44
post #11

halve_evens_only = lambda nums: map(lambda i: i/2, filter(lambda i: not i%2, nums)) I still find it rather silly that python doesn't supper a nice list map/filter; it could be so much nicer nums.filter(lambda i: i%2 == 0).map(lambda i: i/2) If they did, even including the annoyingly long-to-type "lambda". List comprehensions are cool and all, but do not really scale visually (i.e. get rather messy) when you have more…

Python offers filtering expressions in its generator syntax. I find Python's "lambda" hurts readability for most uses, which pains me as a Lisp geek. Your example, as a generator: halve_evens_only = (i / 2) for i in nums if (i%2 == 0) The parens aren't necessary, but they help readability for people who aren't used to the generator order of operations. (Again, Lisp geek, more parens means more readable in my fracture…

The parens are required. What you've written raises a SyntaxError.

You can omit them in the generator expression if it's being passed directly as the only parameter to a function:

  halve_evens_only = list(i/2 for i in nums if i % 2 != 0)

Re: A few things to remember while coding in Python

#45
post #11

halve_evens_only = lambda nums: map(lambda i: i/2, filter(lambda i: not i%2, nums)) I still find it rather silly that python doesn't supper a nice list map/filter; it could be so much nicer nums.filter(lambda i: i%2 == 0).map(lambda i: i/2) If they did, even including the annoyingly long-to-type "lambda". List comprehensions are cool and all, but do not really scale visually (i.e. get rather messy) when you have more…

  halve_evens_only = map (/2) . filter even

Re: A few things to remember while coding in Python

#46
post #18
post #5

It's worth explaining why mutable defaults are bad. The problem with mutable defaults is that they are evaluated once only when the function is defined. Each time the function is called you'll be using the same mutable variable that was created during function definition.

That seems like decidedly unexpected behaviour and makes default params far less useful.

It's a mistake. Default values for optional parameters don't act that way in any other language I know of, including Common Lisp, in which functions are also firstclass.

Re: A few things to remember while coding in Python

#47
post #18

Earlier quoted context omitted.

That seems like decidedly unexpected behaviour and makes default params far less useful.

It's a mistake. Default values for optional parameters don't act that way in any other language I know of, including Common Lisp, in which functions are also firstclass.

It's most certainly not a mistake; Python 3 would probably have fixed it, if it were. It is an (admittedly, strange) side effect of the way 'def' works.

Re: A few things to remember while coding in Python

#48

Probably best not to use iteritems, in python 3, it won't be there, "the dict.iterkeys(), dict.iteritems() and dict.itervalues() methods are no longer supported."

The iter* methods appear in Python 3, just without the iter prefix. Therefore it is good to use them in Python 2 because that makes it possible to translate the code automatically with the 2to3 script. Otherwise possibly superfluous list conversion might get added, e.g., list(d.keys()).

.keys(), .views() and .items() in Python3 return a memoryview which happen to be iterators but do far more.

Re: A few things to remember while coding in Python

#50
post #28

Generally most use this: freqs = {} for c in "abracadabra": try: freqs[c] += 1 except: freqs[c] = 1 If this is really the common idiom, I'd say this is a sign that professional programming has yet to fully mature as a field. Some may say a better solution would be: freqs = {} for c in "abracadabra": freqs[c] = freqs.get(c, 0) + 1 Okay, so I understood immediately what was going on with the 2nd bit of code. Rather go…

I agree with the spirit of your argument. In fact, I almost came here to write a parallel comment: I'm really not sure that reversing the list 'a' with 'a[::-1]' is better than 'reversed(a)', which usually effectively does the same thing, but whose meaning is much more obvious. But, while I agree with your general point, in the specific case of 'defaultdict', I differ. I use 'defaultdict' all the time and I'm glad it…

reversed(a) and a[::-1] are not equivalent. The former produces an iterator over the given list (with all the mutability dangers that come with it), while the latter produces a copied list. For plain iteration, you're correct, reversed() is better (similar to how xrange vs. range was back in the day); however, for reversing something and keeping it around, the slice syntax is better.

    >>> reversed([1, 2, 3])
    
    >>> [1, 2, 3][::-1]
    [3, 2, 1]
To clarify your point, list(reversed(a)) and a[::-1] are equivalent. It's a slightly subtle point, but extremely important if you're keeping the result of reversed() around for any length of time. If you're just iterating at the moment that you use it, yes, they're effectively equivalent.
Post reply on HN