Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 有没有办法限制子类继承其父类的某些方法?_Python_Inheritance_Python 2.7 - Fatal编程技术网

Python 有没有办法限制子类继承其父类的某些方法?

Python 有没有办法限制子类继承其父类的某些方法?,python,inheritance,python-2.7,Python,Inheritance,Python 2.7,比如说,我有上面两个类,水是从液体继承的。我有没有办法限制Water继承父方法之一,比如bar?您可以将该方法重写为no-op,但不能删除它。这样做将违反面向对象设计的核心原则之一,即从某个父对象继承的任何对象都应该能够在使用父对象的任何地方使用。这就是众所周知的Liskov替换原理。您可以将该方法重写为no op,但不能将其删除。这样做将违反面向对象设计的核心原则之一,即从某个父对象继承的任何对象都应该能够在使用父对象的任何地方使用。这就是众所周知的里斯科夫替换原理。有点像。但不要这样做 cl

比如说,我有上面两个类,水是从液体继承的。我有没有办法限制Water继承父方法之一,比如bar?

您可以将该方法重写为no-op,但不能删除它。这样做将违反面向对象设计的核心原则之一,即从某个父对象继承的任何对象都应该能够在使用父对象的任何地方使用。这就是众所周知的Liskov替换原理。

您可以将该方法重写为no op,但不能将其删除。这样做将违反面向对象设计的核心原则之一,即从某个父对象继承的任何对象都应该能够在使用父对象的任何地方使用。这就是众所周知的里斯科夫替换原理。

有点像。但不要这样做

class Liquid(object):
    def foo(self):
        pass

    def bar(self):
        pass

class Water(Liquid):

有点。但不要这样做

class Liquid(object):
    def foo(self):
        pass

    def bar(self):
        pass

class Water(Liquid):

正如其他答案所说,您可以中断一个继承的方法

另一种方法是重构可选方法,并从没有它们的基类继承:

class Liquid(object):
    def foo(self):
        pass

    def bar(self):
        pass

class Water(Liquid):
    def __getattribute__(self, name):
        if name == 'bar':
            raise AttributeError("'Water' object has no attribute 'bar'")

l = Liquid()
l.bar()
w = Water()
w.bar()

正如其他答案所说,您可以中断一个继承的方法

另一种方法是重构可选方法,并从没有它们的基类继承:

class Liquid(object):
    def foo(self):
        pass

    def bar(self):
        pass

class Water(Liquid):
    def __getattribute__(self, name):
        if name == 'bar':
            raise AttributeError("'Water' object has no attribute 'bar'")

l = Liquid()
l.bar()
w = Water()
w.bar()
我想您可以通过使用插槽属性来实现这一点

如果调用了bar,可能会实现getattr方法并引发相应的异常

然而,我同意,你不想在实践中这样做,因为这是一个糟糕设计的标志

我想您可以通过使用插槽属性来实现这一点

如果调用了bar,可能会实现getattr方法并引发相应的异常


但是,我同意,您不希望在实践中这样做,因为这是糟糕设计的标志。

这可能不是一个好主意,但您可以始终使用元类来实现私有属性:

class BaseLiquid(object):
    def foo(self):
        pass

class Barised(object):
    def bar(self):
        pass

class Liquid(BaseLiquid, Barised): pass

class Water(BaseLiquid):
    def drip(self):
        pass
输出为:

def private_attrs(name, bases, attrs):
    def get_base_attrs(base):
        result = {}

        for deeper_base in base.mro()[1:]:
            result.update( get_base_attrs(deeper_base) )

        priv = []
        if "__private__" in base.__dict__:
            priv = base.__private__

        for attr in base.__dict__:
            if attr not in priv:
                result.update( {attr: base.__dict__[attr]} )

        return result


    final_attrs = {}
    for base in bases:
        final_attrs.update( get_base_attrs(base) )

    final_attrs.update(attrs)

    return type(name, (), final_attrs)


class Liquid(object):
    __metaclass__ = private_attrs
    __private__ = ['bar']
    def foo(self):
        pass

    def bar(self):
        pass

class Water(Liquid):
    __metaclass__ = private_attrs

print Water.foo
print Water.bar

编辑:这将打乱isinstance,因为它不会修改类的基。

这可能不是一个好主意,但您可以始终使用元类来实现私有属性:

class BaseLiquid(object):
    def foo(self):
        pass

class Barised(object):
    def bar(self):
        pass

class Liquid(BaseLiquid, Barised): pass

class Water(BaseLiquid):
    def drip(self):
        pass
输出为:

def private_attrs(name, bases, attrs):
    def get_base_attrs(base):
        result = {}

        for deeper_base in base.mro()[1:]:
            result.update( get_base_attrs(deeper_base) )

        priv = []
        if "__private__" in base.__dict__:
            priv = base.__private__

        for attr in base.__dict__:
            if attr not in priv:
                result.update( {attr: base.__dict__[attr]} )

        return result


    final_attrs = {}
    for base in bases:
        final_attrs.update( get_base_attrs(base) )

    final_attrs.update(attrs)

    return type(name, (), final_attrs)


class Liquid(object):
    __metaclass__ = private_attrs
    __private__ = ['bar']
    def foo(self):
        pass

    def bar(self):
        pass

class Water(Liquid):
    __metaclass__ = private_attrs

print Water.foo
print Water.bar

编辑:这会弄乱isinstance,因为它不会修改类的基。

我总是将方法重写为no-op。但是,我使用的框架部分依赖于方法的存在来确定功能是否可用。但是谢谢你提醒我OOD的原则。我应该抛弃这种方法,找到一条不同的出路。谢谢。我总是将方法重写为no-op。但是,我使用的框架依赖于方法的存在来确定功能是否可用。但是谢谢你提醒我OOD的原则。我应该抛弃这种方法,找到一条不同的出路。谢谢。这是一个很好的建议,但不适用于本例,而父类是我正在使用的框架的一部分,通常我不想弄乱它。@ahmoo请检查是否不可能。请快速查看源代码。否则,请务必分析此方法是否始终是必需的-您可以让被重写的方法引发异常,或返回固定数据。可以,先生。谢谢你的建议很好的建议,但在这种情况下不适用,而父类是我正在使用的框架的一部分,通常我不想弄乱它。@ahmoo请检查这是否可行,并快速查看源代码。否则,请务必分析此方法是否始终是必需的-您可以让被重写的方法引发异常,或返回固定数据。可以,先生。谢谢你的建议有趣的回答~是的,我不会这么做~不过,很高兴知道。Thx。有趣的回答~是的,我不会这么做~不过,很高兴知道。谢谢。