DEV Community

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

Posted on

Frozenset in Python (1)

Buy Me a Coffee

*Memo:

  • My post explains a set (1).
  • My post explains set and frozenset functions (1).
  • My post explains set and frozenset functions (2).
  • My post explains set and frozenset functions (3).
  • My post explains set and frozenset functions (4).
  • 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 frozenset:

  • is the unordered collection of zero or more elements whose type is frozenset:
    • Unordered means that the order of the elements in a frozenset 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 immutable(hashable) so it cannot 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 frozenset() with or without an iterable or a frozenset comprehension:
    • For frozenset(), the words type conversion are also suitable in addition to the word creation.
  • can be used with len() to get the length.
  • 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 frozenset is for non-huge data otherwise it gets MemoryError.


frozenset() can create a frozensetas shown below:

A = frozenset()                                   # Empty 1D frozenset
A = frozenset([10, 20, 30, 40, 50])               # 1D frozenset
A = frozenset([10, 20, 30, 10, 20, 30])           # 1D frozenset
A = frozenset([10, 20, 30, 40,                    # 2D frozenset
               frozenset([50, 60, 70, 80])])
A = frozenset([frozenset([10, 20, 30, 40]),       # 2D frozenset
               frozenset([50, 60, 70, 80])])
A = frozenset([frozenset([10, 20, 30, 40]),       # 3D frozenset
               frozenset([frozenset([50, 60]),
                          frozenset([70, 80])])])
A = frozenset([frozenset([frozenset([10, 20]),    # 3D frozenset
                          frozenset([30, 40])]),
               frozenset([frozenset([50, 60]),
                          frozenset([70, 80])])])
# No error

A = frozenset([0, 0.0, 0.0+0.0j, False])
A = frozenset([1, 1.0, 1.0+0.0j, True])
A = frozenset(['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 frozenset([0, 1, 2, 3, 4]): pass
for x in frozenset([frozenset([10, 20, 30, 40]),
                    frozenset([50, 60, 70, 80])]: pass
for x in frozenset([frozenset([frozenset([10, 20]),
                               frozenset([30, 40])]),
                    frozenset([frozenset([50, 60]),
                               frozenset([70, 80])])]): pass
v1, v2, v3 = frozenset([0, 1, 2])
v1, *v2, v3 = frozenset([0, 1, 2, 3, 4, 5])
for v1, v2, v3 in frozenset([frozenset([0, 1, 2]),
                             frozenset([3, 4, 5])]): pass
for v1, *v2, v3 in frozenset([frozenset([0, 1, 2, 3, 4, 5]),
                              frozenset([6, 7, 8, 9, 10, 11])]): pass
print(*frozenset([0, 1]), 2, *frozenset([3, 4, *frozenset([5])]))
print(frozenset([*frozenset([0, 1]), 2,
                 *frozenset([3, 4, *frozenset([5])])]))
A = frozenset(x**2 for x in frozenset([0, 1, 2, 3, 4, 5, 6, 7]))
A = frozenset(frozenset(y**2 for y in x) for x in
        frozenset([frozenset([0, 1, 2, 3]),
                   frozenset([4, 5, 6, 7])]))
A = frozenset(frozenset(frozenset(z**2 for z in y) for y in x) for x in
        frozenset([frozenset([frozenset([0, 1]), frozenset([2, 3])]),
                   frozenset([frozenset([4, 5]), frozenset([6, 7])])]))
# No error

A = frozenset([10, 20, [30, 40], 50, 60])
A = frozenset([10, 20, {30, 40}, 50, 60])
A = frozenset([10, 20, {30:40, 50:60}, 70, 80])
A = frozenset([bytearray(b'Hello')])
A = frozenset([10, 20, 30]) * 3
A = frozenset(range(1000000000))
# Error
Enter fullscreen mode Exit fullscreen mode

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

A = frozenset([10, 20, 30, 40, 50])

print(A)
# frozenset({40, 10, 50, 20, 30})

print(type(A))
# <class 'frozenset'>
Enter fullscreen mode Exit fullscreen mode
A = frozenset() # Empty frozenset

print(A)
# frozenset()
Enter fullscreen mode Exit fullscreen mode

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

A = frozenset([10, 20, 30, 10, 20, 30])

print(A)
# frozenset({10, 20, 30})
Enter fullscreen mode Exit fullscreen mode
A = frozenset([0, 0.0, 0.0+0.0j, False])

print(A)
# frozenset({0})
Enter fullscreen mode Exit fullscreen mode
A = frozenset([1, 1.0, 1.0+0.0j, True])

print(A)
# frozenset({1})
Enter fullscreen mode Exit fullscreen mode

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

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

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

A = frozenset([10, 20, [30, 40], 50, 60])       # frozenset(list)
# TypeError: unhashable type: 'list'

A = frozenset([10, 20, {30, 40}, 50, 60])       # frozenset(set)
# TypeError: unhashable type: 'set'

A = frozenset([10, 20, {30:40, 50:60}, 70, 80]) # frozenset(dict)
# TypeError: unhashable type: 'dict'

A = frozenset([bytearray(b'Hello')])            # frozenset(bytearray)
# TypeError: unhashable type: 'bytearray'
Enter fullscreen mode Exit fullscreen mode

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

<1D frozenset>:

for x in frozenset([10, 20, 30, 40, 50]):
    print(x)
# 40
# 10
# 50
# 20
# 30
Enter fullscreen mode Exit fullscreen mode

<2D frozenset>:

for x in frozenset([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 frozenset>:

for x in frozenset([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 frozenset can be unpacked with an assignment and for statement, function and * but not with ** as shown below:

v1, v2, v3 = frozenset([0, 1, 2])

print(v1, v2, v3)
# 0 1 2
Enter fullscreen mode Exit fullscreen mode
v1, *v2, v3 = frozenset([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([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([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
print(*frozenset([0, 1]), 2, *frozenset([3, 4, *frozenset([5])]))
# 0 1 2 3 4 5
Enter fullscreen mode Exit fullscreen mode
print(frozenset([*frozenset([0, 1]), 2,
                 *frozenset([3, 4, *frozenset([5])])]))
# frozenset({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(*frozenset([0, 1, 2, 3]), *frozenset([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(*frozenset([0, 1, 2, 3]), *frozenset([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

An empty frozenset is False as shown below:

print(bool(frozenset()))              # Empty frozenset
# False

print(bool(frozenset([0])))           # frozenset
print(bool(frozenset([frozenset()]))) # frozenset(Empty frozenset)
# True
Enter fullscreen mode Exit fullscreen mode

A frozenset 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 = frozenset([10, 20, frozenset([30, 40])])

print(20 in v)
# True

print(frozenset([30, 40]) in v)
# True

print(2 in v)
# False
Enter fullscreen mode Exit fullscreen mode
v = frozenset([10, 20, frozenset([30, 40])])

print(20 not in v)
# False

print(frozenset([30, 40]) not in v)
# False

print(2 not in v)
# True
Enter fullscreen mode Exit fullscreen mode

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

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

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

*Memo:

  • The 1st argument is iterable(Optional-Default:()-Type:Iterable):
    • Don't use iterable=.
# Empty frozenset
print(frozenset())
print(frozenset(()))
# frozenset()

print(frozenset([0, 1, 2, 3, 4]))                      # list
print(frozenset((0, 1, 2, 3, 4)))                      # tuple
print(frozenset(iter([0, 1, 2, 3, 4])))                # iterator
print(frozenset({0, 1, 2, 3, 4}))                      # set
print(frozenset(frozenset([0, 1, 2, 3, 4])))           # frozenset
print(frozenset(range(5)))                             # range
# frozenset({0, 1, 2, 3, 4})

print(frozenset({'name': 'John', 'age': 36}))          # dict
print(frozenset({'name': 'John', 'age': 36}.keys()))   # dict.keys()
# frozenset({'age', 'name'})

print(frozenset({'name': 'John', 'age': 36}.values())) # dict.values()
# frozenset({'John', 36})

print(frozenset({'name': 'John', 'age': 36}.items()))  # dict.items()
# frozenset({('name', 'John'), ('age', 36)})

print(frozenset('Hello'))                              # str
# frozenset({'o', 'l', 'e', 'H'})

print(frozenset(b'Hello'))                             # bytes
print(frozenset(bytearray(b'Hello')))                  # bytearray
# frozenset({72, 108, 101, 111})
Enter fullscreen mode Exit fullscreen mode

A frozenset comprehension can create a frozenset as shown below:

<1D frozenset>:

sample = frozenset([0, 1, 2, 3, 4, 5, 6, 7])

A = frozenset(x**2 for x in sample)

print(A)
# frozenset({0, 1, 4, 36, 9, 16, 49, 25})
Enter fullscreen mode Exit fullscreen mode

<2D frozenset>:

sample = frozenset([frozenset([0, 1, 2, 3]), frozenset([4, 5, 6, 7])])

A = frozenset(frozenset(y**2 for y in x) for x in sample)

print(A)
# frozenset({frozenset({16, 25, 36, 49}), frozenset({0, 1, 4, 9})})
Enter fullscreen mode Exit fullscreen mode

<3D frozenset>:

sample = frozenset([frozenset([frozenset([0, 1]), frozenset([2, 3])]),
                    frozenset([frozenset([4, 5]), frozenset([6, 7])])])

A = frozenset(frozenset(frozenset(z**2 for z in y) for y in x) for x in sample)

print(A)
# frozenset({frozenset({frozenset({16, 25}), frozenset({49, 36})}),
#            frozenset({frozenset({9, 4}), frozenset({0, 1})})})
Enter fullscreen mode Exit fullscreen mode

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

A = range(1000000000)

print(frozenset(A))
# MemoryError
Enter fullscreen mode Exit fullscreen mode

A frozenset can be used with len() to get the length as shown below:

A = frozenset([10, 20, 30, 40, 50])

print(len(A))
# 5
Enter fullscreen mode Exit fullscreen mode

A frozenset 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 = frozenset([10, 20, 30, 40, 50, 60])

print(A[0], A[2:6])
# TypeError: 'frozenset' object is not subscriptable
Enter fullscreen mode Exit fullscreen mode
A = frozenset([10, 20, 30, 40, 50, 60])

A[0] = 100
A[2:6] = [200, 300]
# TypeError: 'frozenset' object does not support item assignment
Enter fullscreen mode Exit fullscreen mode
A = frozenset([10, 20, 30, 40, 50, 60])

del A[0], A[3:5]
# TypeError: 'frozenset' object doesn't support item deletion
Enter fullscreen mode Exit fullscreen mode
A = frozenset([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 frozenset, use list() and frozenset() as shown below:

A = frozenset([10, 20, 30, 40, 50, 60])

A = list(A)

print(A[0], A[2:6])
# 40 [50, 20, 60, 30]

A[0] = 100
A[2:6] = [200, 300]

A = frozenset(A)

print(A)
# frozenset({200, 10, 100, 300})
Enter fullscreen mode Exit fullscreen mode
A = frozenset([10, 20, 30, 40, 50, 60])

A = list(A)

del A[0], A[3:5]

A = frozenset(A)

print(A)
# frozenset({10, 50, 20})
Enter fullscreen mode Exit fullscreen mode

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

A = B = C = frozenset([10, 20, 30, 40, 50]) 
                                     # Equivalent
                                     # A = frozenset([10, 20, 30, 40, 50])
                                     # B = A
                                     # C = B
print(A) # frozenset({40, 10, 50, 20, 30})
print(B) # frozenset({40, 10, 50, 20, 30})
print(C) # frozenset({40, 10, 50, 20, 30})
Enter fullscreen mode Exit fullscreen mode

The variables A and B always refer to the same frozenset because a frozenset cannot be 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 frozenset respectively.
  • frozenset.copy() and copy.copy() do shallow copy:
    • frozenset.copy() has no arguments.
  • frozenset() doesn't do shallow copy.
  • copy.deepcopy() does deep copy.
  • copy.deepcopy() should be used because it's safe, doing copy deeply while frozenset.copy() and copy.copy() aren't safe, doing copy shallowly.
import copy 

A = frozenset([10, 20, 30, 40, 50])

B = A # B refers to the same frozenset as A.

print(A) # frozenset({40, 10, 50, 20, 30})
print(B) # frozenset({40, 10, 50, 20, 30})

print(A is B, A is not B)
# True False

# B refers to the same frozenset as A.
B = A.copy()
B = copy.copy(A)
B = copy.deepcopy(A)
B = frozenset(A)

print(A) # frozenset({40, 10, 50, 20, 30})
print(B) # frozenset({40, 10, 50, 20, 30})

print(A is B, A is not B)
# True False
Enter fullscreen mode Exit fullscreen mode

Top comments (0)