在子类中包含在方法内部时,使继承的属性方法起作用

时间:2018-04-21 07:02:22

标签: python inheritance subclass

我试图让父类中描述的属性/ setter方法在继承到子类时起作用。当我直接从父类分配调用时,我能够使它工作,如下所示。在我的情况下,我需要在方法中包含相同的调用,以便我可以在调用父类之前进行一些计算。我可以通过使用fget方法并将对象传递给它来使其工作,但我希望前一种方法能够工作。

我在StackOverflow上查找了这个问题并发现了一些涉及使用super()的方法,我试过了,但它没有用。

非常感谢任何帮助让这个继承的属性方法在子类中工作!

class A(object):
    """ Base Class """
    def __init__(self, n):
        self.n = n
    @staticmethod
    def slices():
        def get_slices(self):
            return self.n
        def set_slices(self, n):
            self.n = n
        return property(get_slices, set_slices)

class B(A):
    def __init__(self, n):
        self.n = n
    his_slices = A.slices() # <--- works well
    def her_slices(self): # <--- does not work
        return A.slices()

if __name__ == "__main__":
    b = B(100)
    # This works
    print("%d slices" % b.his_slices)
    # 100 slices

    # This fails
    print("%d slices" % b.her_slices)
    # TypeError: %d format: a number is required, not method

    # Can be made to work like this, but I want above to work
    ss = b.her_slices()
    print("%d slices" % ss.fget(b))
    # 100 slices

2 个答案:

答案 0 :(得分:0)

我认为你正在寻找更像这样的东西。

class A(object):
    """ Base Class """
    def __init__(self, n):
        self.n = n
        self.slices
    def get_slices(self):
        return self.n
    def set_slices(self, n):
        self.n = n
    slices = property(get_slices, set_slices)


class B(A):
    def __init__(self, n):
        self.n = n
    his_slices = A.slices # <--- works well
    def her_slices(self): # <--- does not work
        return self.slices

if __name__ == "__main__":
    b = B(100)
    # This works
    print("%d slices" % b.his_slices)
    # 100 slices

    # This fails
    print("%d slices" % b.her_slices())
    # TypeError: %d format: a number is required, not method

我不确定你要做的是什么。

答案 1 :(得分:0)

像对待任何其他继承一样对待它。如果您需要修改子类中常规函数的行为,您只需重新定义该函数并完全更改其内容,或者使用super扩展它并进一步修改它。

如果是setter / getters,你会做同样的事情......重新定义/扩展它们。

在你的情况下,事情有点不同,因为正如其中一位评论者指出的那样,slices实际上是staticmethod,它返回property,而不是属性本身。所以你真的没有可以继承和扩展的现有命名属性。

看看你在__main__尝试做什么,你真正想做的是在你的子类中创建一个名为his_slices的新属性,并在其中适当地调用A.slices gettersetter。像这样

class A(object):
    """ Base Class """
    def __init__(self, n):
        self.n = n

    @staticmethod
    def slices():
        def get_slices(self):
            print("Get", self.n)
            return self.n

        def set_slices(self, n):
            print("Set", n)
            self.n = n

        return property(get_slices, set_slices)

class B(A):
    def __init__(self, n):
        self.n = n

    @property
    def his_slices(self):
        return A.slices().fget(self)

    @his_slices.setter
    def his_slices(self, v):
        value = self.n + v
        print("modified n in setter", value)
        A.slices().fset(self, value)

if __name__ == "__main__":
    b = B(100)

    # setter
    b.his_slices = 101
    # getter
    print("%d slices" % b.his_slices)

如果slices确实是基类中的属性,那么这就是继承和修改getter和setter的方法。它还描述了here

class A(object):
    """ Base Class """
    def __init__(self, n):
        self.n = n

    def get_slices(self):
        print("Get A", self.n)
        return self.n

    def set_slices(self, n):
        print("Set A", n)
        self.n = n

    slices = property(get_slices, set_slices)


class B(A):
    @property
    def slices(self):
        print("Get B", self.n)
        return A.slices.fget(self)

    @slices.setter
    def slices(self, v):
        value = self.n + v
        print(".. Modifing value before Set", value)
        A.slices.fset(self, value) 

if __name__ == "__main__":
    a = A(10)
    b = B(10)

    a.slices = 9
    b.slices = 11
    print("%d a-slices" % a.slices)
    print("%d b-slices" % b.slices)

以上代码的输出:

Set A 9
Modifing value before Set 21
Set A 21
Get A 9
9 a-slices
Get B 21
Get A 21
21 b-slices

......如果有疑问,回到基础并听取Raymond Hettinger has to say about properties

的内容总是有用的