Earlier quoted context omitted.
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.
A few things to remember while coding in Python
121–130 of 146 posts
Re: A few things to remember while coding in Python
#122It'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.
> It's worth explaining why mutable defaults are bad They can also be good. Here's an example from the Reddit discussion, showing how a mutable default can be used to very neatly and cleanly add memorization to a function: def fib(n, m={}): if n not in m: m[n] = 1 if n
Re: A few things to remember while coding in Python
#123It'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.
> It's worth explaining why mutable defaults are bad They can also be good. Here's an example from the Reddit discussion, showing how a mutable default can be used to very neatly and cleanly add memorization to a function: def fib(n, m={}): if n not in m: m[n] = 1 if n
Re: A few things to remember while coding in Python
#124Earlier quoted context omitted.
Functions (methods) are first class objects also in Ruby: methods are instances of the class Method, while Procs are a lightweight alternative. Default arguments in Ruby are not mutable in any kind of function object, be it a lambda proc, a regular proc, or a method. You can use a mutable default argument as an ersatz static variable, e.g. for memoization.
> Default arguments in Ruby are not mutable in any kind of function object Maybe I misunderstood you, but they are perfectly mutable: class A attr_accessor :a def initialize @a = [] end def b x = a x # obj.b # => [1] obj.b # => [1, 1] obj.a # => [1, 1] If you mean "inline default arguments are not mutable", that's not true either. What is true is that the default argument is evaluated when the function is called, not…
ruby> class A; end
=> nil
ruby> def foo(bar = A.new); return bar; end
=> nil
ruby> foo
=> #
ruby> foo
=> #
and get back the same object each time `foo` is called in Ruby.I've even seen a major Python library with this bug (I'm sorry, I don't recall which off-hand). It's really surprising behavior for new Python devs.
Re: A few things to remember while coding in Python
#125Earlier quoted context omitted.
There are a few use cases for default variables on effbot's site: http://effbot.org/zone/default-values.htm Basically, sometimes you do want to reuse the mutable between function calls, and in those cases it can save a fair bit of code passing it in repeatedly.
Good coverage. I use it quite often for cache dictionary, it's much simpler API and overall code, than creatng a new class for it. Demo snippet from effbot's site: def calculate(a, b, c, memo={}): try: value = memo[a, b, c] # return already calculated value except KeyError: value = heavy_calculation(a, b, c) memo[a, b, c] = value # update the memo dictionary return value
Re: A few things to remember while coding in Python
#126Earlier quoted context omitted.
It's called destructuring assignment. It's been around for a while. http://dunsmor.com/lisp/onlisp/onlisp_22.html
I mean why would you want to allow both list and tuple syntax for exactly the same semantics, when either of them would be enough.
Re: A few things to remember while coding in Python
#127Earlier quoted context omitted.
Is that clean and neat, or weird and inscrutable? Will it be clear to /anyone/ reading that code what it's doing?
I'm a Python newbie, and that code was immediately clear and obvious to me when I read it. I won't say it would be clear anyone that reads it, because we live in a world where people who claim to be programmers can't do fizz buzz.
Add a @memoize decorator and do it there, you need to always be as obvious as possible. Compare:
@memoize
def fibonacci(n): pass
def fibonacci(n, memory=[]): pass
You don't even need documentation for the first example.Re: A few things to remember while coding in Python
#128Re: A few things to remember while coding in Python
#129There is a builtin function called `reversed`. You'd better remember that than the "useful" [::-1] idiom. The recommendation on `iteritems` had better be generalized to include `iterkeys`, `itervalues`, and other opportunities for using iterators rather than building lists. A note that the 'iter...' versions are removed in Python 3 (because iterator behaviour becomes the default) would be appropriate here. In relatio…
Re: A few things to remember while coding in Python
#130Earlier quoted context omitted.
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…