Exposing members or closing them in Python?

Is there a general convention for exposing members in Python classes? I know this is a "it depends" case, but maybe there is a rule of thumb.

Private member:

class Node:

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

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

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

      

Public participant:

class Node2:

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

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

      

If there's no good reason to make it children

private, are you left with the method add_children

?

+2


a source to share


7 replies


"It depends".



Seriously. If Node

something needs to be done when children are added, you want the first one to catch the change and do what needs to be done. If it's just a list that you don't need to worry about changing, skip to the last one.

+1


a source


The prefix for "private" is the only underscore character. __

used to swear a name and prevent some problems, for example. when using multiple inheritance. Personally, I have never used it.



In any case, the members will still be public; it's just a convention.

+5


a source


I believe that more Pythonic leaves contributors, unless you have a specific reason, based on the fact that the Python code does not intend to restrict the user any more than is necessary at all. This is why, for example, there is no such thing as a truly private member.

+3


a source


Think about how to do something public or private as documentation. It shows your intentions for a member's reach and serves as a warning to other developers that it may change in the future.

+2


a source


  • The answer, of course, is "it depends." If I was assuming I would use the method add_children

    . A class point usually abstracts what you are doing, from the representation of the state that you are storing. my_node.add_children(a, b)

    is the operation I would read as "add children a and b to my mode". my_node.children.extend([a, b])

    forces the user to think of it children

    as a list and delete inside the instance to mutate it. It is sometimes, but less often, what you want. It also makes it difficult to change the API if you end up needing to add children to do something extra.

  • __foo

    attributes are not private. Python Name - Manages them in a systematic, easily reproducible way. Python does not support real private attributes. Using __foo

    doesn't add privacy, but it makes your class harder to test, inherit, and use.

    When I have an attribute that I don't want as part of my public API, I prefix it with a single underscore, eg. _foo

    ... This convention is widely used.

  • I never use it +=

    with lists; I use the method instead extend

    . I don't like +=

    it because most people use it extend

    and because its work is a little confusing. a += b

    differs from in a = a + b

    two ways: the first mutates the original list, and the second creates a new list and reverts it to the original name, and the latter b

    must have a list and the first b

    can be arbitrary iterable. I find a purifier extend

    .

  • I always inherit object

    , not nothing, i.e. class Node(object):

    so I am using new style classes. The new-style classes work in a slightly more natural way and have a few features of the old-style classes.

+2


a source


As you said, it all depends. I usually prefer to have a way to interact with the class in order to get a separation between the programming logic and its implementation. Following the example you posted, I wrote:

class Node:

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

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

      

because if the subclass is going to have access to it childs

, it might be without any weird varname. I usually only use private members with properties to create a cache of the computed value.

0


a source


The convention is intended to be prefixed with a single underscore, however it is purely advisory and is still available to access the attribute like any other. Handy sometimes when you write unit tests

The double underscore prefix invokes the name mangling. You might think the attribute is private, but you can access it like this.

>>> node=Node()
>>> node._Node__children
[]

      

0


a source







All Articles