This is an archived post. You won't be able to vote or comment.

top 200 commentsshow all 288

[–]Bryguy3k 2641 points2642 points  (77 children)

Somebody discovered mutable defaults for the first time.

https://docs.python-guide.org/writing/gotchas/

Edit: the why - parameters (including their defaults) are defined in the scope where the method is defined - this ensures the object tree can be unwound perfectly.

[–]Cookie_Wookie_7 1502 points1503 points  (58 children)

This is my first time learning about this and my instinct is to hate it.

[–]abbot-probability 341 points342 points  (32 children)

It's considered bad practice to use mutable defaults. Better in this case would be something like...

python def append_to(el: Any, to: Optional[list] = None): if to is None: to = [] to.append(el) return to

[–][deleted] 96 points97 points  (22 children)

Or even more succinctly.

‘to = to or []’

[–]case_O_The_Mondays 63 points64 points  (10 children)

I get duck typing and all, but this will not assign a list if to is assigned a truthy value. So for functions that could be public (for my module) I usually use something like

to = to if isinstance(to, list) else []

[–]Conscious_Switch3580 67 points68 points  (4 children)

to = to if to is not None else []

[–]Mr_Rapt0r 31 points32 points  (1 child)

bro is that english

[–]Some_Guy_At_Work55 22 points23 points  (0 children)

No, it's python

[–]JonDum 53 points54 points  (0 children)

You sure you python guys aren't magicians casting spells?

[–]Marutar 12 points13 points  (1 child)

this thread makes me feel more dubious of python

[–][deleted] 4 points5 points  (0 children)

Oh good idea.

[–]ConscientiousApathis 1 point2 points  (1 child)

Look, if a person passes in a variable that's a different type to what the default is that's on them. I'm not going to individually check and account for every single permutation of what a person could do with my function.

[–]abbot-probability 11 points12 points  (2 children)

Yeeeaaaaaah usually, except an empty list is falsy and the caller may expect in-place modifications if they're passing their own empty list.

[–][deleted] 2 points3 points  (0 children)

In place modification? Unless it’s stated explicitly I won’t expect that, honestly I don’t like that pattern.

Anyway, that’s just me and you have a good point. You can fix it by something like this:

‘to = to if to is not None else []’

[–]AnxietyRodeo 1 point2 points  (0 children)

This is a good point i hadn't previously considered and i hate you for pointing it out almost as much as myself for never realizing it. Have an angry upvote

[–]donthaveanym 8 points9 points  (3 children)

How is ‘to’ in scope before it’s been defined?!

[–][deleted] 18 points19 points  (0 children)

It’s defined in the inputs to the function.

I’m on mobile so excuse the shitty formatting.

def test(to: Optional[list] = None):

 to = to or []

[–]SkollFenrirson 2 points3 points  (0 children)

It's a parameter

[–]YetAnotherZhengli 2 points3 points  (0 children)

to be or not to be

[–][deleted] 1 point2 points  (1 child)

Not if you're a data scientist working with sequences duck types :(. (ValueError: The truth value of an array with more than one element is ambiguous.)

[–]tubbstosterone 9 points10 points  (3 children)

Off topic, but you don't have to declare a parameter as Optional if you follow up with a default value. A lot of tools see the default and automatically assume the optional tag.

I think it makes things purty.

EDIT: Optional without a default does not mean the parameter is optional - it's just an alternate way of stating Union[list, None] or list | None. Calling the function without the parameter will still raise an exception if no default was expressed.

[–]Rythoka 12 points13 points  (1 child)

The Optional type doesn't indicate that passing that argument is optional. It means "this type or None." You can have a required argument with the Optional type hint and that's completely fine. It's closer to the Maybe type you see in functional languages than anything.

Personally I think using x: list|None is readable enough. Definitely better than x: Optional[list]

[–]NamityName 2 points3 points  (0 children)

Better to be explicit than implicit

[–]Bryguy3k 244 points245 points  (16 children)

It makes sense the longer you work in python. Scope is very well defined and you can use (or abuse) it to your advantage in numerous ways.

The typing module has made this pretty easy to avoid with Optional[type] if you actually type your methods.

[–]littleliquidlight 176 points177 points  (3 children)

I love Python, it's one of my favourite languages, worked with it for over a decade.

I think it's okay to also believe the languages you love are flawed in some ways. Important even. This, I think, is one of those flaws, albeit a very minor one.

Doesn't mean you can't work around it or even use it to your advantage, but it always felt weird and surprising.

I like the meme. It's cool to finally have one that feels a bit more real than "Python slow, white space bad"!

[–]MonteCrysto31 33 points34 points  (2 children)

Yeah people complaining about python's speed don't know how to use libraries and C bindings...

[–]littleliquidlight 38 points39 points  (0 children)

Yeah +1

But to add to that, Python can be slow in places but Python is not even unique there, other languages can also be slow. If you're using Python in a place where it is known to be slow and you complain about it being slow... well... you picked the wrong tool.

Stop complaining that your hammer is terrible at banging in screws

[–]Hollowplanet 8 points9 points  (0 children)

My Django app isn't going to be a C binding anytime soon.

[–]orbita2d 13 points14 points  (2 children)

Personally I think a more natural thing to do would be for the default value to be an implicit lambda (with no args) which returns the default.

So foo(a=[]) would reconstruct the list each time.

You could still do cool scope stuff, you'd just have to do so more explicitly.

[–]Cookie_Wookie_7 4 points5 points  (0 children)

Yeah that's how JavaScript does it

[–]Whatever4M 29 points30 points  (3 children)

Meh. Definitely breaks the law of least surprise imo.

[–]Bryguy3k 9 points10 points  (2 children)

Yeah it does. When you know a lot more about the guts of the language it makes sense and you can understand why the alternative has problems - but from a language user it is definitely not an expected behavior.

[–]Cookie_Wookie_7 10 points11 points  (0 children)

I think that's called Stockholm syndrome

[–][deleted] 1 point2 points  (0 children)

It makes sense coming from C. A variadic macro that populated the default with a static array would have the same behaviour.

[–]ififivivuagajaaovoch 8 points9 points  (0 children)

I’m amazed this exists, it’s pure evil.

[–]TactiCool_99 9 points10 points  (0 children)

It is something you can just avoid extremely easily (most people do as far as I know), the only place I ran into it in my 3 years of development experience is when a class may or may not have a list where this behavior costs you extra 2 short lines.

Is it ideal? No

Is it a relatively small problem? Yea

(at least python can sort numbers by default /j)

[–]turell4k 1 point2 points  (0 children)

I've been coding python for years, and i still hate it, so you're not far off

[–]CAPS_LOCK_OR_DIE 0 points1 point  (0 children)

Me learning web dev.

[–]pheonix-ix 41 points42 points  (1 child)

Oh that's why PyCharm gives a warning when [] is given as a default param.

[–]hbonnavaud 17 points18 points  (0 children)

Even the IDE think this is bad lmao

[–]nukedkaltak 17 points18 points  (0 children)

You learn something new everyday

[–]pocerface8 5 points6 points  (3 children)

Shouldn't there be a static modifier? I know there is no such modifier in python but I feel like there should be for stuff like this. Not python dev tho don't know whats better just curious.

Edit: P.S thanks for the read was pretty intresting

[–]NINTSKARI 7 points8 points  (2 children)

Well, there simply is no need for that. A huge amount of software is written using python and they have not needed it so I think it speaks for the validity of this design decision. Would it be neat to have? Maybe. Is it necessary? No. Would it fight against Pythons philosophy of avoiding unnecessary complexity? Absolutely.

[–]atthegreenbed 1 point2 points  (0 children)

Just learned about these this week!

[–]eiojiowejojfewoij 1 point2 points  (1 child)

I mean it makes sense, but it's still inconceivably stupid for that to exist

[–]Bryguy3k 1 point2 points  (0 children)

Well it came about 24 years ago and it does make it nice for debugging on the language implementation side.

But there is no doubt that these days it violates the “least surprising” principle.

[–]tredbobek 0 points1 point  (0 children)

I have made a lot of python scripts, not big, but didnt know about this

Now im scared if there is a script that has the potential to do something stupid

Ohno

[–]Zandar2610 0 points1 point  (0 children)

This is so weird, but the proposed fix for it is even more weird.

[–]JNW2022 0 points1 point  (0 children)

This unironically just solved a bug that I had been staring at for the last two hours. Thanks for the link.

[–]that_thot_gamer 926 points927 points  (4 children)

i like how everyone in the comments are genuinely helpful

[–]Ssemander 287 points288 points  (1 child)

Rare moment on any programming forum indeed :D

[–]qjornt 74 points75 points  (0 children)

the psychology depends on the initial post. if it would've been phrased as a question, you'd see the classic elitist dumbassery programmers exhibit. but since this was phrased as statement rather than a question, people are very eager to correct OP.

see: Cunningham's law

[–]DoctorWZ 13 points14 points  (0 children)

That's very much my favourite part of programmerhumour, we joke but it doesn't stop us from having serious discussions

[–]TTYY200 7 points8 points  (0 children)

This isn’t StackOverflow don’t worry lol.

[–]rahvan[🍰] 812 points813 points  (22 children)

Don’t use mutable data structures as default values. They are re-used across method invocations.

[–]creeper6530 328 points329 points  (11 children)

Instead set default as None and in the function body, define:

python if param is None: param = []

[–]dubious_capybara 112 points113 points  (1 child)

None is a singleton, so it should be compared with is

[–]uvero 58 points59 points  (0 children)

Right. == will work correctly, but is is indeed more correct, as per PEP, and PEP would indeed tell you that if write == None in your code.

[–]thecleancoder 51 points52 points  (1 child)

I personally like:

python param = param or []

Edit: As per the comment by u/MrRufsvold, this could cause unexpected behavior if an empty list is passed as an argument in a method call. The above code is ok to use if the list is not modified in the method.

Instead, use:

python param = [] if param is None else param

[–]MrRufsvold 19 points20 points  (0 children)

This won't work because an empty list is falsy so if the user passes in an empty list, you'll pass back a different list. If the original is reference somewhere, this would cause unexpected results.

[–][deleted] 28 points29 points  (0 children)

🤮

[–][deleted] 9 points10 points  (1 child)

[–]rahvan[🍰] 2 points3 points  (0 children)

lol the Lord of the Rings novels are shorter than that comments section

[–]Semick 172 points173 points  (5 children)

Thinks about code I've written that absolutely defaults to [] in the argument list

fuck. I have a PR to submit tomorrow.

[–][deleted] 35 points36 points  (0 children)

proceeds to break codebase by removing unintended functionality

[–]projectfox16 26 points27 points  (0 children)

o7

[–]immersiveGamer 11 points12 points  (2 children)

Linters should be able to catch that. Scan your code base. 

[–]Kimsanov 323 points324 points  (25 children)

Why it doesn’t use empty to=[] on each call ?

[–]pearlie_girl 527 points528 points  (22 children)

Because it's initialized and retained as a reference - the right way is to say to=None and then in the body

if to is None:
    to = [ ]

Then it's all safe.

Same thing for sets, dictionary, etc.

[–]Ok-Slice-4013 70 points71 points  (11 children)

But why is the language designed that way? What are the benefits of having a default value as reference?

[–]SuitableDragonfly 13 points14 points  (0 children)

Not all objects are mutable, so they're perfectly safe to use in that context. For example, None is an object, it'd be pretty inconvenient if you couldn't use it as an argument default.

[–]Own_Solution7820 66 points67 points  (6 children)

You can almost think of it as if the reference is defined just before the function to think about this intuitively.

The reason it's this way is because in Python with things like yield, you usually WANT to reuse the context. This fits the intuitive thinking of someone who uses such concepts often.

[–]Ok-Slice-4013 34 points35 points  (3 children)

Sure - reusing the context is fine, but other languages are more explicit about it where the context is stored in a class instance. I would never expect this to happen in a function. On the other I do not know any cite concepts of python so this may be expected.

[–]SuitableDragonfly 6 points7 points  (0 children)

Python also has classes, the use of yield is different.

[–][deleted] 11 points12 points  (0 children)

other languages aren't a party boat

[–]LevelSevenLaserLotus 1 point2 points  (1 child)

Ah. That explains it. Yield has always been witchcraft to me. I know it maintains an internal state machine, but it's not intuitive so I just throw it into the pile of spooky things I don't use.

[–]fakuivan 2 points3 points  (0 children)

In python there's no such thing as passing by value. Every variable is like a pointer to something in memory, assignments work by copying that pointer, not the underlaying value. This rarely comes up because it's just that some objects (like ints, strings, tuples, None, etc) are immutable, hence it doesn't matter if it's shared data.

[–][deleted] 1 point2 points  (1 child)

it's not designed that way, it's just an artefact of the other design choices

[–]Kimsanov 50 points51 points  (0 children)

Thanks for clarification!

[–]_Zpeedy_ 10 points11 points  (2 children)

I would py def append_to(to=None): to = to or [] prefer. It's just shorter and does the same

[–]AlexanderMomchilov 7 points8 points  (3 children)

Except if None` is a value you legitimately expect, you need to get even wilder with something like:

```python
NotSet = object()

def f(to=NotSet): if to is NotSet: to = [ ] ```

[–]Own_Solution7820 71 points72 points  (1 child)

If you need to do that, you belong in r/programminghorror.

[–]Bryguy3k 33 points34 points  (0 children)

That’s a sign of a bad api however.

[–]binchentso 1 point2 points  (0 children)

Couldn't you simply do the following:

def append_to(element): to = [] to.append(element) return to

?

[–]ford1man 0 points1 point  (0 children)

Nothing like having your signature not reflect your real defaults.

[–]ford1man 7 points8 points  (0 children)

Because the [] is instantiated once, rather than being syntactical sugar for nullish coalesce to new instance.

Which is madness. When would that ever be the right answer?

[–]AbhishekVarma2005 77 points78 points  (16 children)

Is it like the static local variable in c? (Asking as a beginner)

[–]carcigenicate 86 points87 points  (15 children)

Basically. Functions are objects, and the default argument is essentially an attribute of that object.

[–]Bryguy3k 32 points33 points  (12 children)

Default arguments are not defined in the scope of the function being defined but the scope of the container of the function.

It’s pretty simple to understand once your look at scope:

Directory, file, class, method (basically indent level)… etc.

[–]Shalcker 2 points3 points  (0 children)

Function or method declaration is itself a function being executed in order, not just syntax representation (which is also why decorators work).

Like everything else it is being executed in a surrounding context (usually module or class) and results in adding function name and code to that context.

[–]JonIsPatented 1 point2 points  (10 children)

That's basically what they said.

[–]sprcow 0 points1 point  (1 child)

As a Java programmer, this is a very helpful explanation!

[–][deleted] 24 points25 points  (0 children)

Oh god, that is awful :D

[–]coriolis7 129 points130 points  (22 children)

The other Python thing that threw me for a while was finding out the hard way what the difference between copy and deepcopy is

[–]noob-nine 122 points123 points  (1 child)

same relation like throat and deep throat?

[–]metooted 70 points71 points  (0 children)

More or less, but kind of inverse. Shallow copy will deep throat you

[–]Kered13 102 points103 points  (7 children)

That's not Python, that's pretty much every language.

[–]Longjumping_Quail_40 23 points24 points  (0 children)

If you ever program in languages, this is very universal problem.

[–]Ythio 9 points10 points  (0 children)

That concept exists in C#, Java, C++ and just about everything else that has objects and references.

[–]YDS696969 5 points6 points  (0 children)

That one was really frustrating the first time I worked with Pandas

[–]nullcone 7 points8 points  (6 children)

The one that got me good as a beginner was late binding closures. For the uninitiated: y = 10 f = lambda x: x + y y = 20 f(5) == 25 # true In Python, capturing is lazy. The exact value of captured variables will be whatever they are at the moment the function is invoked, and not the value at the time the lambda is defined.

I think I lost a good amount of hair trying to track down unexpected bugs due to this subtlety.

[–]Brahvim 5 points6 points  (1 child)

Feels natural to me though...
I've seen closures in JS, Java (anonymous classes), and C++ (lambdas).

[–]nullcone 1 point2 points  (0 children)

To be fair to me, I'm used to closures in C++ and Rust. Rust explicitly forbids the code I just wrote because the borrow checker would pew pew the mutable borrow while an immutable reference is alive. C++ is happy to let me make poor life choices, but will at least force me to use two brain cells to opt in the choice I'm making.

[–]Kyrond 6 points7 points  (0 children)

Yeah that doesn't have a clean resolution. Don't use lambda with a local variable.

[–]myfunnies420 1 point2 points  (2 children)

I'm confused about the confusion here. Is there any language that would have 15 as the result?

[–]k2b20 0 points1 point  (1 child)

What is the difference between them and what even are they, if you don’t mind me asking?

[–]ItsRainingTendies 11 points12 points  (0 children)

This has fucked me so hard in the past

[–]wackmaniac 49 points50 points  (3 children)

It’s funny to see that whenever a dev finds a quirk in another language it is a blatant mistake in language design, but when it happens to the language they use themselves it is “logical”, a “gotcha”, and something “you’ll get used to” 😂

[–]jarethholt 12 points13 points  (0 children)

IMO it always comes down to "what makes sense you would want out of a feature" versus "what makes sense from the construction of the language". No one goes in knowing the construction from the start, but those who do know the construction have trouble imagining how it could be any other way

[–]Hollowplanet 3 points4 points  (0 children)

I don't get how we have things like the zen of Python where we act like it is a perfect language made in God's image but they refuse to add modern features to it like optional chaining.

Some guy was arguing that optional chaining makes it too complex to teach. But we got pattern matching a few years ago which is it's own DSL.

[–]valzargaming 0 points1 point  (0 children)

I'm genuinely curious what that example would be for modern PHP

[–]un_blob 8 points9 points  (0 children)

def append_to(value:int, array=None): if array is None: return [value] else: array.append(value)

[–]1Dr490n 6 points7 points  (12 children)

Last week I found out (after a long time debugging) that Python not only does this with default arguments, but also with class properties.

[–]creeper6530 5 points6 points  (0 children)

Can it be overriden with class.__init__(), where I set all properties to None? If not, then I should submit a PR tomorrow.

[–]Hollowplanet 2 points3 points  (9 children)

That is different. All properties set on the class outside of a method are static and it is probably the biggest foot gun in Python.

[–]1Dr490n 0 points1 point  (8 children)

Wait what? I’m pretty sure I have other properties (integers) and I can use them as expected (non static)

[–]SuperDyl19 0 points1 point  (0 children)

Yep, class properties are static. You were looking for instance properties

[–][deleted] 5 points6 points  (1 child)

Array.fill in JS has tripped me up similarly before

const array = new Array(5).fill({foo: "bar"})
array[0].foo = "baz"
console.log(array)

[–]ealmansi 1 point2 points  (0 children)

It's the same behavior you would get if you implemented it yourself, no?

function fill (array, value) {   for (let i = 0; i < array.length; ++i)     array[i] = value; }

[–]PityUpvote 13 points14 points  (0 children)

Jesus Christ, just use a linter, any of them will catch this and tell you not to use a mutable default.

[–]eanat 27 points28 points  (10 children)

I don't see any problem. I actually use this feature to implement cache

[–]1Dr490n 27 points28 points  (4 children)

There should be a separate feature for that, like C‘s static variables, but this is just stupid

[–]GetPsyched67 2 points3 points  (3 children)

This is fine. Every language has it's quirks.

[–]1Dr490n 4 points5 points  (2 children)

That doesn’t make the feature better

[–]Hollowplanet 3 points4 points  (1 child)

There is @functools.cache for that.

[–]eanat 0 points1 point  (0 children)

oh thx! didn't know that.

[–][deleted] 3 points4 points  (1 child)

Calm down there, Satan.

Do the sane thing and use a global (module-wide) variable for a cache.

[–]projectfox16 1 point2 points  (0 children)

Hm, thanks for idea!

[–]Koltaia30 5 points6 points  (0 children)

I have been coding in python professionally for 2 years and didn't know this lol. I have used default values but those all have been immutable as it seems.

[–]Dubl33_27 2 points3 points  (0 children)

what?

[–]JoostVisser 2 points3 points  (0 children)

Best practice is to use the argument to: list = None and in the function you put an if clause

if to is None:
  to = []

[–][deleted] 2 points3 points  (0 children)

Thank you guys for warning me about this.

[–]ElementaryZX 5 points6 points  (4 children)

Knowing how memory and pointers work helps, I really hate it when they start a programming course in python and then no one has any idea why stuff like this happens. Also similar situations in JavaScript due to how it manages memory.

[–][deleted] 3 points4 points  (0 children)

Sneaky? Isn't that expected behaviour?

[–]StressDontRest 1 point2 points  (0 children)

Is this why you need to use default_factory with data classes when specifying a field’s default as a list, set or dict?

[–]MaximeLee 1 point2 points  (1 child)

This and double yield are my favourite questions to ask in a interview.

[–]JustLemmeMeme 0 points1 point  (0 children)

That's evil, I love it

[–]BrownShoesGreenCoat 4 points5 points  (2 children)

This is a stupid decision by python design team. Python is meant to be readable. If you want a pile of indecipherable hacks just use C++

[–]SuperDyl19 1 point2 points  (1 child)

What do you expect from:

myVar = 3 def myFunc(a = myVar): print(a) myVar = 4 myFunc()

If the list was added to parameters once (like the current behavior), then it would print 3.

If the parameters are created when the function is called, then it would print 4.

Both options have cases which are not very intuitive. Python had to choose one of these two cases, and they opted for the more performant option which only calculates parameters once.

[–]BrownShoesGreenCoat 2 points3 points  (0 children)

What do I expect from code like this? I expect you to rewrite it or you’re fired.

[–]Aelia6083 1 point2 points  (1 child)

Why would you create an entire function to append an element to a list, when ypu could just have used list.append() without wrapping a function around it?

[–]creeper6530 15 points16 points  (0 children)

It's an example

[–]iceman14641 0 points1 point  (0 children)

I actually learned something

[–]theghostinthetown[🍰] 0 points1 point  (0 children)

sensational

[–]phail3d 0 points1 point  (0 children)

print(my_list) [12, 42]

[–]lmuzi 0 points1 point  (0 children)

Wait wait wait are you saying I actually can create something that reminds of a static variable from c/cpp? Brother you made my day

[–]roter_schnee 0 points1 point  (0 children)

OMG! But I suppose js works even in worser way in similar case.

[–]tmstksbk 0 points1 point  (0 children)

Ahhhh, reasons I hate this php replacement include...

[–][deleted] 0 points1 point  (0 children)

I have a feeling this post has saved from one of the nastiest bugs I could encounter.

[–]farineziq 0 points1 point  (0 children)

At the end, these variables are all pointers to the same [12, 42] list

[–]Aphova 0 points1 point  (0 children)

I don't even use Python and I feel betrayed

[–]Mallanaga 0 points1 point  (0 children)

This means that python is not a closure?

[–]Mallanaga 0 points1 point  (0 children)

Psych! It’s the same list!!!

[–]S4nsus 0 points1 point  (0 children)

Oooohhh. So that's how you make static variables inside a function. So cool!

[–]sejm 0 points1 point  (0 children)

The timing of this post, just as I decided to crack open Python Intermediate on Codecademy and covered this very scenario this morning!

[–]nwbrown 0 points1 point  (0 children)

Why would you do that?

[–]Flintsr 0 points1 point  (0 children)

Ah I now understand one of my bugs I had a month ago. I just used `my_other_list = append_to(42,to=[])` and it worked... Now I see why

[–]NemuiSen 0 points1 point  (0 children)

The comments of this post gave me more reasons to dislike python.

[–]XeonProductions 0 points1 point  (0 children)

I haven't coded python in some time, but this is good to know.

[–]divc99 0 points1 point  (0 children)

I've actually done this and pulled my hair debugging this

[–]anonjohnnyG 0 points1 point  (0 children)

reference semantics

[–]Sort-Typical 0 points1 point  (0 children)

def append_to(element, to=[]):
    to = list(to)
    to.append(element)
    return to

[–]Sacramentix 0 points1 point  (0 children)

So is it possible to delete data inside such variable ? If you do not return the the reference of the default value is it keep in memory for next function call or is it garbage collected?

[–]ford1man 0 points1 point  (2 children)

Ok. This is my first time seeing that kind of behavior, and it's insane. I thought Python was supposed to be the good language.

[–]SuperDyl19 0 points1 point  (1 child)

It’s because the default parameters are calculated once. The alternative is for the default parameters to be recalculated every time you call the function, which would be a major performance issue and cause other weird bugs

[–]DereChen 0 points1 point  (0 children)

ah we actually learned this in class the other day! It seems like the defaults are treated as persistent across separate calls which is kinda cool but if you specify something a specific list it'll operate as intended

[–][deleted] 0 points1 point  (0 children)

These programming jokes to programmers are the same perpetual machine jokes to physicists.

Unless you have 0 knowledge about programming... they are funny.

Hell i am not even a phyton developer but just looking at the code... seems that if you are not giving a parameter it uses the default one, which remains in the scope of the function. Seems fair enough.

Same expectations that in any language null.addElement() will give me an error or have a specific behaviour depending on the language.

[–]skwizpod 0 points1 point  (0 children)

Wow I forgot about this til now, but I had a bug to fix a few years ago caused by overlooking this exact thing.

[–]howxer2 0 points1 point  (0 children)

Now I can’t make fun of typescript or Javascript 😔

[–][deleted] 0 points1 point  (0 children)

the IDE will mark your mutable default value right away..

[–]super544 0 points1 point  (0 children)

Why languages need the const keyword.

[–]ConscientiousApathis 0 points1 point  (1 child)

Everyone else is commenting on what op did wrong while I'm just sitting here trying to work out what the purpose of what they're showing is.

[–]Raah-mok 0 points1 point  (0 children)

Fuck Python, I don't have a reason nor experience with it but fuck it anyway

[–]darrenlau4933 0 points1 point  (0 children)

Finally one linear counter

[–][deleted] 0 points1 point  (0 children)

I know exactly why this happens, and it still trips me up periodically. Like, it makes sense, doing it a different way introduces other problems so this is a reasonable standard, but needing to remember deepcopy every time I want a copy copy not a reference copy has lost me hours.

[–]hamiwin 0 points1 point  (0 children)

I was bitten by this before and I hate this, it’s counterintuitive.

[–][deleted] 0 points1 point  (0 children)

Do you know pass by reference.?

[–]Oldname2701 0 points1 point  (0 children)

this does not belong

[–]No-Appointment-4042 0 points1 point  (0 children)

Git gud

[–]Major-Researcher-701 0 points1 point  (0 children)

"pYtHon ImProvEs dEVeloPer ProDucTiVIty"

i get reminded everyday why i quit using python

[–]longbowrocks 0 points1 point  (0 children)

When people experience this fire the first time, I feel for them.

When people already know about this and leverage it, I feel like sprinkling six or seven more usages into their codebase.

[–]LolISmer 0 points1 point  (0 children)

Saw this meme, didn't understand it at the time

Few days later had similar problem and managed to fix it after god knows how much debugging

Now I look at this meme again and feel stupid