Python Forum

Full Version: Inheritance private attributes
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hello guys,

I'm trying to inherit private attributes (self.__attrib), but when I use the parent __init__ method this private attributes doesn't inherit. For example:

class Primary():
	def __init__(self, param1, param2):
		self.param1 = param1
		self.__param2 = param2

	def getP1(self):
		return self.param1

	def getP2(self):
		return self.__param2

class Secondary(Primary):
	def __init__(self, param1, param2, param3):
		Primary.__init__(self, param1, param2)
		self.__param3 = param3

	def getP3(self):
		return self.__param3

	def test(self):
		print (self.__param2)

#Main

p = Primary('a', 'b')
s = Secondary('a', 'b', 'c')

s.test()
When I try to access self.__param2 in Secondary instance, there is an error:
Error:
Traceback (most recent call last): File "class_test.py", line 38, in <module> s.test() File "class_test.py", line 21, in test print (self.__param2) AttributeError: 'Secondary' object has no attribute '_Secondary__param2'
I think in three solutions:
1 - Use public attributes: self.param2 instead of self.__param2. It is not an important problem, but conceptually, the attributes that will not be accessed out of class, must be private. Not?

2- Not reutilize the Primary __init__ constructor. But we are wasting inheritance potencial, not? Like this:

class Secondary(Primary):
	def __init__(self, param1, param2, param3):
		self.param1 = param1
		self.__param2 = param2
		self.__param3 = param3
3- Use parent get() method when I need it (maybe the best solution):
def test(self):
		print (Primary.getP2(self))
Any best solution? Maybe the best is the third option, not?

Thanks a lot Big Grin
class Primary():
    def __init__(self, param1, param2):
        self.param1 = param1
        self.__param2 = param2

    def getP1(self):
        return self.param1

    def getP2(self):
        return self.__param2

class Secondary(Primary):
    def __init__(self, param1, param2, param3):
        Primary.__init__(self, param1, param2)
        self.__param3 = param3

    def getP3(self):
        return self.__param3

    def test(self):
        print (self.getP2())

#Main

p = Primary('a', 'b')
s = Secondary('a', 'b', 'c')

s.test()
Thanks Larz60+

By the way ... I do not see many examples of private attributes in Python. It seems that they get used to using public attributes. I have been years without programming, but in C, C ++ ... as a rule I always used private attributes.

Something similar I find with abstract classes. In Python it is used rather little.

Is there any reason in this regard?

Thanks!
There are no reglementations concerning private attributes. There is only a coding convention (like you used in your code) to mark private attributes but in general they behave like global variables. It's a bit different in python in comparison to C/C++ or Java. Somehow the same goes for abstract classes. There are abstract classes and also I like to program with these since they are a good programming technique. But also those methods only can be marked as abstract and can vary in its given attributes so that a method in a child class only needs the same name. Both concepts exist in python and are used, but they work in a different way than you may know it from other programming languages :)
(May-02-2018, 08:18 PM)vaison Wrote: [ -> ]the attributes that will not be accessed out of class, must be private. Not?
There is nothing private in Python,and getter/setter should not be used.
__ is for name mangling and is not private.
A quick demo of name mangling.
class Foo:
    def __init__(self):
        self.__var = 3 # Not private, it's for name mangling

class Bar(Foo):
    def __init__(self):
        super().__init__()
        self.__var = 3
Test usage:
>>> obj = Bar()
>>> # Both have been given different name(name mangling)
>>> obj._Foo__var
3
>>> obj._Bar__var
3
>>> 
>>> # Change one will not change the other
>>> obj._Foo__var = 100
>>> obj._Foo__var
100
>>> obj._Bar__var
3
Hello,

ok, thanks for the aclarations. I have it much clearer.