Computer368106 views
中学英語811710 views
高校生物551766 views
りんご209490 views
高校日本史190571 views
MathPython497343 views
世界の国564520 views
いろは3010814 views
中学社会668760 views
LaTeX962153 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 のディスクリプタプロトコルと関数の関係

ディスクリプタは __get__, __set__, __delete__ を定義したオブジェクトで、属性アクセスをカスタマイズできます。実は Python の関数もディスクリプタであり、これがメソッドの仕組みの根幹です。

ディスクリプタプロトコル

class Descriptor:
    def __get__(self, obj, objtype=None):
        print(f"__get__ called: obj={obj}, objtype={objtype}")
        return "value"
    
    def __set__(self, obj, value):
        print(f"__set__ called: obj={obj}, value={value}")

class MyClass:
    attr = Descriptor()

obj = MyClass()
print(obj.attr)    # __get__ が呼ばれる
obj.attr = 10      # __set__ が呼ばれる

関数はディスクリプタ

関数オブジェクトは __get__ を持っています。これがメソッドバインディングの仕組みです。

def greet(self):
    return f"Hello, {self.name}!"

print(hasattr(greet, "__get__"))  # True

クラス内で関数を定義すると、インスタンスからアクセスしたときに __get__ が呼ばれ、バウンドメソッドが返されます。

class Person:
    def __init__(self, name):
        self.name = name
    
    def greet(self):
        return f"Hello, {self.name}!"

p = Person("Alice")

# クラス経由:関数そのもの
print(Person.greet)        # <function Person.greet>

# インスタンス経由:バウンドメソッド
print(p.greet)             # <bound method Person.greet of <Person>>

get の動作を確認

func = Person.__dict__["greet"]
print(func)                      # <function Person.greet>
print(func.__get__(p, Person))   # <bound method Person.greet of <Person>>

インスタンス経由でアクセスすると、func.__get__(instance, type) が呼ばれ、第一引数が束縛されたメソッドオブジェクトが返されます。

自作ディスクリプタで関数をラップ

class LoggedMethod:
    def __init__(self, func):
        self.func = func
    
    def __get__(self, obj, objtype=None):
        if obj is None:
            return self.func
        def wrapper(*args, **kwargs):
            print(f"Calling {self.func.__name__}")
            return self.func(obj, *args, **kwargs)
        return wrapper

ディスクリプタを理解すると、プロパティ、クラスメソッド、スタティックメソッドの仕組みも明確になります。