是否存在关于在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 :(得分:5)
“private”的前缀是单个下划线。
__
用于破坏名称并避免一些问题,例如何时使用多重继承。
我个人从未使用它。
无论如何,成员仍然可以公开访问;这只是一个惯例。
答案 1 :(得分:3)
我认为除非你有特别的理由不让成员公开,否则更多Pythonic,因为Python代码通常不打算限制用户超出必要的范围。这就是为什么,例如,没有真正的私人成员。
答案 2 :(得分:2)
考虑选择公开或私人作为文档。它显示了您对成员范围的意图,并向其他开发人员发出警告,告知其未来可能会发生变化。
答案 3 :(得分: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):
,所以我正在使用新式类。新式课程更加本土化,并且有一些旧式课程没有的功能。
答案 4 :(得分:1)
“这取决于。”
严重。如果Node
需要在添加子项时执行某些操作,那么您需要先了解更改并执行需要完成的操作。如果它只是一个您不需要担心变化的列表,那么请使用后者。
答案 5 :(得分:0)
正如你所说,这取决于。通常我更喜欢有一种与类交互的方法,以便在编程逻辑和它的实现之间进行分离。按照您发布的示例,我将写下:
class Node:
def __init__(self):
self.childs = []
def add_childs(self, *args):
self.childs += args
因为如果一个子类可以访问childs
,那么它可以没有任何奇怪的varname。
通常我只使用属性的私有成员来创建计算值的缓存。
答案 6 :(得分:0)
约定是使用单个下划线作为前缀,但它纯粹是建议性的,并且仍然可以像访问任何其他属性一样访问该属性。在编写单元测试时有时很方便
双下划线前缀调用名称重整。您可能会觉得该属性是私有的,但您可以像这样访问它。
>>> node=Node()
>>> node._Node__children
[]