Skip to content

Instantly share code, notes, and snippets.

@IvanaGyro
Created April 9, 2019 03:41
Show Gist options
  • Save IvanaGyro/6d2d6d404989600cde35d947a714d824 to your computer and use it in GitHub Desktop.
Save IvanaGyro/6d2d6d404989600cde35d947a714d824 to your computer and use it in GitHub Desktop.
Demo the behaviors of Python's descriptor which is implemented with __set__ and __get__ and demo the relations between instance methods and class functions.
import inspect
descriptor_records = []
class Descriptor(object):
def __init__(self, value=None):
self.value = value
def __get__(self, instance, owner): # owner == instance.__class__
descriptor_records.append(('get', instance, owner))
return self.value
def __set__(self, instance, value):
descriptor_records.append(('set', instance, value))
self.value = value
class Teddy:
age = Descriptor(0)
def __init__(self):
self.tall = Descriptor(100)
teddy1 = Teddy()
teddy2 = Teddy()
assert 'tall' in teddy1.__dict__
assert 'age' not in teddy1.__dict__
assert 'age' in Teddy.__dict__
# instances share the same class property
teddy1.age = 10
assert descriptor_records.pop() == ('set', teddy1, 10)
assert teddy1.age == 10
assert descriptor_records.pop() == ('get', teddy1, Teddy)
assert teddy2.age == 10
assert descriptor_records.pop() == ('get', teddy2, Teddy)
# assign a descriptor to an instance is invalid
assert type(teddy1.tall) == Descriptor
# access __dict__ cannot invoke the descriptor
assert type(Teddy.__dict__['age']) == Descriptor
assert len(descriptor_records) == 0
d1 = Descriptor()
d2 = Descriptor()
# instance method are the same obeject, but not equal
assert d1.__set__ != d2.__set__
assert id(d1.__set__) == id(d2.__set__)
# instance method is "method", class method is "function"
assert inspect.ismethod(d1.__set__)
assert not inspect.isfunction(d1.__set__)
assert not inspect.ismethod(Descriptor.__set__)
assert inspect.isfunction(Descriptor.__set__)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment