Descriptor

In general, a descriptor is an object attribute with “binding behavior”, one whose attribute access has been overridden by methods in the descriptor protocol. Those methods are __get__()__set__(), and __delete__(). If any of those methods are defined for an object, it is said to be a descriptor.  from https://docs.python.org/2/howto/descriptor.html

When you want to access/view an attribute of an object,  you can just type .__dict__ to check what is stored there. They are all saved in Dictionary format !


class guo(object):
    print("nothing to say")

class Circle(guo):
    pi = 3.1415926
    def __init__ (self, radius):
        self.radius = radius
        self.circum = 2*self.pi*radius

my = Circle(3)
type(my).mro()  # [<class '__main__.Circle'>, <class '__main__.guo'>, <class 'object'>]

But the problem is if we set the new value(here, "radius") to the class object, other attributes is not updated!

my.radius
Out[6]: 3
my.circum
Out[7]: 18.849555600000002

###################
# new value
my.radius = 2
my.circum
Out[9]: 18.849555600000002  ## it is wrong !


Solution :

class Circle(guo):
    pi = 3.1415926
    def __init__ (self, radius):
        self.radius = radius
    @property
    def circum(self):
         return 2*self.pi*radius

Now run it again!

my = Circle(3)   
print(my.circum)  # 18.849555600000002


my.radius = 2print(my.circum)  # 12.5663704

Yes, it is right now !!

Find a good example to implement the descriptor :
# https://www.smallsurething.com/python-descriptors-made-simple/

from weakref import WeakKeyDictionary

class Price(object):
    def __init__(self):
        self.default = 0        self.values = WeakKeyDictionary()

    def __get__(self, instance, owner):
        return self.values.get(instance, self.default)

    def __set__(self, instance, value):
        if value < 0 or value > 100:
            raise ValueError("Price must be between 0 and 100.")
        self.values[instance] = value

    def __delete__(self, instance):
        del self.values[instance]



class Book(object):
    price = Price()

    def __init__(self, author, title, price):
        self.author = author
        self.title = title
        self.price = price

    def __str__(self):
        return "{0} - {1}".format(self.author, self.title)

b = Book("William Faulkner", "The Sound and the Fury", 12)
b.price  # 12b.price = -12b.price = 101



留言

這個網誌中的熱門文章

AndrewNg's CNN notes(practical issues)

New findings in Numpy