如何避免在python中意外重写方法?

如何避免在python中意外重写方法?,python,class,Python,Class,我知道有很多类似的问题。但我的问题不同。 我不想创建一个无法重写的方法。 我想保护我新创建的类,以免意外重写某些内容 使用下划线作为前缀是很好的,但是很快我就会得到很多带有很多下划线的方法。在我继承的类中的某个地方,我将重写grand祖先的类方法 我真正想要的是这么简单的东西: class Cat(Mammal): def walk(self): if ancestor_has_function('walk'): parent.walk();

我知道有很多类似的问题。但我的问题不同。 我不想创建一个无法重写的方法。 我想保护我新创建的类,以免意外重写某些内容

使用下划线作为前缀是很好的,但是很快我就会得到很多带有很多下划线的方法。在我继承的类中的某个地方,我将重写grand祖先的类方法

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

class Cat(Mammal):
    def walk(self):
        if ancestor_has_function('walk'):
            parent.walk();
        do_something_here();
如果猫的任何祖先(无论是哺乳动物、动物还是生命体)有“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方法的注释,您也可以让它工作。

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

class MyClass:
    def __method(self):
        pass

    def __init__(self):
        self.method = __method

然后检查标识并调用保存的方法

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

class MyClass:
    def __method(self):
        pass

    def __init__(self):
        self.method = __method
然后检查标识并调用保存的方法

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

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

def walk(self):
    if "walk" in dir(Mammal) and callable(Mammal.walk):
        Mammal.walk(self)
    # do something
您可以使用
dir()
函数获取为某个模块或类声明的所有名称。层次结构中更高级别的类中声明的方法也将包括在内。但是,请注意,这也将包括属性,因此请首先检查
callable()

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

def walk(self):
    if "walk" in dir(Mammal) and callable(Mammal.walk):
        Mammal.walk(self)
    # do something

是的
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'):

是的
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'):

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

class Mammal(object):
    def walk(self):
        pass
然后,通过调用
super()
,在子类中扩展它:

使
super()
调用有条件并不困难,但这可能是一个坏主意:它冗长、脆弱,只会鼓励不良做法。如果您确实有很好的理由这样做,您可以像处理任何其他对象一样,在
super
对象上使用
hasattr()

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

不过,您可能只希望在不寻常的情况下执行此操作,例如,出于某种原因,您无法依赖于存在的某些方法的第三方库中的类的子类化。

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

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

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

    def somefunc(self):
        ....

    def someOtherFunc(self):
        ....


allmembers = inspect.getmembers(SomeClass, predicate=inspect.ismethod)
然后,通过调用
super()
,在子类中扩展它:

使
super()
调用有条件并不困难,但这可能是一个坏主意:它冗长、脆弱,只会鼓励不良做法。如果您确实有很好的理由这样做,您可以像处理任何其他对象一样,在
super
对象上使用
hasattr()

class Cat(Mammal):
    def walk(self):
        if hasattr(super(Cat, self), 'walk'):
            super(Cat, self).walk()
        do_something_here()
不过,您可能只希望在不寻常的情况下执行此操作,例如,由于某种原因,您无法依赖于存在某些方法的第三方库中的类的子类化

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>)]
您可以获取类中定义的所有方法的列表,并检查是否有类似名称的方法,因为
getmembers
返回未绑定的方法实例,您也可以轻松访问该函数

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

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

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

@Piet拥有它。不要有条件地重写方法——始终重写它们,并使用
super()
@katrielex调用原始方法
Animal
类可以有或没有
walk
方法。假设它是第三方库,您无法确保它是否有特定的方法,您将看到为什么有必要使用
条件语句
。@Piet有它。不要有条件地重写方法——始终重写它们,并使用
super()
@katrielex调用原始方法
Animal
类可以有或没有
walk
方法。假设它是第三方库,您无法确保它是否有特定的方法,您将看到为什么有必要使用
条件语句
。我以前从未知道python有“super”方法。它也适用于python 2.7吗?是的:
super()
是与python 2.2中的新样式类一起引入的。我以前从未知道python有“super”方法。它是否也适用于Python2.7?是的:
super()
与Python2.2中的新样式类一起引入。