简体   繁体   中英

Setting Values Of Inherited Properties

I want to be able to create a concrete instance of a class that inherits from another concrete class, which in turn inherits from an abstract class.

The basic pattern is:

from abc import ABCMeta, abstractproperty

class Foo(object):
    __metaclass__ = ABCMeta

    @abstractproperty
    def x(self):
        pass

    @abstractproperty
    def y(self):
        pass

class Bar(Foo):
    x = None
    y = None

    def __init__(self, x, y):
        self.x = x
        self.y = y

    @property
    def x(self):
        return self.x

    @x.setter
    def x(self, value):
        self.x = value

    @property
    def y(self):
        return self.y

    @y.setter
    def y(self, value):
        self.y = value

class Baz(Bar):

    def __init__(self):
        super().__init__(x=2, y=6)


a = Baz()

When I try to create the instance of Baz I get a RecursionError: maximum recursion depth exceeded error. (As well as a pylint warning telling me that the signatures of the setter methods don't match the signatures of the base class)

However, if I remove the setters, I get an error self.x = x AttributeError: can't set attribute

What's the correct pattern to do this?

You need to change names for your x() / y() methods or for your x / y properties, for example rename

class Bar(Foo):
    x = None
    y = None

To:

class Bar(Foo):
    x_val = None
    y_val = None

And rename the references to x / y as well.

What you did is basically:

def x():
    return x()

It happened because your def x overridden the x = None , so x is a function(property) that is calling itself. Avoid this by using another attribute(named differently) for storing the actual value of x.

Example from python docs ( https://docs.python.org/3.5/library/functions.html#property ):

class C:
    def __init__(self):
        self._x = None

    @property
    def x(self):
        return self._x

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

Note: attribute names starting with underscore should be considered "private" and should not be directly accessed outside of the class. But it's only a convention for programmers, technically they are just normal attributes and you can do whatever you want, but it's nice to follow some convention, isn't it?

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