ヒストリア290598 views
高校化学2924392 views
教育149510 views
中学社会668760 views
小学社会310485 views
LaTeX962153 views
りんご209490 views
高校物理160203 views
中学数学623755 views
中学理科1630641 views
Help
Tools
NewsSpreadsheetCalendarBookkeepingMarkdown TablesSlidesTier ListPen ToolIllustrationCrayonWatercolorPixel ArtASCII ArtPerspectiveEndless StairsGraphMind MapER DiagramFamily TreeMemeCurved TextImage EditorMosaicRetro FilterPencil SketchSwirl EffectLine ArtOCR/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 NetsRolling DiceCross SectionsMotion PathMechanicsWavesElectromagnetic WavesCapacitorsLight and LensesThermodynamicsHow Semiconductors WorkMolecular StructuresAtomic OrbitalsElectrochemical CellsChemical EquilibriumCrystal LatticesBuffer pHOrganic Reaction MapPeriodic TableComplex IonsDNA Double HelixCell DivisionMembrane ChannelsNerve ImpulseMuscle ContractionHormones and HomeostasisRock 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 TheoryShogi StrategyPiano Rhythm Game

English

Python の自由変数とセル変数(__closure__)の仕組み

クロージャは外側のスコープの変数を参照する内部関数です。その仕組みは __closure__ 属性、自由変数、セル変数によって実現されています。

クロージャの基本

def outer(x):
    def inner(y):
        return x + y
    return inner

add_10 = outer(10)
print(add_10(5))  # 15

inner 関数は outer のローカル変数 x を参照しています。outer が終了しても x の値は保持されます。

closure 属性

クロージャが参照する外部変数は __closure__ に格納されます。

print(add_10.__closure__)
# (<cell at 0x...: int object at 0x...>,)

print(add_10.__closure__[0].cell_contents)  # 10

自由変数とセル変数

自由変数(free variable)

内部関数から見た、外側スコープの変数。co_freevars に記録。

セル変数(cell variable)

外部関数から見た、内部関数に渡す変数。co_cellvars に記録。

def outer(x):
    def inner(y):
        return x + y
    return inner

# 外側から見ると x はセル変数
print(outer.__code__.co_cellvars)  # ('x',)

# 内側から見ると x は自由変数
inner = outer(10)
print(inner.__code__.co_freevars)  # ('x',)

セルオブジェクトの仕組み

セルは変数への間接参照を提供します。これにより、外側関数が終了しても変数を生存させられます。

def make_counter():
    count = 0
    def increment():
        nonlocal count
        count += 1
        return count
    return increment

counter = make_counter()
print(counter())  # 1
print(counter())  # 2
print(counter.__closure__[0].cell_contents)  # 2

複数の自由変数

def outer(a, b):
    def inner(c):
        return a + b + c
    return inner

fn = outer(1, 2)
print(fn.__code__.co_freevars)  # ('a', 'b')
print([cell.cell_contents for cell in fn.__closure__])  # [1, 2]

クロージャの内部構造を理解すると、なぜ変数が保持されるのか、nonlocal がどう動作するのかが明確になります。