DEV Community

Super Kai (Kazuya Ito)
Super Kai (Kazuya Ito)

Posted on • Edited on

Set in Python (1)

Buy Me a Coffee

*Memo:

  • My post explains set functions (1).
  • My post explains set functions (2).
  • My post explains a set and dictionary(dict) comprehension.
  • My post explains the shallow copy of the set with a tuple.
  • My post explains the shallow and deep copy of the set with an iterator.
  • My post explains a list and the list with indexing.
  • My post explains a tuple.
  • My post explains a dictionary (1).
  • My post explains an iterator (1).
  • My post explains a string.
  • My post explains a bytes.
  • My post explains a bytearray.

A set:

  • is the unordered collection of zero or more elements whose type is set:
    • Unordered means that the order of the elements in a set isn't kept so it doesn't guarantee that the order is always the same.
  • shouldn't be huge not to get MemoryError.
  • doesn't allow duplicated elements (even with different types).
  • is mutable so it can be changed:
  • can have the hashable types of elements:
    • A hashable type is the type whose value cannot be changed like str, bytes, int, float, complex, bool, tuple, frozenset, range or iterator.
  • cannot have the unhashable types of elements:
    • A unhashable type is the type whose value can be changed like bytearray, list, set or dict.
  • can be iterated with a for statement.
  • can be unpacked with an assignment and for statement, function and * but not with **.
  • is False if it's empty.
  • can be checked if a specific element is or isn't in it with in keyword or not and in keyword respectively.
  • can be checked if it is or isn't referred to by two variables with is keyword or not and is keyword respectively.
  • cannot be enlarged with * and a number.
  • can be created by {}, set() with or without an iterable or a set comprehension:
    • For set(), the words type conversion are also suitable in addition to the word creation.
  • cannot be read or changed by indexing or slicing.
  • can be continuously used through multiple variables.
  • can be copied to refer to a different set.

A set is for non-huge data otherwise it gets MemoryError.


{} can create a set as shown below:

*Memo:

  • Be careful, the empty curlybraces {} are an empty dictionary but not an empty set so use set() to create an empty set.
A = set() # Empty 1D set A = {} # dict not set A = {10, 20, 30, 40, 50} # 1D set A = {10, 20, 30, 10, 20, 30} # 1D set A = {10, 20, 30, 40, frozenset({50, 60, 70, 80})} # 2D set A = {frozenset({10, 20, 30, 40}), # 2D set  frozenset({50, 60, 70, 80})} A = {frozenset({10, 20, 30, 40}), # 3D set  frozenset({frozenset({50, 60}), frozenset({70, 80})})} A = {frozenset({frozenset({10, 20}), frozenset({30, 40})}), # 3D set  frozenset({frozenset({50, 60}), frozenset({70, 80})})} # No error  A = {1, 1.0, 1.0+0.0j, True} A = {'A', b'A', 2, 2.3, 2.3+4.5j, True, (2, 3), frozenset({2, 3}), range(2, 3), iter([2, 3])} for x in {0, 1, 2, 3, 4}: pass for x in {frozenset({10, 20, 30, 40}), frozenset({50, 60, 70, 80})}: pass for x in {frozenset({frozenset({10, 20}), frozenset({30, 40})}), frozenset({frozenset({50, 60}), frozenset({70, 80})})}: pass v1, v2, v3 = {0, 1, 2} v1, *v2, v3 = {0, 1, 2, 3, 4, 5} for v1, v2, v3 in {frozenset({0, 1, 2}), frozenset({3, 4, 5})}: pass for v1, *v2, v3 in {frozenset({0, 1, 2, 3, 4, 5}), frozenset({6, 7, 8, 9, 10, 11})}: pass print({*{0, 1, *{2}}, *{3, 4}}) print(*{0, 1, *{2}}, *{3, 4}) A = {x**2 for x in {0, 1, 2, 3, 4, 5, 6, 7}} A = {frozenset(y**2 for y in x) for x in {frozenset({0, 1, 2, 3}), frozenset({4, 5, 6, 7})}} A = {frozenset(frozenset(z**2 for z in y) for y in x) for x in {frozenset({frozenset({0, 1}), frozenset({2, 3})}), frozenset({frozenset({4, 5}), frozenset({6, 7})})}} # No error  A = {10, 20, [30, 40], 50, 60} A = {10, 20, {30, 40}, 50, 60} A = {10, 20, {30:40, 50:60}, 70, 80} A = {bytearray(b'Hello')} print(**{0, 1, 2, 3, 4}) A = {10, 20, 30} * 3 # Error 
Enter fullscreen mode Exit fullscreen mode

A set is the unordered collection of zero or more elements whose type is set as shown below:

A = {10, 20, 30, 40, 50} print(A) # {50, 20, 40, 10, 30}  print(type(A)) # <class 'set'> 
Enter fullscreen mode Exit fullscreen mode
A = set() # Empty set  print(A) # set() 
Enter fullscreen mode Exit fullscreen mode

A set doesn't allow duplicated elements (even with different types) as shown below:

A = {10, 20, 30, 10, 20, 30} print(A) # {10, 20, 30} 
Enter fullscreen mode Exit fullscreen mode
A = {1, 1.0, 1.0+0.0j, True} print(A) # {1} 
Enter fullscreen mode Exit fullscreen mode

A set can have the hashable types of elements as shown below:

A = {'A', b'A', 2, 2.3, 2.3+4.5j, True, (2, 3), frozenset({2, 3}), range(2, 3), iter([2, 3])} print(A) # {True, 2, 2.3, frozenset({2, 3}), # <list_iterator object at 0x000001F3B9E5F250>, # b'A', (2.3+4.5j), (2, 3), 'A', range(2, 3)} 
Enter fullscreen mode Exit fullscreen mode

A set cannot have the unhashable types of elements as shown below:

A = {10, 20, [30, 40], 50, 60} # set(list) # TypeError: unhashable type: 'list'  A = {10, 20, {30, 40}, 50, 60} # set(set) # TypeError: unhashable type: 'set'  A = {10, 20, {30:40, 50:60}, 70, 80} # set(dict) # TypeError: unhashable type: 'dict'  A = {bytearray(b'Hello')} # set(bytearray) # TypeError: unhashable type: 'bytearray' 
Enter fullscreen mode Exit fullscreen mode

A set can be iterated with a for statement as shown below:

<1D set>:

for x in {10, 20, 30, 40, 50}: print(x) # 40 # 10 # 50 # 20 # 30 
Enter fullscreen mode Exit fullscreen mode

<2D set>:

for x in {frozenset({10, 20, 30, 40}), frozenset({50, 60, 70, 80})}: for y in x: print(y) # 40 # 10 # 20 # 30 # 80 # 50 # 60 # 70 
Enter fullscreen mode Exit fullscreen mode

<3D set>:

for x in {frozenset({frozenset({10, 20}), frozenset({30, 40})}), frozenset({frozenset({50, 60}), frozenset({70, 80})})}: for y in x: for z in y: print(z) # 40 # 30 # 10 # 20 # 80 # 70 # 50 # 60 
Enter fullscreen mode Exit fullscreen mode

A set can be unpacked with an assignment and for statement, function and * but not with ** as shown below:

v1, v2, v3 = {0, 1, 2} print(v1, v2, v3) # 0 1 2 
Enter fullscreen mode Exit fullscreen mode
v1, *v2, v3 = {0, 1, 2, 3, 4, 5} print(v1, v2, v3) # 0 [1, 2, 3, 4] 5 print(v1, *v2, v3) # 0 1 2 3 4 5 
Enter fullscreen mode Exit fullscreen mode
for v1, v2, v3 in {frozenset({0, 1, 2}), frozenset({3, 4, 5})}: print(v1, v2, v3) # 3 4 5 # 0 1 2 
Enter fullscreen mode Exit fullscreen mode
for v1, *v2, v3 in {frozenset({0, 1, 2, 3, 4, 5}), frozenset({6, 7, 8, 9, 10, 11})}: print(v1, v2, v3) print(v1, *v2, v3) # 6 [7, 8, 9, 10] 11 # 6 7 8 9 10 11 # 0 [1, 2, 3, 4] 5 # 0 1 2 3 4 5 
Enter fullscreen mode Exit fullscreen mode
def func(p1='a', p2='b', p3='c', p4='d', p5='e', p6='f'): print(p1, p2, p3, p4, p5, p6) func() # a b c d e f  func(*{0, 1, 2, 3}, *{4, 5}) # 0 1 2 3 4 5 
Enter fullscreen mode Exit fullscreen mode
def func(p1='a', p2='b', *args): print(p1, p2, args) print(p1, p2, *args) print(p1, p2, ['A', 'B', *args, 'C', 'D']) func() # a b () # a b Nothing # a b ['A', 'B', 'C', 'D']  func(*{0, 1, 2, 3}, *{4, 5}) # 0 1 (2, 3, 4, 5) # 0 1 2 3 4 5 # 0 1 ['A', 'B', 2, 3, 4, 5, 'C', 'D'] 
Enter fullscreen mode Exit fullscreen mode
print({*{0, 1, *{2}}, *{3, 4}}) # {0, 1, 2, 3, 4} 
Enter fullscreen mode Exit fullscreen mode
print(*{0, 1, *{2}}, *{3, 4}) # 0 1 2 3 4 
Enter fullscreen mode Exit fullscreen mode
print(**{0, 1, 2, 3, 4}) # TypeError: print() argument after ** must be a mapping, not set 
Enter fullscreen mode Exit fullscreen mode

An empty set is False as shown below:

print(bool(set())) # Empty set # False  print(bool({0})) # set print(bool({frozenset()})) # set(Empty frozenset) # True 
Enter fullscreen mode Exit fullscreen mode

A set can be checked if a specific element is or isn't in it with in keyword or not and in keyword respectively as shown below:

v = {10, 20, frozenset({30, 40})} print(20 in v) # True  print({30, 40} in v) # True  print(2 in v) # False 
Enter fullscreen mode Exit fullscreen mode
v = {10, 20, frozenset({30, 40})} print(20 not in v) # False  print({30, 40} not in v) # False  print(2 not in v) # True 
Enter fullscreen mode Exit fullscreen mode

A set cannot be enlarged with * and a number as shown below:

A = {10, 20, 30} * 3 # TypeError: unsupported operand type(s) for *: 'set' and 'int' 
Enter fullscreen mode Exit fullscreen mode

set() can create a set with or without an iterable as shown below:

*Memo:

  • The 1st argument is iterable(Optional-Default:()-Type:Iterable):
    • Don't use iterable=.
# Empty set print(set()) print(set(())) # set()  print(set([0, 1, 2, 3, 4])) # list print(set((0, 1, 2, 3, 4))) # tuple print(set(iter([0, 1, 2, 3, 4]))) # iterator print(set({0, 1, 2, 3, 4})) # set print(set(frozenset({0, 1, 2, 3, 4}) )) # frozenset print(set(range(5))) # range # {0, 1, 2, 3, 4}  print(set({'name': 'John', 'age': 36})) # dict print(set({'name': 'John', 'age': 36}.keys())) # dict.keys() # {'age', 'name'}  print(set({'name': 'John', 'age': 36}.values())) # dict.values() # {'John', 36}  print(set({'name': 'John', 'age': 36}.items())) # dict.items() # {('age', 36), ('name', 'John')}  print(set('Hello')) # str # {'H', 'e', 'l', 'o'}  print(set(b'Hello')) # bytes print(set(bytearray(b'Hello'))) # bytearray # {72, 108, 101, 111} 
Enter fullscreen mode Exit fullscreen mode

A set comprehension can create a set as shown below:

<1D set>:

sample = {0, 1, 2, 3, 4, 5, 6, 7} A = {x**2 for x in sample} print(A) # {0, 1, 4, 36, 9, 16, 49, 25} 
Enter fullscreen mode Exit fullscreen mode

<2D set>:

sample = {frozenset({0, 1, 2, 3}), frozenset({4, 5, 6, 7})} A = {frozenset(y**2 for y in x) for x in sample} print(A) # {frozenset({16, 25, 36, 49}), frozenset({0, 1, 4, 9})} 
Enter fullscreen mode Exit fullscreen mode

<3D set>:

sample = {frozenset({frozenset({0, 1}), frozenset({2, 3})}), frozenset({frozenset({4, 5}), frozenset({6, 7})})} A = {frozenset(frozenset(z**2 for z in y) for y in x) for x in sample} print(A) # {frozenset({frozenset({16, 25}), frozenset({49, 36})}), # frozenset({frozenset({9, 4}), frozenset({0, 1})})} 
Enter fullscreen mode Exit fullscreen mode

Be careful, a huge set gets MemoryError as shown below:

A = range(100000000) print(set(v)) # MemoryError 
Enter fullscreen mode Exit fullscreen mode

A set cannot be read or changed by indexing or slicing as shown below:

*Memo:

  • A del statement can still be used to remove one or more variables themselves.
A = {10, 20, 30, 40, 50, 60} print(A[0], A[2:6]) # TypeError: 'set' object is not subscriptable 
Enter fullscreen mode Exit fullscreen mode
A = {10, 20, 30, 40, 50, 60} A[0] = 100 A[2:6] = [200, 300] # TypeError: 'set' object does not support item assignment 
Enter fullscreen mode Exit fullscreen mode
A = {10, 20, 30, 40, 50, 60} del A[0], A[3:5] # TypeError: 'set' object doesn't support item deletion 
Enter fullscreen mode Exit fullscreen mode
A = {10, 20, 30, 40, 50, 60} del A print(A) # NameError: name 'A' is not defined 
Enter fullscreen mode Exit fullscreen mode

If you really want to read or change a tuple, use list() and set() as shown below:

A = {10, 20, 30, 40, 50, 60} A = list(A) print(A[0], A[2:6]) # 50 [40, 10, 60, 30]  A[0] = 100 A[2:6] = [200, 300] A = set(A) print(A) # {200, 100, 20, 300} 
Enter fullscreen mode Exit fullscreen mode
A = {10, 20, 30, 40, 50, 60} A = list(A) del A[0], A[3:5] A = set(A) print(A) # {40, 10, 20} 
Enter fullscreen mode Exit fullscreen mode

A set can be continuously used through multiple variables as shown below:

A = B = C = {10, 20, 30} # Equivalent  # v1 = {10, 20, 30} A.update({40, 50}) # v2 = v1 B.remove(30) # v3 = v2 C.pop() print(A) # {20, 40, 10} print(B) # {20, 40, 10} print(C) # {20, 40, 10} 
Enter fullscreen mode Exit fullscreen mode

The variables A and B refer to the same set unless copied as shown below:

*Memo:

  • is keyword or is and not keyword can check if A and B refer or don't refer to the same set respectively.
  • set.copy(), copy.copy() and set() do shallow copy:
    • set.copy() has no arguments.
  • copy.deepcopy() does deep copy.
  • copy.deepcopy() should be used because it's safe, doing copy deeply while set.copy(), copy.copy() and set() aren't safe, doing copy shallowly.
import copy A = {10, 20, 30} B = A # B refers to the same set as A.  B.add(40) # Changes the same set as A.  # ↓↓ print(A) # {40, 10, 20, 30} print(B) # {40, 10, 20, 30}  # ↑↑ print(A is B, A is not B) # True False  # B refers to the different set from A. B = A.copy() B = copy.copy(A) B = copy.deepcopy(A) B = set(A) B.add(50) # Changes a different set from A.  print(A) # {40, 10, 20, 30} print(B) # {40, 10, 50, 20, 30}  # ↑↑ print(A is B, A is not B) # False True 
Enter fullscreen mode Exit fullscreen mode

Top comments (0)