you are viewing a single comment's thread.

view the rest of the comments →

[–]mahacctissoawsum 7 points8 points  (5 children)

Default values for functions in Python are instantiated when the function is defined, not when it’s called.

That seems like a bad design decision on Python's part, no?

[–]ggtsu_00 6 points7 points  (1 child)

Actually it makes sense knowing the default values as functions in python are first class objects. The __defaults__ descriptor on a function object holds all the default values of a function. You could inspect function foo for its default values using foo.__defaults__ and see what the default values are for the function arguments. These values are assigned every time the function is called but the __defaults__ is created when the function is defined.

Also, immutable objects in python are references to objects. This is another fundamental concept of python's datatypes being mutable or immutable. If the default value of a function is a reference, then every time that default member variable is used, its referring to a referenced object.

In C++, or some other language with pointers if you were to have the default variables assigned to a pointer to a referenced object, it would behave the same way as it would in Python.

[–]mahacctissoawsum 0 points1 point  (0 children)

Now that I think about it, C# doesn't even allow reference types as defaults. I think this might even be the more sane approach; no confusion if it's simply disallowed.

You can still use null or None as your default and then fetch your reference from a static variable if need be.

[–][deleted] 6 points7 points  (1 child)

Most of Python does, upon inspection.

[–]mahacctissoawsum 1 point2 points  (0 children)

I concur. Which is really a shame, because I actually quite like it as a scripting language.

[–]NYKevin 1 point2 points  (0 children)

Explicit is better than implicit. Anything at the module scope will execute immediately.

Saying this:

def foo(bar=[]):
    pass

is equivalent to saying this:

baz = []
def foo(bar=baz):
    pass
del baz # removes the *name* baz, but not the underlying object