美文网首页python高级编程知识点收录
python中Properties的一些小用法

python中Properties的一些小用法

作者: 老马的春天 | 来源:发表于2018-03-30 17:35 被阅读14次

    property最大的用处就是可以为一个属性制定getter,setter,delete和doc,他的函数原型为:

        def __init__(self, fget=None, fset=None, fdel=None, doc=None): # known special case of property.__init__
            """
            property(fget=None, fset=None, fdel=None, doc=None) -> property attribute
            
            fget is a function to be used for getting an attribute value, and likewise
            fset is a function for setting, and fdel a function for del'ing, an
            attribute.  Typical use is to define a managed attribute x:
            
            class C(object):
                def getx(self): return self._x
                def setx(self, value): self._x = value
                def delx(self): del self._x
                x = property(getx, setx, delx, "I'm the 'x' property.")
            
            Decorators make defining new properties or modifying existing ones easy:
            
            class C(object):
                @property
                def x(self):
                    "I am the 'x' property."
                    return self._x
                @x.setter
                def x(self, value):
                    self._x = value
                @x.deleter
                def x(self):
                    del self._x
            
            # (copied from class doc)
            """
            pass
    

    从上边的代码中可以看出来,它一共接受4个参数,我们再继续看一段代码:

    class Rectangle(object):
        def __init__(self, x1, y1, x2, y2):
            self.x1, self.y1 = x1, y1
            self.x2, self.y2 = x2, y2
    
        def _width_get(self):
            return self.x2 - self.x1
    
        def _width_set(self, value):
            self.x2 = self.x1 + value
    
        def _height_get(self):
            return self.y2 - self.y1
    
        def _height_set(self, value):
            self.y2 = self.y1 + value
    
        width = property(_width_get, _width_set, doc="rectangle width measured from left")
        height = property(_height_get, _height_set, doc="rectangle height measured from top")
    
        def __repr__(self):
            return "{}({}, {}, {}, {})".format(self.__class__.__name__,
                                               self.x1,
                                               self.y1,
                                               self.x2,
                                               self.y2)
    
    
    rectangle = Rectangle(10, 10, 30, 15)
    print(rectangle.width, rectangle.height)
    rectangle.width = 50
    print(rectangle)
    rectangle.height = 50
    print(rectangle)
    print(help(rectangle))
    

    通过property,我们有能力创造出一个属性来,然后为这个属性指定一些方法,在这里用setter,getter的好处就是可以监听属性的赋值和获取行为,表面上看上去上边的代码没有问题,但是当出现继承关系的时候,就出问题了。

    class MetricRectangle(Rectangle):
        def _width_get(self):
            return "{} metric".format(self.x2 - self.x1)
    
    
    mr = MetricRectangle(10, 10, 100, 100)
    print(mr.width)
    

    即使我们在子类中重写了getter方法,结果却是无效的,这说明property只对当前的类生效,于是不得不把代码改成下边这样:

    class MetricRectangle(Rectangle):
        def _width_get(self):
            return "{} metric".format(self.x2 - self.x1)
    
        width = property(_width_get, Rectangle.width.fset)
    
    
    mr = MetricRectangle(10, 10, 100, 100)
    print(mr.width)
    
    

    因此,在平时的编程中,如果需要重写属性的话,应该重写该类中所有的property,否则程序很很难以理解,试想一下,setter在子类,getter在父类,多么恐怖

    另一种比较好的方案是使用装饰器,可读性也比较好

    class Rectangle(object):
        def __init__(self, x1, y1, x2, y2):
            self.x1, self.y1 = x1, y1
            self.x2, self.y2 = x2, y2
    
        @property
        def width(self):
            """rectangle width measured from left"""
            return self.x2 - self.x1
    
        @width.setter
        def width(self, value):
            self.x2 = self.x1 + value
    
        @property
        def height(self):
            return self.y2 - self.y1
    
        @height.setter
        def height(self, value):
            self.y2 = self.y1 + value
    
        def __repr__(self):
            return "{}({}, {}, {}, {})".format(self.__class__.__name__,
                                               self.x1,
                                               self.y1,
                                               self.x2,
                                               self.y2)
    
    
    rectangle = Rectangle(10, 10, 30, 15)
    print(rectangle.width, rectangle.height)
    rectangle.width = 50
    print(rectangle)
    rectangle.height = 50
    print(rectangle)
    print(help(rectangle))
    

    相关文章

      网友评论

      本文标题:python中Properties的一些小用法

      本文链接:https://www.haomeiwen.com/subject/rdwicftx.html