python中的基类是什么_为什么在Python中使用抽象基类?

@ Oddthinking的答案没有错,但是我认为它错过了Python在鸭子打字的世界中具有ABC的真实 , 实际的原因。

抽象方法是整齐的,但在我看来,它们并没有真正填补鸭式打字所没有涉及的任何用例。 抽象基类的真正威力在于它允许你定制isinstance和issubclass的行为 。 ( __subclasshook__基本上是Python的__instancecheck__和__subclasscheck__钩子之上的一个友好的API。)调整内置结构以处理自定义types是Python哲学的重要组成部分。

Python的源代码是示例性的。 这里是collections.Container如何在标准库中定义(写作时):

class Container(metaclass=ABCMeta): __slots__ = () @abstractmethod def __contains__(self, x): return False @classmethod def __subclasshook__(cls, C): if cls is Container: if any("__contains__" in B.__dict__ for B in C.__mro__): return True return NotImplemented

__subclasshook__这个定义说任何具有__contains__属性的类都被认为是Container的一个子类,即使它没有直接__subclasshook__它的子类。 所以我可以写这个:

class ContainAllTheThings(object): def __contains__(self, item): return True >>> issubclass(ContainAllTheThings, collections.Container) True >>> isinstance(ContainAllTheThings(), collections.Container) True

换句话说, 如果你实现了正确的界面,你就是一个子类! ABCs提供了一种正式的方式来定义Python中的接口,同时坚持鸭式打字的精神。 此外,这也是一种尊重开放原则的方式 。

Python的对象模型看起来表面上类似于一个更传统的面向对象系统(我的意思是Java *) – 我们得到了类,你的对象,你的方法 – 但是当你抓表面时,你会发现更丰富的东西更灵活。 同样,Java开发人员也可以认识到Python的抽象基类的概念,但实际上它们是为了一个非常不同的目的。

我有时会发现自己正在编写可以作用于单个项目或多个项目集合的多态函数,而且我发现isinstance(x, collections.Iterable)比hasattr(x, '__iter__')或同等try...except更具可读性try...except块。 (如果你不知道Python,那三个中的哪一个会使代码的意图清晰?)

我发现我很less需要写自己的ABC–我更喜欢依靠鸭子打字 – 而且通常我会通过重构来发现需要的东西。 如果我看到一个多态函数做了很多属性检查,或者很多函数做了相同的属性检查,那味道就表明存在一个等待提取的ABC。

*没有深入讨论Java是否是一个“传统”的面向对象系统。

附录 :尽pipe抽象基类可以覆盖isinstance和issubclass的行为,但它仍然不会进入虚拟子类的MRO 。 这对于客户端来说是一个潜在的问题:并不是每个实例对象isinstance(x, MyABC) == True都具有在MyABC定义的方法。

class MyABC(metaclass=abc.ABCMeta): def abc_method(self): pass @classmethod def __subclasshook__(cls, C): return True class C(object): pass # typical client code c = C() if isinstance(c, MyABC): # will be true c.abc_method() # raises AttributeError

不幸的是,其中一个“只是不这样做”的陷阱(其中Python相对较less!):避免用__subclasshook__和非抽象方法来定义ABCs。 而且,您应该使__subclasshook__的定义与您定义的ABC抽象方法集一致。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值