1

我知道那里有很多类似的问题。但我的问题不同。 我不想做一个不能被覆盖的方法。 我想保护我新创建的类不会意外覆盖某些东西。

使用下划线作为前缀非常好,但很快我就会得到很多带有很多下划线的方法。在我继承的类的某个地方,我将覆盖祖辈的类方法。

我真正想要的是这样简单的东西:

class Cat(Mammal):
    def walk(self):
        if ancestor_has_function('walk'):
            parent.walk();
        do_something_here();

如果 Cat 的任何祖先(哺乳动物、动物或 LifeForm)具有“walk”方法,则应首先执行父方法。

这有可能在python中做到这一点吗?

编辑: 例如,这是我认为不错的答案的简历。希望这对其他人有帮助:

class Animal(object):
    pass
    #def walk(self):
    #    print('animal walk')

class Mammal(Animal):
    def walk(self):
        if hasattr(super(Mammal, self), 'walk') and callable(super(Mammal,self).walk):
            super(Mammal, self).walk()
        print('mammal walk')

class Cat(Mammal):
    def walk(self):
        super(Cat, self).walk()
        print('cat walk')
    
if __name__ == '__main__':
    cat = Cat()
    cat.walk()

这是输出:

哺乳动物步行

猫步

尝试取消注释 Animal 的 walk 方法,你也会让它工作。

4

5 回答 5

6

一般来说,您可能希望在最通用的超类中至少提供一个存根方法:

class Mammal(object):
    def walk(self):
        pass

然后,通过调用在子类中扩展它super()

class Cat(Mammal):
    def walk(self):
        super(Cat, self).walk()  # or just super().walk(), in Python 3+
        do_something_here()

使super()调用有条件并不难,但这可能是一个坏主意:它冗长、脆弱,并且只会鼓励不良做法。如果你真的,真的有充分的理由这样做,你可以hasattr()super对象上使用,就像你对任何其他对象一样:

class Cat(Mammal):
    def walk(self):
        if hasattr(super(Cat, self), 'walk'):
            super(Cat, self).walk()
        do_something_here()

但是,您只想在不寻常的情况下执行此操作,例如从第三方库子类化类,由于某种原因,您不能依赖某些存在的方法。

于 2012-09-06T10:45:44.363 回答
3

是的。hasattr检查是否存在具有特定名称的属性。并callable检查特定属性是否可调用。

class Mammal(object):
    def walk(self):
        print "walking"


class Cat(Mammal):
    def walk(self):
        if hasattr(Mammal,'walk') and callable(Mammal.walk):
            Mammal.walk(self);
        print "another walking!"

现在:

>>> my_cat = Cat()
>>> my_cat.walk()
walking
another walking!

请注意,您还可以使用super这样的方式获取父类:

if hasattr(super(Cat, self),'walk'):
于 2012-09-06T10:43:50.690 回答
1

您可以使用该dir()函数获取为某个模块或类声明的所有名称。在层次结构中较高的类中声明的方法也将包括在内。但是请注意,这也将包括属性,因此请先检查callable()

此外,在 python 中调用父方法看起来有点不同,请参见下面的代码。

def walk(self):
    if "walk" in dir(Mammal) and callable(Mammal.walk):
        Mammal.walk(self)
    # do something
于 2012-09-06T10:41:21.370 回答
0

您可以将原始方法保留在字段中

class MyClass:
    def __method(self):
        pass

    def __init__(self):
        self.method = __method

然后检查身份并调用保存的方法

于 2012-09-06T10:37:52.213 回答
0
import inspect

class SomeClass():
    def __init__(self):
        ...

    def somefunc(self):
        ....

    def someOtherFunc(self):
        ....


allmembers = inspect.getmembers(SomeClass, predicate=inspect.ismethod)

getmembers返回给定类中定义的所有方法的列表,它是包含方法名称和定义的元组列表:

[('__init__', <unbound method SomeClass.__init__>),
 ('somefunc', <unbound method SomeClass.somefunc>),
 ('someOtherFunc', <unbound method SomeClass.someOtherFunc>)]

由于元组的第一个元素是字符串,您可以使用基于字符串的方法来过滤基本方法,例如__init__

allmembers = filter(lambda x: not x.startswith('__'), [x[0] for x in inspect.getmembers(SomeClass, predicate=inspect.ismethod))])

[('somefunc', <unbound method SomeClass.somefunc>),
('someOtherFunc', <unbound method SomeClass.someOtherFunc>)]

您可以获得类中定义的所有方法的列表,并检查您是否有类似名称的方法,因为getmembers返回一个未绑定的方法实例,您也可以轻松访问该函数。

于 2012-09-06T10:57:30.487 回答