中学理科1630641 views
中学英語811710 views
雑学1473612 views
いろは3010814 views
LaTeX962153 views
小学算数1200427 views
世界の国564520 views
ヒストリア290598 views
高校倫理1440106 views
高校日本史190571 views
Help
Tools
NewsSpreadsheetCalendarSlidesTier ListPen ToolIllustrationCrayonPixel ArtASCII ArtPerspectiveEndless StairsGraphMind MapER DiagramFamily TreeMemeCurved TextImage EditorMosaicRetro FilterPencil SketchOCR/HighlighterMakeup EditorFaviconVideo TrimmerScrolling VideoVideo TitleColor PickerColor ExtractorBonfireFireworksWater RippleWater SplashBreaking GlassWood GrainMarble TextureCSS ButtonIcon MakerBar ChartGrouped Bar ChartStacked Bar ChartPie ChartLine ChartArea ChartStacked Area ChartScatter Plot3D Bar Chart3D Pie ChartBar Chart RaceBubble ChartPopulation PyramidPictogramEarningsCandlestick ChartInvestment RiskMortgage SimulatorCalculatorMatrix CalculatorFunction GraphPolynomial ExpansionVenn DiagramField VisualizerRubik's Cube Group TheoryTraveling SalesmanVoronoi and DelaunayFractalColumn ArithmeticDraw Math FiguresArithmetic AnimationArithmetic Word ProblemsCounting with Tree DiagramsCube NetsCross SectionsMotion PathMechanicsWavesLight and LensesThermodynamicsHow Semiconductors WorkMolecular StructuresAtomic OrbitalsElectrochemical CellsChemical EquilibriumCrystal LatticesBuffer pHComplex IonsDNA Double HelixCell DivisionMembrane ChannelsNerve ImpulseRock ClassificationWeatherConstellationsSolar and Lunar Eclipses3D ModelingFloor PlanSeismic StructuresIntersection TurnMaglevCooking AnimationOrigamiLive Viewer CountGeoJSON MapRailway MapPopulation MapCrime MapLand Price MapSchool MapShrine and Castle MapHouse of Representatives MapWord MapSolitaireReversiHakoiri MusumeChessHamburgerRippleSlide Puzzle MakerNeon PinballNovel MakerJapanese Typing PracticePiano Score EditorMusic Theory

English

Python の frozenset(イミュータブルな集合)

frozenset は変更不可能(イミュータブル)な集合だ。通常の set と同じ要素を持てるが、作成後に要素を追加・削除できない。

基本的な作成方法

frozenset() コンストラクタにイテラブルを渡して作成する。

fs = frozenset([1, 2, 3])
print(fs)       # frozenset({1, 2, 3})
print(type(fs)) # <class 'frozenset'>

set と同様に、重複は自動的に排除される。

fs = frozenset([1, 2, 2, 3, 3, 3])
print(fs)  # frozenset({1, 2, 3})

空の frozenset を作るには引数なしで呼び出す。

empty = frozenset()
print(empty)  # frozenset()

set との違い

frozenset はイミュータブルなため、要素を変更するメソッドが存在しない。

fs = frozenset([1, 2, 3])

# これらはすべてエラー
# fs.add(4)           # AttributeError
# fs.remove(1)        # AttributeError
# fs.update([4, 5])   # AttributeError
set

add(), remove(), update() など変更メソッドあり。ハッシュ不可。

frozenset

変更メソッドなし。ハッシュ可能で辞書のキーや集合の要素になれる。

ハッシュ可能である利点

frozenset はハッシュ可能なため、辞書のキーとして使える。

# frozenset を辞書のキーに
permissions = {
    frozenset(["read"]): "viewer",
    frozenset(["read", "write"]): "editor",
    frozenset(["read", "write", "delete"]): "admin"
}

user_perms = frozenset(["read", "write"])
print(permissions[user_perms])  # editor

通常の set ではこれができない。

# set は辞書のキーにできない
d = {
    {1, 2}: "value"  # TypeError: unhashable type: 'set'
}

集合の要素としても使える。つまり「集合の集合」が作れる。

# 冪集合(べきしゅうごう)を作る例
original = {1, 2}
power_set = {
    frozenset(),
    frozenset([1]),
    frozenset([2]),
    frozenset([1, 2])
}
print(power_set)

集合演算

frozenset でも和集合、積集合などの演算ができる。結果は frozenset になる。

a = frozenset([1, 2, 3])
b = frozenset([3, 4, 5])

print(a | b)  # frozenset({1, 2, 3, 4, 5})
print(a & b)  # frozenset({3})
print(a - b)  # frozenset({1, 2})
print(a ^ b)  # frozenset({1, 2, 4, 5})

set と frozenset を混ぜて演算すると、左側のオペランドの型になる。

s = {1, 2, 3}
fs = frozenset([3, 4, 5])

result1 = s | fs
print(type(result1))   # <class 'set'>

result2 = fs | s
print(type(result2))   # <class 'frozenset'>

set との相互変換

set と frozenset は簡単に変換できる。

# set から frozenset へ
s = {1, 2, 3}
fs = frozenset(s)

# frozenset から set へ
fs2 = frozenset([4, 5, 6])
s2 = set(fs2)

一時的に要素を変更したい場合、set に変換してから操作し、また frozenset に戻すパターンがある。

fs = frozenset([1, 2, 3])

# 変更したい場合は一度 set にする
temp = set(fs)
temp.add(4)
temp.remove(1)

# 再び frozenset に
fs = frozenset(temp)
print(fs)  # frozenset({2, 3, 4})

比較と判定

frozenset でも部分集合の判定などが可能だ。set との比較もできる。

fs1 = frozenset([1, 2])
fs2 = frozenset([1, 2, 3])
s = {1, 2, 3}

print(fs1 <= fs2)  # True
print(fs1 <= s)    # True
print(fs1.issubset(s))  # True

等価判定では、set と frozenset は要素が同じなら等しいと判定される。

s = {1, 2, 3}
fs = frozenset([1, 2, 3])

print(s == fs)  # True

ただし型は異なるので、is による同一性判定は False になる。

実用的なユースケース

関数の引数にデフォルト値として集合を使いたい場合、frozenset が安全だ。

# 危険な例(ミュータブルなデフォルト引数)
def bad_func(items=set()):
    items.add("new")
    return items

# 安全な例
def good_func(items=frozenset()):
    return set(items) | {"new"}

キャッシュのキーとしても活用できる。

from functools import lru_cache

@lru_cache(maxsize=100)
def expensive_operation(items: frozenset):
    # 重い処理
    return sum(items)

result = expensive_operation(frozenset([1, 2, 3]))

set はハッシュできないため lru_cache と組み合わせられないが、frozenset なら問題ない。

メモリと性能

frozenset は set とほぼ同じメモリ使用量で、検索の計算量も O(1) だ。イミュータブルであることによるオーバーヘッドはほとんどない。

import sys

s = set(range(1000))
fs = frozenset(range(1000))

print(sys.getsizeof(s))   # 32984
print(sys.getsizeof(fs))  # 32984

変更不可という制約が許容できる場面では、frozenset を積極的に使うことで意図しない変更を防げる。