ヒストリア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 のデコレータのスタック順序と実行順序

複数のデコレータを重ねた場合、適用順序と実行順序が異なります。この仕組みを理解しないと、予期しない動作が起きます。

デコレータの適用順序

デコレータは下から上に適用されます。

@decorator_a
@decorator_b
@decorator_c
def func():
    pass

# 等価な記述
func = decorator_a(decorator_b(decorator_c(func)))

最も内側(func に近い)の decorator_c が最初に適用されます。

実行順序

ラッパー関数の実行は、適用の逆順(上から下)になります。

def decorator(name):
    def wrapper(func):
        def inner(*args, **kwargs):
            print(f"{name}: before")
            result = func(*args, **kwargs)
            print(f"{name}: after")
            return result
        return inner
    return wrapper

@decorator("A")
@decorator("B")
@decorator("C")
def greet():
    print("Hello!")

greet()

出力:

A: before
B: before
C: before
Hello!
C: after
B: after
A: after

外側のデコレータから実行が始まり、内側に向かい、戻るときは逆順です。

順序が重要な例

from functools import wraps

def require_auth(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        print("Checking authentication")
        return func(*args, **kwargs)
    return wrapper

def log_call(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        print(f"Calling {func.__name__}")
        return func(*args, **kwargs)
    return wrapper

# ログを先に出したい場合
@log_call
@require_auth
def action():
    print("Action executed")

action()
# Calling wrapper ← log_call が wrapper を見ている
# Checking authentication
# Action executed

この例では log_call が require_auth のラッパーを見てしまいます。

@wraps の効果

wraps を使えば、関数名が保持されます。

# wraps を使った場合の出力
# Calling action
# Checking authentication
# Action executed

デコレータの順序を決める際は、実行順序を意識して設計しましょう。