<div dir="ltr"><div><div>"""<br></div><div>Demonstrating the descriptor protocol</div><div>(cl) MIT by K. Urner</div><div>"""</div><div><br></div><div>class Property:</div><div><br></div><div>    def __init__(self, start):</div><div>        <a href="http://self.it">self.it</a> = start</div><div><br></div><div>    def __set__(self, obj, val):</div><div>        if isinstance(obj, ReadOnly):</div><div>            print("Can't set property from this child")</div><div>        else:</div><div>            <a href="http://obj.it">obj.it</a> = val</div><div><br></div><div>    def __get__(self, obj, objtype=None):</div><div>        if not hasattr(obj, "it"):</div><div>            <a href="http://obj.it">obj.it</a> = <a href="http://self.it">self.it</a></div><div>        return <a href="http://obj.it">obj.it</a></div><div><br></div><div><br></div><div>class Thing:</div><div><br></div><div>    property = Property(0)</div><div><br></div><div>class ReadOnly(Thing):</div><div>    pass</div><div><br></div><div>class ReadWrite(Thing):</div><div>    pass</div><div><br></div><div># Test Code</div><div><br></div><div># Subclasses treated differently</div><div>the_thing = ReadOnly()</div><div>print("Before:",the_thing.property)</div><div>the_thing.property = 42</div><div>print("After:",the_thing.property)</div><div>print("="*10)</div><div>the_thing = ReadWrite()</div><div>print("Before:", the_thing.property)</div><div>the_thing.property = 42</div><div>print("After:",the_thing.property)</div><div><br></div><div># Multiple instances have their own values</div><div>print("="*10)</div><div>thing1 = Thing()</div><div>thing2 = Thing()</div><div>thing1.property = 1</div><div>thing2.property = 2</div><div>print("thing1.property:", thing1.property, thing1.__dict__)</div><div>print("thing2.property:", thing2.property, thing2.__dict__)</div><div><br></div><div><br></div><div># from the docs: <a href="https://docs.python.org/3.4/howto/descriptor.html">https://docs.python.org/3.4/howto/descriptor.html</a></div><div>class Dict(dict): # subclass rather than presume defining Dict top-level</div><div><br></div><div>    def fromkeys(klass, iterable, value=None):</div><div>        "Emulate dict_fromkeys() in Objects/dictobject.c"</div><div>        d = klass()</div><div>        for key in iterable:</div><div>            d[key] = value</div><div>        return d</div><div>    fromkeys = classmethod(fromkeys)</div><div><br></div><div>print(Dict.fromkeys('abracadabra'))</div><div># {'a': None, 'r': None, 'b': None, 'c': None, 'd': None}</div></div><div><br></div><div>OUTPUT from the above:</div><div><br></div><div><div>Before: 0</div><div>Can't set property from this child</div><div>After: 0</div><div>==========</div><div>Before: 0</div><div>After: 42</div><div>==========</div><div>thing1.property: 1 {'it': 1}</div><div>thing2.property: 2 {'it': 2}</div><div>{'a': None, 'r': None, 'b': None, 'c': None, 'd': None}</div><div><br></div><div>Process finished with exit code 0</div></div><div><br></div><div><br></div></div>