Fw: [翻譯] Google 建議的 Python 風格指南 13
※ [本文轉錄自 Python 看板 #1HYIhEj7 ]
作者: sandwichC (沒回應=掛站) 看板: Python
標題: [翻譯] Google 建議的 Python 風格指南 13
時間: Wed May 8 00:24:43 2013
歡迎大家插隊翻譯,像 t 大那篇就寫得很棒
有時候翻譯的過程發現一些以前沒注意的小細節也蠻有趣的
這次的內容是用 property 讀寫 class 內的變數
對 property 不熟的可以搭配 python doc 閱讀:
http://docs.python.org/2/library/functions.html#property
-------正文開始的分隔線-------
原文網址:http://google-styleguide.googlecode.com/svn/trunk/pyguide.html
屬性 (property)
若需要讀寫類別內的變數時,使用 屬性 (property) 來取代直接的存取及
getter/setter 式的存取。
釋義:
它是 getter/setter 的一個包裝 (wrapper)。使用 a.x 時,雖然看起來像是直接
讀寫,但實際上是透過類似於 a.setX(val) 或 a.getX() 的方式來讀寫,當計算
量不大時適用。
優點:
不需要使用 getter 及 setter,故可讀性增加。計算採用延遲求值的方式 (lazy
calculation)。這是 python 在寫 class 時的慣用法 (編案:較舊版本的 python
不支援此方法)。有時候直接讀寫類別內的變數是合理的,這時使用 getter/setter
的方法顯得繁瑣。若使用屬性則可繞過這個問題,未來也可以在不破壞呼叫方式的
情況下加上讀寫的方法 (method)。
缺點:
使用上,property 宣告的地方在 getter 與 setter 方法之後,因此往往得看到
後面的程式片段才知道前面的方法被用來當作屬性。例外:唯讀的屬性在被創建
的時候就有 @property 的裝飾 (decorator) 了,最後有例子。(編案:較新的
python 多了 setter 和 deleter 的 decorator,所以這已經不是缺點了。)
必須繼承自 object 類別。可能隱藏像是運算子重載這類的副作用。繼承時易造
成困惑。
決策:
在新的程式中用 property 來取代直接讀寫或 getter/setter 式的讀寫。唯讀的
property 在創建時加上 @property 裝飾。
(編案:較新的版本的 python 可直接用 @property, @x.setter, @x.deleter
來取代 x = property(getx, setx, delx, "docstring contents"))
繼承時,若子類別沒覆載 (override) property,則繼承關係很模糊。
因此,應確認讀寫的方法被間接地呼叫,以確保子類別中被重載的方法有被
property 呼叫。(使用 template method 設計模式)
(編案:若子類別連 property 一起覆載,則不一定需要用 template method 設
計模式間接呼叫讀寫的方法。)
Yes:
import math
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
編案:以下的例子可以幫助理解為何有子類別時要使用間接呼叫
(1) 不使用間接呼叫
class Foo(object):
def _get_var(self):
return 10
var = property(_get_var)
class Bar(Foo):
def _get_var(self):
return 20
bar = Bar()
print bar.var
輸出:10
(2) 使用間接呼叫
class Foo(object):
def _get_var(self):
return 10
def __get_var(self):
return self._get_var()
var = property(__get_var)
class Bar(Foo):
def _get_var(self):
return 20
bar = Bar()
print bar.var
輸出:20
(3) 子函式也用 property
class Foo(object):
def _get_var(self):
return 10
var = property(_get_var)
class Bar(Foo):
def _get_var(self):
return 20
var = property(_get_var)
bar = Bar()
print bar.var
輸出:20
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 75.102.68.185
※ 發信站: 批踢踢實業坊(ptt.cc)
※ 轉錄者: sandwichC (75.102.68.185), 時間: 05/08/2013 00:26:24
Translate-CS 近期熱門文章
PTT數位生活區 即時熱門文章