2010-04-29 69 views
2

是否有關於在Python類中暴露成員的常規約定?我知道這是一個「取決於」的情況,但也許有一條經驗法則。暴露成員或使它們在Python中是私有的?

私有成員:

class Node: 

    def __init__(self): 
    self.__children = [] 

    def add_children(self, *args): 
    self.__children += args 

node = Node() 
node.add_children("one", "two") 

公共成員:

class Node2: 

    def __init__(self): 
    self.children = [] 

node2 = Node2() 
node2.children += "one", "two" 

如果沒有很好的理由讓children私人,你會留在法add_children

+0

1)它取決於2)孩子 - >孩子。 – Stephen 2010-04-29 14:38:04

+0

uups!糾正了複數 – deamon 2010-04-29 14:40:08

回答

1

「這取決於」。

說真的。如果Node需要在添加子項時執行某些操作,那麼您首先需要抓住更改並執行需要完成的任務。如果這只是一個你不需要擔心變化的列表,那就去後者。

5

「private」的前綴是單個下劃線。 __用於改變名稱並避免一些問題,例如當使用多重繼承時。 Personnally我從來沒有用過它。

無論如何,會員仍然可以公開訪問;這只是一個慣例。

3

我相信,除非您有特定的理由,否則基於Python代碼通常不打算限制用戶超出必要的範圍,會讓成員暴露更爲Pythonic。例如,這就是爲什麼沒有真正的私人會員這樣的事情。

2

想想如何選擇公開或私人的文件。它顯示了您對成員範圍的意圖,並向其他開發者發出警告,表明它可能在未來發生變化。

0

正如你所說,這取決於。通常我更喜歡有一種方法與類進行交互,以獲得編程邏輯與實現之間的分離。下面,您張貼的例子,我會說:

class Node: 

    def __init__(self): 
     self.childs = [] 

    def add_childs(self, *args): 
     self.childs += args 

,因爲如果一個子類將訪問childs可以毫不奇怪VARNAME。 通常我只使用屬性的私有成員來創建一個計算值的緩存。

0

約定是以一個下劃線作爲前綴,但它純粹是建議性的,並且仍然可以像訪問其他屬性一樣訪問該屬性。方便有時在編寫單元測試時

雙下劃線前綴調用名稱修改。您可能會覺得該屬性是私人的,但您可以像這樣訪問它。

>>> node=Node() 
>>> node._Node__children 
[] 
2
  • 答案是,當然, 「這取決於」。如果我猜測,我會使用add_children方法。一個類的重點通常是將你正在做的事情從你存儲的狀態表示中抽象出來。 my_node.add_children(a, b)是一種操作,我將其理解爲「將a和b添加到我的模式中」。 my_node.children.extend([a, b])使用戶將children視爲一個列表,並在實例內部向下進行變異。有時,但不太常見,你想要什麼。如果您最終需要添加子項來做額外的事情,那麼也很難不更改API。

  • __foo屬性不是私有的。 Python名稱 - 以一種系統的,易於重現的方式將它們篡改。 Python不支持真正的私有屬性。使用__foo不會增加隱私,但它確實會讓您的班級更難測試,繼承和使用。

    當我有一個屬性,我不希望作爲公共API的一部分,我用一個下劃線作爲它的前綴,例如, _foo。這個慣例被廣泛使用。

  • 我從來沒有使用+=列表;我使用extend方法。我不喜歡+=,因爲大多數人使用extend,因爲它的操作有點混亂。 a += b有兩種不同於a = a + b的方式:前者改變原始列表,後者創建新列表並重新將其重新命名爲原始名稱,後者b必須是列表,而前者b可能是任意可迭代的。我發現extend更清潔。

  • 我始終繼承object,而不是什麼都沒有,即class Node(object):,讓我使用新式的類。新式課程的工作原理略有一些,而舊式課程則不具備一些功能。