Both of these will give a duplicate of a set:
shallow_copy_of_set = set(old_set)
Or:
shallow_copy_of_set = old_set.copy() #Which is more readable.
The reason that the first way above doesn't give a set of a set, is that the proper syntax for that would be set([old_set])
. Which wouldn't work, because set
s can't be elements in other set
s, because they are unhashable by virtue of being mutable. However, this isn't true for frozenset
s, so e.g. frozenset(frozenset(frozenset([1,2,3]))) == frozenset([1, 2, 3])
.
So a rule of thumb for replicating any of instance of the basic data structures in Python (lists, dict, set, frozenset, string):
a2 = list(a) #a is a list
b2 = set(b) #b is a set
c2 = dict(c) #c is a dict
d2 = frozenset(d) #d is a frozenset
e2 = str(e) #e is a string
#All of the above give a (shallow) copy.
So, if x
is either of those types, then
shallow_copy_of_x = type(x)(x) #Highly unreadable! But economical.
Note that only dict
, set
and frozenset
have the built-in copy()
method. It would probably be a good idea that lists and strings had a copy()
method too, for uniformity and readability. But they don't, at least in Python 2.7.3 which I'm testing with.
list
s have a.copy()
method.str
does not, but it also doesn't need one; it's immutable, so copying is meaningless (for general sequence types, you can slice with[:]
, which works onstr
, it's just pointless). If you really need to handle shallow-copying arbitrary types (silently reusing the existing object for immutable types likestr
), you'd just use thecopy
module, and doshallow_copy_of_x = copy.copy(x)
(which is significantly clearer thantype(x)(x)
, and handles types where the constructor doesn't accept an instance of the class). – Rombert