What I’m trying to do:
Locate a Client-side alternative to Python 3.7 dataclasses, which aren’t currently available Client-side. Anything to reduce the tedium of ad-hoc class definition and inter-object comparison.
Obviously, this would have to be a pure Python implementation, Skulpt-compatible.
Playing with them now… also looking at types.SimpleNamespace. The Python documentation doesn’t really do them justice, which is why they seemed to be a poor fit.
Both of them offer == and !=, which is quite handy for dealing with user input, e.g., checking to see whether there are any unsaved changes in the page:
editable_values = deepcopy(original_values)
... # data binding and editing code here
if original_values != editable_values:
... # save edited values
In many cases, this simplistic comparison is enough.
Why I missed this: We’re conditioned to think of tuples (including namedtuples) as immutable, so you wouldn’t ordinarily think of the namedtupleeditable_values as being actually editable! But when its members are container types (list, dict, …), the container contents can still be changed.
Subtle.
If you need members to contain scalar values, and be able to edit those values (e.g., via data binding), then types.SimpleNamespace might be used instead. Unlike namedtuple, this doesn’t generate a new type (class); it creates values directly. But the resulting values still support deepcopy, ==, and !=, so it can still be a win.
Yes, I believe in the case of mutable objects inside immutable tuples, the memory reference pointers to the mutable objects are what is doing the “not changing” in the tuple.
So creating the tuple just increases the reference count of the mutable container type.
Shallow vs. deep copy really messed me when I started as a person who started in C++, then did PHP, then went to python thinking I never had to worry about pointers again!
As a longtime C/C++ programmer, I like to distinguish between pointers (which can be incremented and decremented, and optionally subscripted and de-referenced), and references, which are (almost always) de-referenced for you in advance. The latter are far simpler in behavior, and so they’re much easier to reason about.
Conflating the ideas, as many authors seem to do, only adds to the confusion. It’s called “reference counting”, not “pointer counting”, for a reason!
Eli makes an early aside, to address that very issue. It’s unfortunate that, even knowing better, they still stuck with the more ill-fitting term. At this rate, the terminology’s original precision and accuracy is going to popularized out of existence.
I’m looking forward to reading Eli’s posts and video! Implementing variables as references has a huge but subtle impact on language semantics. You have to reason about it differently than you do in some other mainstream languages. But because mental shortcuts are easy, and the in-language effects can be subtle, this can lead to extremely subtle bugs even in venerable Python code. Anything that helps us spot and prevent them is a boon.
You’re absolutely right - having been only a C programmer previously and not C++, I didn’t realise there was better terminology until quite a way in >.< Perhaps I’ll re-write this at some point, because I’m sure it’s only going to bother me more as time goes on.
Late to the party, but I remembered this post and found a nice video going over the performance of each of these options and their draw backs, so I figured it would be nice to share.