python中Properties的一些小用法

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

正如您从上面的代码中看到的,它总共接受四个参数,所以让我们转到一段代码:

[En]

As you can see from the above code, it accepts a total of four parameters, so let’s move on to a piece of code:

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的好处是可以监听属性的赋值和获取行为。从表面上看,上面的代码没有问题,但当有继承关系时就有问题了。

[En]

Through property, we have the ability to create an attribute and then specify some methods for it. * the advantage of using setter,getter here is that you can listen to the assignment and acquisition behavior of the attribute * . On the surface, there is no problem with the above code, but there is a problem when there is an inheritance relationship.

class MetricRectangle(Rectangle):
    def _width_get(self):
        return "{} metric".format(self.x2 - self.x1)

mr = MetricRectangle(10, 10, 100, 100)
print(mr.width)

即使我们重写子类中的getter方法,结果也是无效的,这意味着该属性只适用于当前类,因此我们必须将代码更改为如下所示:

[En]

Even if we override the getter method in the subclass, the result is invalid, which means that property only works for the current class, so we have to change the code to look like this:

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在父类,多么恐怖

另一个更好的解决方案是使用装饰器,它也更具可读性。

[En]

Another better solution is to use a decorator, which is also more readable.

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))

Original: https://www.cnblogs.com/machao/p/8677591.html
Author: 马在路上
Title: python中Properties的一些小用法

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/6664/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

最近整理资源【免费获取】:   👉 程序员最新必读书单  | 👏 互联网各方向面试题下载 | ✌️计算机核心资源汇总