2010-04-29 67 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):,让我使用新式的类。新式课程的工作原理略有一些,而旧式课程则不具备一些功能。