简体   繁体   中英

Override a field in parent class with property in child class

Where I am now looks like this:

class A(object):
    def __init__(self, val):
        self.x=val
        self.y=42
        # other fields

class B(object):
    def __init__(self):
        self.a=22
        # other fields

class C(A,B):
    def __init__(self, val):
        super(C,self).__init__(val)
    @property
    def x(self):
        # if A.x is None return a value that I can compute from A.y and B.a
        # if A.x is not None return it
    @x.setter
    def x(self, val):
        # set the field value

Sometimes I just want to set an assumed value for x by hand, in which case I would just use an A . In other cases I want to use a more complicated approach that involves computing Ax 's value on the basis of information that is organized into a B . The idea in this code is to make a C class that can look like an A (in terms of the x field) but doesn't need that field value to be set by hand, instead it just gets derived.

What I can't figure out is how to have the Cx property shadow the Ax field in a sensible way.

The line self.x = val in the A.__init__ method will simply invoke your Cx setter . You already have everything handled here. You are handling per instance attributes here, not attributes on a class that are inherited by subclasses.

All you need to do is to set a different attribute in the setter to represent the x value. You could name it _x , for example:

class C(A, B):
    _x = None

    @property
    def x(self):
        if self._x is not None:
            return self._x
        return self.a + self.y

    @x.setter
    def x(self, val):
        self._x = val

Note that if all C.__init__ does is call super().__init__ , you don't need it at all. However, you do need to make sure at least A.__init__() plays along in the inheritance structure; add in more calls to super().__init__() :

class A(object):
    def __init__(self, val, *args, **kwargs):
        super(A, self).__init__(*args, **kwargs)
        self.x = val
        self.y = 42

class B(object):
    def __init__(self, *args, **kwargs):
        super(B, self).__init__(*args, **kwargs)
        self.a = 22

Using *args and **kwargs allows these methods to pass on any extra arguments to other classes in the hierarchy.

Demo, using the above classes:

>>> c = C(None)
>>> c.x
64
>>> c.x = 15
>>> c.x
15

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