Like for this specific example:
https://stackoverflow.com/questions/2612802/how-to-clone-or-...
Knowing the right thing to do requires you be informed about the history of Python language design. Like you could just read the documentation and see that lists have a copy method but it doesn't give you a good grasp of what the alternatives are and why you might choose them. And prior to Python 3.3 you're expected to know that the best practice way to do this is to leverage an edge case in the slicing syntax or the list function. Doesn't matter if you're the best computer scientist in the world, sifting through the massive corpous of documentation and historical knowledge required to write good Python is nigh impossible unless you're willing to dedicate yourself Python.
This is something that languages need to tackle because the gap between doing a thing and doing that same thing in a way that follows language conventions and best practices is too damn high.
That said, copying is in this case the end result of distinct different methods. In the stackoverflow answer, the only redundant way to copy is the .copy method list has. If I understand right it is just a convenient method in order so new programmers don't need to import the copy module.
list() is a common way to create a new list, and the constructor can take a initial sequence. Lists are sequences, so list can take a list, but that is just a side effect.
Slicing is very useful for taking the first or last objects of a list. if you take all the first and all the last objects, you get a copy. Its not the primary function of slicing, but a useful side effect.
The copy module is a lower level interface to work with python objects. As any other lower level interface it mostly used in exception cases when you really want a "deep copy". I have used that trick once in my whole programming career, and it was to work around a restriction in a third-party module for a corner case which they clearly didn't consider.
This, above many other things, keeps me coming back to Python year after year.
Outside of lisps, I find Python to be one of the simplest syntaxes, so the only effort is the logic to solve the problem.
Golang, by contrast, is really quite schizophrenic sometimes about whether it wants to be a high or low level language.
Compare it to C, which it has displaced as an introductory language. Python and C are superficially interchangeable to a beginner, but to learn C you have to invest time into pointers and memory management. Python sacrifices the efficiency of direct memory management to avoid the complication of pointers. Arguably, this is a significant benefit because it also cuts down on ways to introduce bugs.
Compare it to a Lisp - Python has a pretty inferior set of basic capabilities (can't even use a dict as a dict key, drives me mad), but that just means there is only one easy way to do things that everyone uses. Less room to think up clever ways of doing things, less complexity reading other's code.
Being the 'best' language for a task has a huge cost - incidental complexity created by including specialist constructs. Python's success suggests maybe programmers prefer this complexity to be encapsulated in a library rather than the language core.
Curious, is this actually something you want to do often? While there is no hashable+immutable frozendict ala frozenset, you could throw one together or even define a hash function on a subclass and "swim at your own risk" not to mutate it later.
I've encountered this enough with lists and the obvious solution is to cast them to tuples. Can't say I've found the same with dicts tho.
As for the comparison with lisp - in most lisps this is a non issue because nearly all structures are immutable
You can still create a hashable key from a dict with FrozenSet(mydict.items()).
tuple(d.items())
>>> tuple({1:2,3:4}.items()) == tuple({3:4,1:2}.items())
False
>>> frozenset({1:2,3:4}.items()) == frozenset({3:4,1:2}.items())
TrueMany major programming languages undersell how natural key-value data structures are; usually by providing unwieldy mapping data types. Clojure has spoiled me.
> you could throw one together
Yeah, I do. Most Python programmers wouldn't see a need for that, but that can be attributed to Python not having the capability by default and so they've just internalised not to use dict for anything that needs to be a key. World's mildest form of learned helplessness, I suppose.
You're being extremely uncharitable here.
To a Python programmer "using a dict as a key" is a nonsensical idea for the same reason "using a list as a key" is — both dicts and lists are mutable. Python programmers don't think of dicts or lists as synonymous with their content.
I'm assuming you don't want to literally use a dict as a key, you want to use the keys and values contained in a dict as a key. Nothing stops you. You just have to say it:
point = dict(x=4, y=5, z=1)
point_reviews = dict()
point_reviews[tuple(point.items())] = "A+++ great coord would point to again"
You might wonder why you can't just use dicts directly. Again, dicts are mutable. What happens if you write: point = dict(x=0, y=9001)
point_reviews = dict()
point_reviews[point] = "Love how it's over 9000 here!"
point["y"] = 8999
result = point_reviews[dict(x=0, y=8999)] # Is this a KeyError or not?
More detail on this issue is explained here: https://wiki.python.org/moin/DictionaryKeysIn the simplest case where you have a predefined list of keys, I'd suggest using a namedtuple instead of a dict. If you need to treat a dict's content as hashable but can't enumerate the keys, `tuple(d.items())` is probably the best choice in recent Python versions. Be aware though that in older Pythons you can't rely on stable sort order of dictionary items, so you have to use something like `frozenset(d.items())`.
>>> tuple(dict(a=1, b=2).items())
(('a', 1), ('b', 2))
>>> tuple(dict(b=2, a=1).items())
(('b', 2), ('a', 1))
Of course, if you can absolutely guarantee how the dictionary has been constructed, it is possible. No rules are absolute. But in my experience, frozenset() is probably better: >>> frozenset(dict(a=1, b=2).items())
frozenset({('b', 2), ('a', 1)})
>>> frozenset(dict(b=2, a=1).items())
frozenset({('b', 2), ('a', 1)})
(Or sometimes even id(), as, if you are confident enough that the dictionary is identical, that might be because it came from the same place. If you are building a reverse dictionary, say, or a cache of indices. Though obviously that it is much more situationally dependent.) dict(a=1,b=2) == dict(b=2,a=1)
is True (on 3.7.3). I'm not too keen on introducing a third type of equality on the same type, even if it makes some theoretical sense. >>> a = {}
>>> x = id(a)
>>> del a
>>> a = {}
>>> y = id(a)
>>> x == y
TrueGive them a string, they return a table or function. Give them the table or function, they return a string.
It’s a useful technique that you can only apply if your hashmap can map anything to anything.
Any hashmap will have problems with storing mutable objects, where the hash value itself can change after the object has been stored, causing some very unwanted paradoxes.
And that is the problem with Python dicts as keys.
I just assumed it was the former, based on the fact that dicts are disallowed as keys.
The reason for that choice is because the object is mutable.
dict = { "foo" : "bar" }
set = { dict : true }
set.has_key?(dict) # true
I'm sure there are other use cases where dict keys can be convenient.
someset = {"one", "two", "three"}
"one" in someset # true
frozen = frozenset(someset)
somedict = {frozen: "example"}
frozen in somedict # true somedict[frozen] # "example"
I would think a NamedTuple would do the trick? (https://docs.python.org/3/library/collections.html#collectio...)
but often better than master of one
You'll look like a community expert and thought leader in no time.
Helps the resume inhalers that weigh these arbitrary things.
More complex questions about specific frameworks or how that might work with your ORM and memory cache just don't get the attention.
Some programming language and frameworks have more active communities on StackOverflow than others.
So in my sprints, I would typically have 3 tasks in progress at once: 1 I would work on myself, 1 would go on Stackoverflow waiting for the answer, and 1 would be something that required progress from a different team in the company (like a new API endpoint so I could do something on a frontend, or different service)
It was pretty efficient for me. In some communities, the real thought leaders and framework developers are on stack overflow, watching the hashtag like a hawk.
You can also use github issues on the actual package you have issue with pretty well too, alongside it.
So you're really crowdsourcing a lot, and evaluating if that solution is correct enough for your implementation.
But so many times, especially with frameworks, the answer is a good copy and paste job. your mileage and use case may vary.