0

I have a class a defined like this:

class a: def __init__(self, w, x, y, z): self.w = w self.x = x self.y = y self.__z = z 

I also have another class b which inherits a defined like this:

class b(a): def __init__(self, w, x, y, z, t): super().__init__(w, x, y, z) self.__t = t 

Now if I had access w, x, y from within b, I could simply do:

self.w self.x self.y 

But I can't do self.z or self.__z to access z. So my question is how can you access dunder values such as z from within class b

(I know python doesn't really have private variables and I could do self._a__z from within class b to access z but I'm looking for methods which would allow me to just do something like self.z to access z from inside b)

3
  • 4
    The whole point of making it private is to make that difficult. _a__z is the only way to do it. Commented Mar 19, 2021 at 1:49
  • 4
    The whole point of using double-underscore name-manglinbg is to prevent name collisions in subclasses. If you want to just use self.z then don't use double underscore name mangling. You are trying to have your cake and eat it too. Commented Mar 19, 2021 at 2:25
  • 1
    1. If z is meant to be accessible in b then it should not be private, as @juanpa.arrivillaga suggested. 2. If z is meant to be partially accessible (e.g. read-only) in b then you can use getters and/or setters just like in other OOP languages. Commented Mar 19, 2021 at 2:53

2 Answers 2

3

There are a variety of ways you could solve the problem by changing the API of class a to expose it's __z attribute in some more inheritance-friendly way. For instance, you could make the actual mangled attribute name an implementation detail and have the public API be a property:

class a: def __init__(self, w, x, y, z): self.w = w self.x = x self.y = y self.__z = z @property def z(self): return self.__z @z.setter def z(self, value): self.__z = value 

But unless you're doing some validation or modification of the value somewhere in the property's code, you probably should just do away with the double-underscores and let the child class access self.z like it can w, x and y. The simplest solution is to replace self.__z = z with self.z = z. You can always change it later to use a property if you find you do need validation or something.

If you just want to hint that z is not part of the wider public API, but only for subclasses and other code that knows about the intimate details of a's design, consider using a single underscore: self._z = z. This has no special effects in the interpreter, but the single-underscore serves as a sort of documentation that _z is an internal attribute and you should only mess with it if you know what you're doing.

Sign up to request clarification or add additional context in comments.

Comments

1

You could do something like this if you want to keep your code clean:

class a: def __init__(self, w, x, y, z): self.w = w self.x = x self.y = y self.__z = z def get_field(self): return self.__z class b(a): def __init__(self, w, x, y, z, t): super().__init__(w, x, y, z) self.__t = t def ChildMethodWhichUsingParentField(self): return self.get_field() c = b(1,2,3,4,5) print(c.ChildMethodWhichUsingParentField()) 

Output

4 

Similarly, you can use a setter to change its value:

class a: def __init__(self, w, x, y, z): self.w = w self.x = x self.y = y self.__z = z def get_field(self): return self.__z def set_field(self,z): self.__z = z class b(a): def __init__(self, w, x, y, z, t): super().__init__(w, x, y, z) self.__t = t def ChildMethodWhichUsingParentField(self): return self.get_field() def ChildMethodWhichSettingParentField(self,z): self.set_field(z) c = b(1,2,3,4,5) print(c.ChildMethodWhichUsingParentField()) c.ChildMethodWhichSettingParentField(10) print(c.ChildMethodWhichUsingParentField()) 

Output

4 10 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.