Python Forum
when to make attributes private?
Thread Rating:
  • 1 Vote(s) - 3 Average
  • 1
  • 2
  • 3
  • 4
  • 5
when to make attributes private?
#1
I've been working through an introductory python book. I've got quite a bit of experience coding in other languages, but am new to Python. My book seems to have some odd notions about when to make attributes private and suggests all changes to an object's attributes should be done through methods. That sounds pretty tedious to me (creating all the accessors) but I was hoping to get some idea of what the python world things of its advice. The book says:
Quote:Understanding When to Implement Privacy
So now that you know how to use privacy, should you make every attribute in every class private to protect them from the outside world? Well, no. Privacy is like a fine spice: Used sparingly, it can greatly improve what you're making. Make private any method you don't want a client to invoke. If it's critical that an attribute never be accessed directly by a client, you can make it private. But keep this to a minimum, as creating private attributes is rare in Python. The philosophy among programmers is to trust that clients will sue an object's methods and not directly alter its attributes.

When you write a class:
* Create methods so that clients won't need to directly access an object's attributes
* Use privacy only for those attributes and methods that are completely internal to the operation of objects.
*
When you use an object:
* Minimize the direct reading of an object's attributes
* Avoid directly altering an object's attributes
* Never directly access an object's private attributes or methods

I added the italics. Now most of this makes sense but I've never been told not to directly access an object's attributes. Like I said, creating accessors for every attribute seems extremely tedious. I an appreciate concealing the sausage factory of a class with privacy, but this seems a bit strong.

Any comments or documentation welcome.
Reply
#2
Accessing attributes directly is taboo in most programming languages and is archetypal of OOP languages in particular. It's a matter of encapsulation and ensuring that each object works correctly. Directly changing attributes without using the appropriate methods can generate bugs since any given method could update multiple attributes for consistency. The book likely mentions it because Python doesn't enforce privacy; so, respecting privacy is entirely on the programmer.

That said, Pythonistas don't hammer on this too much. Generally, we don't use setters/getters in Python because they aren't needed, whereas other languages require them.

Personally, if an attribute is private, it should either have a setter or only be set at instantiation. In the event it lacks a setter, reading it is okay but don't change it.
Reply
#3
That's rather odd. Getters and setters don't make sense in Python. Since there are no private attributes (such as those in Java), they don't provide any security. Therefore all they can do is slow things down.

I'm not even sure why they are using the term 'private attribute'. If you really need security in Python, as in you need to make sure foo.spam changes every time foo.eggs changes, you use properties.

I do often provide ways for others to not have to access the attributes of the class directly, but I do this to make my classes easier to use. For example, say I have an class that's has a list attribute and some extra tracking attributes. I will override __iter__ so you can just do for knight in round_table: rather than for knight in round_table.knights:.

What is the name of the book you are using?
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#4
(Jan-10-2019, 02:48 AM)stullis Wrote: Accessing attributes directly is taboo in most programming languages and is archetypal of OOP languages in particular.
Perhaps I misunderstand you here, but I've been programming for quite some time in other languages (C++, PHP, Javascript) and have often seen client code directly change the public properties/attributes of classes. I'd hardly say it's taboo. I might be missing something?

(Jan-10-2019, 02:48 AM)stullis Wrote: Directly changing attributes without using the appropriate methods can generate bugs since any given method could update multiple attributes for consistency. The book likely mentions it because Python doesn't enforce privacy; so, respecting privacy is entirely on the programmer.
In my experience, if you don't want someone changing the properties/attributes of an object, you make them private. Conversely, it seem super tedious and unnecessary to create a get & set method when you don't apply any restrictions. This is really the essence of my question. Why create all those trivial get/set functions if you don't have to?

(Jan-10-2019, 02:48 AM)stullis Wrote: That said, Pythonistas don't hammer on this too much. Generally, we don't use setters/getters in Python because they aren't needed, whereas other languages require them.
This is really the answer I was kinda hoping for. Still, I'd like to honor the predominant python culture in any code I write.

(Jan-10-2019, 02:48 AM)stullis Wrote: Personally, if an attribute is private, it should either have a setter or only be set at instantiation. In the event it lacks a setter, reading it is okay but don't change it.
Hear hear!
Reply
#5
(Jan-10-2019, 10:10 PM)sneakyimp Wrote: In my experience, if you don't want someone changing the properties/attributes of an object, you make them private. Conversely, it seem super tedious and unnecessary to create a get & set method when you don't apply any restrictions. This is really the essence of my question. Why create all those trivial get/set functions if you don't have to?
You don't as getters/setters make no sense in Python,if you don't have damn good reason other wise not.
Python Is Not Java say it clear.
Quote:Getters and setters are evil. Evil, evil, I say! Python objects are not Java beans.
Do not write getters and setters. This is what the 'property' built-in is for.
And do not take that to mean that you should write getters and setters, and then wrap them in 'property'.
That means that until you prove that you need anything more than a simple attribute access, don't write getters and setters.
They are a waste of CPU time, but more important, they are a waste of programmer time.
Not just for the people writing the code and tests, but for the people who have to read and understand them as well.
Reply
#6
  • +1 for not writing getters and setters.
  • Use properties if you need them.
  • Create attributes with a single leading underscore such as _spam to indicate that code exploiting your library should not use this attribute directly.
I almost never use the double underscore privacy mechanism such as __eggs, but some python programmers use it now and then.
Reply
#7
(Jan-11-2019, 10:37 AM)Gribouillis Wrote: I almost never use the double underscore privacy mechanism such as __eggs
The wording privacy mechanism is maybe not best description for the double underscore,as it a has "little" or nothing to do with privacy.
It's really to avoid naming conflicts in subclasses,also called name mangling.

To take quick tour of _ and __.
private and public variables like Java does,dos not translate directly over to Python.

Single _
class Bar:
    def __init__(self):
        self.external = 99
        self._internal = 50
Use:
>>> obj = Bar()
>>> 
>>> # get
>>> obj._internal
50
>>> # set
>>> obj._internal = 444
>>> obj._internal
444
Have full access to the attribute value of that variable even it with _.
_ just as Waring hint merely an agreed upon convention.
Quote:Hey, this isn’t really meant to be a part of the public interface of this class.
Best to leave it alone.
Quote:Nothing is really private in python.
After all, we're all consenting adults here.

Double __
class Foo:
    def __init__(self):
        self.var_1 = 'hello'
        self.__var_2 = 'egg' # Not private,it's for name mangling when subclass

class Bar(Foo):
    def __init__(self):
        super().__init__()
        self.var_1 = 'world'
        self.__var_2 = 'spam'
Use:
>>> obj = Bar()
>>> 
>>> obj.var_1
'world'
>>> # var_1 "hello" is overridden and can never be restored
>>> 
>>> obj._Foo__var_2
'egg'
>>> obj._Bar__var_2
'spam'
>>> # var_2 can not be overridden in subclass,because of name mangling so both "egg" and "spam" can be reached
So i guess we could say that we private copy of original egg,but it still is possible to access or modify a variable that we call private copy Hand
Reply
#8
Quote:The wording privacy mechanism is maybe not best description for the double underscore,as it a has "little" or nothing to do with privacy.
Functionaly speaking it is related to privacy in C++ because in C++, private members can't be accessed by the subclasses. In python, it is an attempt to hide the member from the subclasses. The python tutorial uses the term 'private variables'.
Reply
#9
(Jan-11-2019, 06:32 PM)Gribouillis Wrote: it is an attempt to hide the member from the subclasses. The python tutorial uses the term 'private variables'.
Yes i know,but don't like the use of term 'private variables' in doc,i think it can lead to some misunderstanding.

I think Raymond Hettinger say okay in tutorial.
Raymond Hettinger Wrote:People will mistakenly reference this to make thing private in Python
The intention of double underscore was not about privacy
Reply
#10
If you're not doing any extra work with the setter/getter, then making the methods is... a waste of your time? If you want it publicly available, let it be publicly available.

If you DO have extra work to do (such as using validation to make sure the value it's being set to makes sense), then the @property decorator is pretty awesome: https://docs.python.org/3/library/functi...l#property
>>> class spam:
...   def __init__(self, val):
...     self.foo = val
...   @property
...   def foo(self):
...     return self.__foo
...   @foo.setter
...   def foo(self, val):
...     if not isinstance(val, int):
...       raise Exception("Slow down there, cowboy.")
...     self.__foo = val
...
>>> x = spam(5)
>>> x.foo
5
>>> x.foo = 7
>>> x.foo
7
>>> x.foo = "bar"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 10, in foo
Exception: Slow down there, cowboy.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Lint and private var names PatM 1 655 Dec-15-2022, 05:08 PM
Last Post: deanhystad
  Unable to import Private Repo using setup.py Bob786 1 1,705 Sep-02-2021, 04:19 PM
Last Post: snippsat
  python 3 dns lookup private domain didact 1 2,501 Sep-19-2020, 06:01 PM
Last Post: bowlofred
  [split] Помощь по приватным ключам/Private key help sairam17519 0 1,578 Sep-07-2020, 12:55 PM
Last Post: sairam17519
  Download file from Private GitHub rep vinuvt 0 1,930 Jul-27-2020, 11:38 AM
Last Post: vinuvt
  Private package distribution abomination disadvantages research andreir 2 2,116 May-07-2020, 12:32 AM
Last Post: andreir
  Помощь по приватным ключам/Private key help vlrubl777 5 5,804 Mar-15-2019, 08:16 PM
Last Post: vlrubl777
  Fetching private ip address from instances of an autoscaling group deepsonune 0 3,243 May-18-2018, 10:32 AM
Last Post: deepsonune
  Inheritance private attributes vaison 5 12,612 May-03-2018, 09:22 AM
Last Post: vaison
  Can access class private variable? Michael 2 7,141 Aug-11-2017, 01:59 PM
Last Post: snippsat

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020