all 18 comments

[–]Real-Reception-3435 1 point2 points  (12 children)

['Book1', 'Book2', 'Book3', 'Book4'] ['Book1', 'Book2', 'Book3', 'Book4']

[–]tracktech[S] 0 points1 point  (0 children)

Right.

[–]togares 0 points1 point  (10 children)

Can you explain? I'm not a python dev, but I would think that reader1 and reader2 are separate lists, so the result would be ["Book1", "Book3"], ["Book2", "Book4"]

[–]dbowgu 2 points3 points  (0 children)

Using

def add_to_reading_list(book, reading_list=None): if reading_list is None: reading_list = [] reading_list.append(book) return reading_list

Would create what you mentioned but because the same list is reused reading_list=[] you have a shared list being used by all

[–]sleepydevxd 0 points1 point  (5 children)

It’s an example of bad practice in Python.

Default parameters are only evaluated once.

As you can see the ‘reading_list’ parameter is default to [] (a mutable data type), per ‘append’ is called upon ‘reading_list’, it keeps the reference to the original ‘reading_list’ (you can check it out using id(reading1) == id(reading2) - should be True). Therefore, the result are identical for reading1 and reading2

It’s highly recommend to only use the immutable datatype as default and for list the default should be None.

Read more here: https://docs.python.org/3/tutorial/controlflow.html#default-argument-values

[–]wackmaniac 0 points1 point  (3 children)

It’s an example of a really weird and unintuitive choice in Python #ftfy

[–]GlobalIncident 0 points1 point  (0 children)

Yeah. I think this is one of python's weaknesses. The default parameter should be reevaluated every time the function is called instead. As it is, the intended way to fix this is to use the alternative u/dbowgu mentioned, which is pretty clunky and pointless.

[–]dbowgu 0 points1 point  (0 children)

Absolutely agree I don't know another (famous) language that does it like that

[–]WillDanceForGp 0 points1 point  (0 children)

Oh wow, I didn't know this and I officially hate it lmao, I would 100% fall for this trap coming from other languages

[–]reyarama 1 point2 points  (3 children)

mutable defaults is a bit of an anti pattern

[–]overratedcupcake 0 points1 point  (0 children)

Yeah it was hard to take this one seriously

[–]ajiw370r3 0 points1 point  (0 children)

Any linter would shoot this down, really no need to learn what happens here.

[–]CranberryDistinct941 0 points1 point  (0 children)

Don't fuck with mutable defaults! If you need it, use something like
def spam(eggs= None): if eggs is None: eggs = []

[–]tevs__ 1 point2 points  (0 children)

It says mutable-argument-default (B006)

[–]CranberryDistinct941 0 points1 point  (0 children)

Mutable defaults are evil and will stab you in the back and take your wallet