Click here to Skip to main content
15,888,984 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Simple code in Python2.7 with a "private" data item "items". I hear there is nothing really one can do in Python to declare an attribute truly "private" ... this code manages to change the first elemement of the items list from an instance of Group to a string. Why and how can I stop it / re-code ?? I feel the pain in Python circles when people like me talk about "private" , but stick with me please because I'm trying to protect myself here from doing something I "culturally" shouldnt be doing - i.e. writing to other classes and instances (as quoted here: class - Does Python have “private” variables in classes? - Stack Overflow)

class Groups():
    
  def __init__(self):
    self.__items = []
  
  def add(self, name, hidden=None, position=None):
    if name not in self.__items:
      if position is None:
        print("appending %s" % name)
        self.__items.append(Group(name=name, hidden=hidden, position=position))
      else:
        print("inserting %s" % name)
        self.__items.insert(position, Group(name=name, hidden=hidden, position=position))
      print('after add, len=',len(self.__items))
  
  def list(self):
    print("list():")
    print "".join("   item: "+x.name for x in self.__items)
    return self.__items

g=Groups()
print("adding ITEM")
g.add("ITEM")
g.list()
print("changing..")
g.list()[0]="Changed" 
g.list() Should now raise an exception


The list() method is returning items by reference allowing direct access to the list, rather than passing by-value (i.e. a copy of the items). Further, the name mangling __items seems to be innefectual in that I can still modify the data by using list()[0] =

By the way, what I am trying to do here is abstract the implementation of __list. Today it is a simple Python list, tomorrow I might make it a class, but I want to abstract this in the Groups class.

I just need some education here me thinks.

What I have tried:

nothing - not sure what to do as I am learning Python.
Posted
Updated 22-Jun-18 0:57am
v5

I'm not a Python expert so my thoughts might not be exact.

Your list() function is returning a reference to the private member. Because the function is a member too, it has access to the array. As a result, the calling side "sees" a reference which is it allowed to use and change.

Do you know C++? It is similar there:
C++
class Test {
public:
    Test(int a = 0) { m_a = a; }
    int& get() { return m_a; }
private:
    int m_a;
};

int main()
{
    Test test(1);
    // Allowed because get() returns a reference
    test.get() = 2;
    // This will print 2
    printf("%d\n", test.get());
    
    return 0;
}

The solution is to not return the list at all or return a copy of the list (see Programming FAQ — Python 3.6.6rc1 documentation: How do I copy an object in Python?[^] ):
Python
# Using slicing
return self.__items[:]
# Return a new list
return list(self.__items)
# Using copy.copy() or copy.deepcopy()
return copy.deepcopy(self.__items)

[EDIT]
The best solution would be returning a read only reference like with the C++ const keyword. But Python does (and will) not support such due to its design and ideology.

With Python, the caller of such functions is responsible for not doing something "wrong" with the returned references. Such should be stated clearly in the documentation for the function.
[/EDIT]
 
Share this answer
 
v2
Comments
ninjaef 22-Jun-18 8:26am    
yes, understand C++
thanks for the example
got it now...simple now you explained it that way.
yes, ive heard of python duckduck principles and use-me-dont-abuse me ideology.

EDIT
sorry, my phone hit 4star instead of 5. meant to give you 5*. sorry
See 9. Classes — Python 3.4.8 documentation: Private Variables[^]. I suggest going to the first page of that tutorial, and working your way through it; a really useful tutorial.
 
Share this answer
 
Comments
ninjaef 22-Jun-18 6:21am    
Naturall I am reading python documentation, including the section on classes, I felt that was obvious otherwise how would I learn Python - links to a documentation are not really helpful in this instance, I was hoping for an explanation rather than a link to the language docs. Specifically, why is list()[0] allowed to change the "private" __items data ?? I clearly do not understand what is going on despite reading the documentation !
Richard MacCutchan 22-Jun-18 9:25am    
“Private” instance variables that cannot be accessed except from inside an object don’t exist in Python. I do not think that statement could be any clearer.

"Why is list()[0] allowed to change the "private" __items data ?"
Because, as clearly expalined in the documentation, there is no such thing as 'private' in Python.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900