Created
April 9, 2019 03:41
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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