tags:

views:

127

answers:

4

In Python, which is the best way (style wise) to allow public access to an object's variables?

There are lots of options I've seen from different languages, I was wondering which of these (if any) is the preferred Python method? These are the options I'm currently torn between:

  1. Allow direct access to object variables (e.g. print(object.variable)), ignore data hiding
  2. Allow access to object variables by a wrapper function:

class X:
    variable_a = 0
    variable_b = 0
...
    def get_variable_a(self):
        return self.variable_a

If this is the recommended way, how do you name the methods? (get_variablename(), or just variablename etc?)

What does everyone recommend for this?

thanks!

Lucy

+4  A: 

Don't bother using accessors until they're necessary; converting a simple attribute to a property is quick and easy, and doesn't need modification of client code.

When I write a property, I use _get_FOO() and _set_FOO() for the accessors, and _FOO for the attribute itself.

Ignacio Vazquez-Abrams
@Ingacio, do you really use a leading underscore for properties which you intend to access from outside the class/instance? That goes against a strong Python convention, where `_foo` says "not public!" Or was the underscore in `_FOO` just a typo?
Peter Hansen
@Peter: The *property* is called `FOO`. The *store* is called `_FOO`.
Ignacio Vazquez-Abrams
@Ignacio: Ah, of course... duh. :)
Peter Hansen
+2  A: 

Just allow direct access to any variables that you wish to expose as the public API. If you need to change the behavior you can always turn it into a property later on.

Notice that this is orthogonal to information hiding. obj.get_some_implementation_detail() is no better than obj.some_implementation_detail.

Ants Aasma
+3  A: 

There are no "private" variables in Python. Check section 9.6 of this document http://docs.python.org/tutorial/classes.html

There is a convention though, that the users of the class should treat variables with names, starting with underscore to be not touched directly. Still, there is no mechanism which may prevent this.

Same with the mangled names (starting with 2 underscores).

Sunny
A: 

You can use

Getters and setters (Java like)

class SomeClass(object):
  ...

  def get_x(self):
    return self._x
  def set_x(self, x):
    self._x = x

c = SomeClass()
print c.get_x()
c.set_x(10)

Properties (C# like)

class SomeClass(object):
  ...

  def get_x(self):
    return self._x
  def set_x(self, x):
    self._x = x
  x = property(get_x, set_x)

c = SomeClass()
print c.x
c.x = 10

I think it is merely a matter of style. Choose the one you like better. Same applies to the naming convention, choose one convention and stick to it.

In any case, data hiding can be done with pseudo-private variables (beginning with two underscores). They cannot be accessed directly, as opposed to the example variables (_x not starting with two underscores).

AndiDog
Actually - they can. Just with a different name, which includes the class name. The name of the variable is mangled, not its access level. From the same document you refer: "Note that the mangling rules are designed mostly to avoid accidents; it still is possible to access or modify a variable that is considered private."
Sunny
"“Private” instance variables that cannot be accessed except from inside an object, don’t exist in Python." (from the page you linked to)
Devin Jeanpierre
You can use getters and setters, but Python has an entire mechanism to save you having to deal with them. Protection is built in. See "Accessors: Why Python Doesn’t Have Them":http://albert.infinitepigeons.org/wp/?p=135
Tom
Why the downvotes? I clearly wrote "cannot be accessed __directly__" which is completely true because with a instance variable "__x" you cannot access "instance.__x" but must use "instance._ClassName__x". It's about how you use such variables - as long as you don't access any variables called `.__something` (and instead use the property `.something`), you're good. Python doesn't enforce it but it should be a convention for every programmer.
AndiDog
My downvote was mainly for "I think it is merely a matter of style.". Python strongly suggests using directly exposed variables or properties rather than explicit getters and setters, and the naming convention is not a matter of taster here either; it is a standard way to denote private variables.
Max Shawabkeh
You are making mistake to compare variable and its name. __x is just the name, not the variable itself. And the variable is accessible directly (just with another name), i.e. in Pyton you can not forbid this. While properties (or setters and getters) are a way to access a variable indirectly. In the languages, where "private" has meaning, one can not access "private" variables directly. You still can use some form of reflection, but it's not part of the language, but part of the framework, in which this language is used (Java, C#, etc., may use reflection trough framework functions).
Sunny
That's exactly what I said - the variable is named differently and thus cannot be accessed directly by the name `__x`. I don't know why you're still trying to correct me...
AndiDog
@AndiDog, you're missing his point still. From his point of view (and many others) there are in effect no variables in Python, just objects and names. The object can be accessed directly... the name is irrelevant, though it's what you're focusing on when you refer to "direct access of the variable". (Just trying to help clarify here... If I had downvoted, it would merely have been because your answer seems to imply strongly that this provides positive protection, when it really only protects against casual/accidental access.)
Peter Hansen