Hi

OK, so I am reading on OOP in Python, and I am an old C/C++ programmer so I have somewhat high expectations :).

My question is regarding private/public variables. Per default, all class data members are public, but if we precede them with a double underscore, they become private.


1) In the following, why can't I access data? It is private, so it should be available to only class methods, which output is:

class Test():
    __data = 1

    def output(self):
        print Test.data

ins = Test()
ins.output()

2) The following is OK, i.e. I can't access the data member from outside the class:

class Test():
    __data = 1

    def output(self):
        print Test.data

ins = Test()
print ins.data

3) In the following, why can I access the private member data from the outside?

class Test():
    __data = 1

    def output(self):
        print Test.data

Test.data = 2

Any help is appreciated.

Best,
Niles.

Edited 5 Years Ago by Niles64: n/a

data is different variable than __data.

class Test():
    __data = 1

    def output(self):
        print self.__data

    def set_data(self, value):
        self.__data = value

# set public class variable for class Test
Test.data = 3
my_test = Test()
my_test.data = 2
print 'Class data changed for instance my_test', my_test.data
my_test.output()

my_test.set_data(5)
my_test.output()

your_test = Test()
print('Original __data')
your_test.output()
your_test.set_data(9)
# my_test did not change
print('my_test.__data')
my_test.output()
print('your_test.__data')
your_test.output()

his_test = Test()
# new instance start value did not change,
# as it was set by class definition to 1
print 'Initial __data'
his_test.output()

Test.data = 5
# Test.data definition added data variable with value 5 to all new instances
print 'Class Test data for his_test:', his_test.data
print 'Value of Test.data:', Test.data

EDIT: class variable change example

Edited 5 Years Ago by pyTony: n/a

Actually also your_test.data changes at the end of previous test code, only my_test has instance variable called data which shadows the class variable. Some more lines from line 36:

Test.data = 5
# Test.data definition added data variable with value 5 to all new instances
# but also the instances, which did not set it themself (making it instance variable)
print 'Class Test data for his_test.data:', his_test.data
print 'Value of Test.data:', Test.data
print "My_test's data is instance variable: my_test.data:", my_test.data
print 'your_test.data:', your_test.data
print 'Removing instance variable data from my_test'
del my_test.data
print 'Unshadowed my_test class variable is also changed:', my_test.data

And line 16 should say:

print 'Instance variable data shadowing the class data for instance my_test', my_test.data

Edited 5 Years Ago by pyTony: n/a

Thanks. Your example brings a question to my mind:

class Test():
    data = 1

    def output(self):
        print Test.data

    def set_data(self, value):
        Test.data = value

Test.data = 3 #changed class variable for all existing and future instances

my_test = Test()
my_test.output()

my_test.data = 2 #now I create an object variable called data

print 'Class data changed for instance my_test', my_test.data

my_test.output() #output still prints class variable

Isn't the above example very "non-Pythonic" in the sense that we now have a class variable called data for all existing and future instances of the class Test *except* the instance my_test, for which my_test.data is 2, *but* my_test's methods still refer to the class variable.

I mean, it seems like Python is built around the concept of simplicity, but yet we still have the opportunity to potentially shoot ourselves in the foot like this. What is up with that?

you are not using instances class variable self.data but the class variable Test.data. If you want per instance variables you should create them in classes' __init__ method. This is the main idiomatic way.

you are not using instances class variable self.data but the class variable Test.data. If you want per instance variables you should create them in classes' __init__ method. This is the main idiomatic way.

I agree, but don't you agree that the construction I made in my previous post is an example showing that Python is not "idiot proof"? (I know this is a bad term to use when talking about programming, but ...)?

program can only do what you ask it to do. 'implicit' is spirit of Python as expressed in 'import this' To ask program to do correct thing you need to know what you want. Then you must know how to express it correctly with the language.

This question has already been answered. Start a new discussion instead.