python:元类或`__init_subclass__`:不良子类创建期间的惯用异常吗?

发布于 2025-02-08 07:40:11 字数 148 浏览 0 评论 0原文

是否有任何良好的惯例来通过元素或__ init_subclass __提出什么例外,以在子类上执行某些不变性?

对于这个答案,我将接受Python内置行为,PEPS,标准库或良好成熟的第三方库,或者认为为什么应该以某种方式进行操作的理由。

Are there any good conventions for what exception should be raised by a metaclass or __init_subclass__ that enforces certain invariants on subclasses?

For this answer I would accept precedent from Python built-in behavior, PEPs, the standard library, or well-established third-party libraries, or compelling reasoning for why it should be done a certain way.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

痴骨ら 2025-02-15 07:40:11

我在python本身中所知道的先例是始终提高typeerror

  • 如果您尝试为不支持它的类型的子类提供插槽,则CPYTHON将提出type> typeerror
     >>>类More Powerfultuple(元组):通过
    ... __ slots__ =('Power',)
    ...
    Trackback(最近的最新电话):
      文件“< stdin>”,第1行,in< module>
    typeError:非__ slots__不支持“元组”的亚型
     
  • 如果您尝试子类bool,它将升级typeerror
     >>>班级BetterBool(Bool):通过
    ...
    Trackback(最近的最新电话):
      文件“< stdin>”,第1行,in< module>
    TypeError:类型“ bool”不是可接受的基本类型
     
  • Micropython至少有一个Python实施了该公约,并将其用于其他类别不允许子类别的类别:
     >>> class strongerfastermethodtype(types.methodtype):
    ... 经过
    ...
    Trackback(最近的最新电话):
      文件“< stdin>”,第1行,in< module>
    TypeError:类型“ bund_method”不是可接受的基本类型
     

这里最重要的先例是第一个。后两个可以说是特定于类型的子分类错误,因为它们是由于试图使用错误的 type 作为输入子分类操作而特别错误的(因此,如果您只有这些示例,那仍然是一致的如果由于某些其他原因,如果子类是错误的,则更合适。但是第一个是提高typeError,即使问题不一定是特定于类型的:您可以用__ slots__ =('POWER',)__ slots __ slots_ = = ()它将起作用。因此,即使在许多其他情况下,我们使用一个空的iToserable而不是使用,我们至少在参考子类错误的语言本身的参考语言本身中至少有一个预先一个或多个元素将更适当地valueerror


此外,该文档排除了尝试使用多个继承对类似的子分类错误(在某些情况下可能会很诱人) - 例如,元素或__ Init_SINIT_SUBCLASS __ 可能会想象出工厂函数在程序执行的中间动态地制作子类,并认为提出更精确的错误将有所帮助确定乘以子类typeErrorvalueerror,也许是他们自己的子分类错误和value error,而不仅仅是提高普通,这是一个好主意。 typeError如上所述的类别precent确实可以),因为该文档明确建议不要从多个异常类型进行子类别,因为内部实现详细信息可以免费实现不同的例外,以可能使它们两者都无法使用它们作为基础类:

有些具有自定义内存布局,这使得无法创建从多个异常类型继承的子类。类型的内存布局是实现细节,可能会在Python版本之间发生变化,从而导致新的冲突。因此,建议避免完全分类多个异常类型。


我不知道有任何PEP,标准库或第三方图书馆来建立特定的做法。

(但是,肯定有库,例如nequ tupledataclassesattrs,甚至可能是Sqlalchemy和Pydantic这样的类别,它们可以编程生成类根据用户参数,可能值得寻找自己的示例。)

The precedent I know of within Python itself is to just always raise TypeError:

  • If you try to give slots to subclasses of types that don't support it, CPython raises a TypeError:
    >>> class MorePowerfulTuple(tuple): pass
    ...     __slots__ = ('power',)
    ...
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: nonempty __slots__ not supported for subtype of 'tuple'
    
  • If you try to subclass bool, it raises a TypeError:
    >>> class BetterBool(bool): pass
    ...
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: type 'bool' is not an acceptable base type
    
  • At least one other Python implementation, MicroPython, has taken this convention and used it for other classes that it does not allow subclassing:
    >>> class StrongerFasterMethodType(types.MethodType):
    ...     pass
    ...
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: type 'bound_method' is not an acceptable base type
    

The most significant precedent-setter here is the first one. The latter two are arguably type-specific subclassing errors, because they're specifically errors due to trying to use a wrong type as input the subclassing operation (so if you had just those examples, that is still consistent with other exception types being more appropriate if the subclassing is erroneous for some other reason). But the first one is raising a TypeError even though the problem is not necessarily type-specific: you could replace __slots__ = ('power',) with __slots__ = () and it would work. So we've got at least one precent in the reference implementation of the language itself of a subclassing error being reported as a TypeError, even though in many other situations, using an empty iterable rather than an iterable with one or more elements would be more appropriately a ValueError.


There does not seem to be any class in the built-in exception hierarchy designed for this purpose.

Also, that documentation rules out trying to use multiple inheritance for the subclassing errors like these (which could've been tempting in some situations - for example, the implementor of a metaclass or __init_subclass__ might imagine a factory function dynamically making subclasses on the fly in the middle of program execution based on some parameters, and think it would be helpful to raise a more precise error like ValueError - so a developer might decide it's a good idea to multiply subclass TypeError and ValueError and maybe their own subclassing error and ValueError, instead of just raising a plain TypeError as above built-in class precent does), because that documentation explicitly recommends not subclassing from multiple exception types, due to internal implementation details being free to implement different exceptions in a way that might make it impossible to use them both as base classes:

Some have custom memory layouts which makes it impossible to create a subclass that inherits from multiple exception types. The memory layout of a type is an implementation detail and might change between Python versions, leading to new conflicts in the future. Therefore, it’s recommended to avoid subclassing multiple exception types altogether.


I don't know of any PEPs, standard libraries, or third-party libraries establishing a specific practice.

(However, there are definitely libraries, such as namedtuple, dataclasses, attrs, and probably even ones like SQLAlchemy and Pydantic, which programmatically generate classes based on user parameters, that might be worth looking at for their own examples.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文