min*_*rus 5 python properties decorator google-style-guide python-decorators
我很好奇Google Python样式指南中有关属性的建议之一.
在其中,他们给出了以下示例:
class Square(object):
"""A square with two properties: a writable area and a read-only perimeter.
To use:
>>> sq = Square(3)
>>> sq.area
9
>>> sq.perimeter
12
>>> sq.area = 16
>>> sq.side
4
>>> sq.perimeter
16
"""
def __init__(self, side):
self.side = side
def __get_area(self):
"""Calculates the 'area' property."""
return self.side ** 2
def ___get_area(self):
"""Indirect accessor for 'area' property."""
return self.__get_area()
def __set_area(self, area):
"""Sets the 'area' property."""
self.side = math.sqrt(area)
def ___set_area(self, area):
"""Indirect setter for 'area' property."""
self.__set_area(area)
area = property(___get_area, ___set_area,
doc="""Gets or sets the area of the square.""")
@property
def perimeter(self):
return self.side * 4
Run Code Online (Sandbox Code Playgroud)
我有两个问题:
什么是使用三个下划线"间接"的利益___get_area和___set_area以及两个下划线的,只是用两个直接强调那些了吗?
为什么使用property()这组双重和三重下划线方法作为方法,而不是做类似的事情:
@property
def area(self):
return self.side ** 2
@area.setter
def area(self, value):
self.side = math.sqrt(value)
Run Code Online (Sandbox Code Playgroud)Mar*_*ers 12
在风格指南中,他们给出了一个理由:
如果不覆盖属性本身,则具有属性的继承可能不明显.因此,必须确保间接调用访问器方法以确保属性调用子类中重写的方法(使用模板方法DP).
(其中模板方法DP是模板方法设计模式(Alex Martelli的幻灯片,Google的Pythonista extraordinaire).
因此,他们希望为子类提供覆盖实现的机会,并给出property三重下划线版本来调用双下划线方法,以便您可以覆盖它们.在这种情况下,您必须拼写出受损的名称:
class WonkySquare(Square):
def _Square__get_area(self):
return self.square ** 2 + 0.5
Run Code Online (Sandbox Code Playgroud)
显然,提出这个方案的人从来不知道你可以只覆盖一个属性的getter或setter,看看Python覆盖getter而没有setter:
class ProperlySubclassedSquare(Square):
@Square.area.getter
def area(self):
return self.square ** 2 + (0.5 - 0.5)
Run Code Online (Sandbox Code Playgroud)
话又说回来,getter,setter和deleter装饰属性在Python 2.6只添加.样式指南必须是为较旧的Python版本编写的.
对于2.6及更高版本,请坚持使用该@propname.setter模式.