"""
Demonstrating the descriptor protocol
(cl) MIT by K. Urner
"""

class Property:

    def __init__(self, start):
        self.it = start

    def __set__(self, obj, val):
        if isinstance(obj, ReadOnly):
            print("Can't set property from this child")
        else:
            obj.it = val

    def __get__(self, obj, objtype=None):
        if not hasattr(obj, "it"):
            obj.it = self.it
        return obj.it


class Thing:

    property = Property(0)

class ReadOnly(Thing):
    pass

class ReadWrite(Thing):
    pass

# Test Code

# Subclasses treated differently
the_thing = ReadOnly()
print("Before:",the_thing.property)
the_thing.property = 42
print("After:",the_thing.property)
print("="*10)
the_thing = ReadWrite()
print("Before:", the_thing.property)
the_thing.property = 42
print("After:",the_thing.property)

# Multiple instances have their own values
print("="*10)
thing1 = Thing()
thing2 = Thing()
thing1.property = 1
thing2.property = 2
print("thing1.property:", thing1.property, thing1.__dict__)
print("thing2.property:", thing2.property, thing2.__dict__)


# from the docs: https://docs.python.org/3.4/howto/descriptor.html
class Dict(dict): # subclass rather than presume defining Dict top-level

    def fromkeys(klass, iterable, value=None):
        "Emulate dict_fromkeys() in Objects/dictobject.c"
        d = klass()
        for key in iterable:
            d[key] = value
        return d
    fromkeys = classmethod(fromkeys)

print(Dict.fromkeys('abracadabra'))
# {'a': None, 'r': None, 'b': None, 'c': None, 'd': None}

OUTPUT from the above:

Before: 0
Can't set property from this child
After: 0
==========
Before: 0
After: 42
==========
thing1.property: 1 {'it': 1}
thing2.property: 2 {'it': 2}
{'a': None, 'r': None, 'b': None, 'c': None, 'd': None}

Process finished with exit code 0
_______________________________________________
Edu-sig mailing list
Edu-sig@python.org
https://mail.python.org/mailman/listinfo/edu-sig

Reply via email to