5

不確定Python的約定類型暗示的實例變量 - 我一直在__init__構造函數的參數內做他們喜歡在這裏看到:類型提示公約實例變量的Python

class LoggedVar(Generic[T]): 
    def __init__(self, value: T, name: str, logger: Logger) -> None: 
     self.name = name 
     self.logger = logger 
     self.value = value` 

鏈接,上面的代碼片段:https://docs.python.org/3/library/typing.html#user-defined-generic-types

但我也看到註釋實例變量的__init__參數內的PEP約定等(以下片段),然後還做類型提示:

class BasicStarship: 
    captain: str = 'Picard'    # instance variable with default 
    damage: int       # instance variable without default 
    stats: ClassVar[Dict[str, int]] = {} # class variable` 

    def __init__(self, damage: int, captain: str = None): 
     self.damage = damage 
     if captain: 
      self.captain = captain # Else keep the default 

最後,後來就PEP526文章中,他們說可以做的方便和約定如下:

class Box(Generic[T]): 
    def __init__(self, content): 
     self.content: T = content 

網址兩個上面的代碼片段: https://www.python.org/dev/peps/pep-0526/#class-and-instance-variable-annotations

那麼,這些公約之一比我應該嘗試堅持的其他更好/更廣泛接受(更好的可讀性等)?

+0

直到現在我還沒有意識到PEP 526;謝謝。 – chepner

+0

爲什麼在第二個例子中是'captain'和'damage'實例變量?他們也不是類變量嗎?或者事實是,它們在init方法中被改變,使它們成爲實例變量?如果我有一個列表,並用'list.append()'改變它,那麼所有實例都會共享這個改變,所以它仍然是一個類變量。 – Asara

回答

1

對於大多數情況,我會推薦使用第一個版本,其中將類型分配給__init__方法的參數。

該特定方法的冗餘度最小,同時仍允許類型檢查程序驗證您是否在代碼中的其他地方正確調用了該方法__init__

我會建議使用第二個或第三個版本,在那裏你明確註釋的字段(內部或外部__init__)當你__init__方法已發展足夠複雜到這個地步的一個或多個以下應用:

  1. 它不再那麼簡單,究竟你們的田地,開始與
  2. 現在,已經沒有你的參數和你的域之間的一個一對一的映射
  3. 您有掩蓋了怎樣的田地,在複雜的初始化邏輯分配。

但是,我還不清楚第二個還是第三個版本是首選 - 我個人比較喜歡第三個版本,因爲它在概念上更清潔,似乎沒有混合實例和類屬性的概念,但我不能否認第二個版本看起來更乾淨。

我在'打字'gitter頻道上詢問了這個問題,並得到了Guido的回覆(誰是你不知道的機會製作了Python並且目前正在開發mypy並打字相關的東西) :

無論哪種方式似乎都有強烈的意見。我確實更喜歡將屬性註釋放在類體中,而不是將它們灑在整個__init__和其他方法中。我還認爲,使用PEP 526這將是未來(也可以使用基於類的NamedTuple聲明和可能的https://github.com/ericvsmith/dataclasses)。

link to quote

所以,好像建議在第三的第二個版本,並在該方式定義類將更加深入地集成到Python語言本身在未來的某一時刻!

編輯:PEP 557, data classesrecently accepted並且似乎在軌道(?)將包含在Python 3.7中。

1

我會堅持你在LoggedVar中做的事情,它遵循與Python中其他任何地方相同的規則,所以不會陷入混亂。

BasicStarShip類通過將它們移出__init__函數來更改變量的範圍。隨着隊長宣佈BasicStarShip.captain將返回'皮卡爾'。

PEP526註釋很好閱讀,但它是一個特定情況下的新規則,即__init__函數。來自Python的禪宗「特殊情況不足以打破規則。」