简体   繁体   中英

Python - Updating Child Attributes with a Base Class Method

I have spent the day trying to find an answer to this question but have come up with nothing.

Suppose I have several classes, each containing a methods that are identical to those in the others.

class A:
    def __init__(self, attr1, attr2, color):
        self.__attr1 = attr1
        self.__attr2 = attr2
        self.__color = color

    def set_color(self, color):
        self.__color = color

class B:
    def __init__(name, attr3, attr4, color):
         self.__attr3 = attr3
         self.__attr4 = attr4
         self.__color = color

    def set_color(self, color):
        self.__color = color

In this example, the identical methods are reduced to just one identical method, set_color, to illustrate what I am trying to do.

Is there a way to eliminate repeating code, perhaps with an abstract class as follows?

class Parent:
    def set_color(self, color):
        self.__color = color

class A(Parent):
    def __init__(self, attr1, attr2, color):
        self.__attr1 = attr1
        self.__attr2 = attr2
        self.__color = color


class B(Parent):
    def __init__(name, attr3, attr4, color):
         self.__attr3 = attr3
         self.__attr4 = attr4
         self.__color = color

exampleA = A(attr1, attr2, "blue)

I want to be able change from blue to red in a way like this so that I don't have to define the same methods within each class A and B

exampleA.set_color("red")

but this doesn't work as I expected it to, it doesn't change the value of exampleA.__color

You can't. The whole point of __private -style attributes is that they're private. Base classes, subclasses, outsiders, nobody else can see the or modify them. If a base class or subclass tries, they will end up creating their own private attribute on the instance, completely independent of yours.

If you don't want that, just don't use __private -style attributes.

So, what should you do?

Well, the most Pythonic thing is to just use public attributes, and scrap your getters and setters entirely: exampleA.color = 'red' .

If you have a really good reason you need to hide the attributes, maybe you wanted to make them _private instead of __private , which means they're private only by convention, so your code will just work as-is. But again, I doubt you really need to hide them.

If you really, really need __private members, but still really need to defeat the entire purpose of __private members… well, in that case, I lied; you actually can access them, by manually mangling the names. For example, the attribute that's named __color from inside class A is named _A__color from outside of class A .

If you're wondering why Python lets you violate the __private protection... well, unlike the similar feature in Java, this isn't meant to protect you against someone else's malicious code. What it protects you from is a scenario like this: You write a class A with a an attribute __x . I write a class B with an attribute __x . Someone else composes our classes by inheriting from both, without telling either you or me. My code still works, so does yours.

For further information, see the tutorial section on private variables , and the reference documentation on identifiers .

The only reason this wouldn't work exactly as you have it is because you're using attributes prefixed with __ , which makes them "private" and so not accessible to the parent class. Don't do that: just use normal attribute names.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM