python / python/cpython

Resolution / determining of metaclass docs don't align with what really happens

未關閉
#99,505 2 則留言 0 個 reaction 已指派 0 人 在 GitHub 檢視

還沒有人認領這個 Issue。

docs
主要語言
Python
星號
77.2k
分支
36k
PR 合併指標
PR 指標待擷取

描述

Documentation

I'm not 100% sure if this is an issue with the docs or the interpreter. But it's evident that the docs don't match what the interpreter does.

The docs say here:

The appropriate metaclass for a class definition is determined as follows:

  • if no bases and no explicit metaclass are given, then :func:type is used;
  • if an explicit metaclass is given and it is not an instance of
    :func:type, then it is used directly as the metaclass;
  • if an instance of :func:type is given as the explicit metaclass, or
    bases are defined, then the most derived metaclass is used.

The most derived metaclass is selected from the explicitly specified
metaclass (if any) and the metaclasses (i.e. type(cls)) of all specified
base classes. The most derived metaclass is one which is a subtype of all
of these candidate metaclasses. If none of the candidate metaclasses meets
that criterion, then the class definition will fail with TypeError.

So according to that, the metaclass of D in this code

class M1(type): pass
class M2(type): pass
class Mx(M1, M2): pass

class A1(metaclass=M1): pass
class A2(A1): pass

class B1(metaclass=M2): pass

class C1(metaclass=Mx): pass

class D(A2, B1, C1): pass

should be Mx as it's the most derived of all candidates (M1, M2, Mx). But instead the cpython exitis with

    class D(A2, B1, C1): pass
TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases

Note that class D(A2, C1, B1): pass works.

Some additional context:

As said above, I'm not even sure what the actually algorithm is that determines the implicit metaclass. From my experimentation, I assume it's:

  • If there's an explicit metaclass, it is checked to be a sub-class of the metaclass of each parent
  • If there's no explicit metaclass, the parents are checked from left to right:
    • When a new metaclass is encountered, it is checked to be a sub-class of the previous implicit metaclass and, if it is, set as the new implicit metaclass.
Linked PRs
  • gh-123349

貢獻指南

開啟貢獻指南

從這裡開始

  1. 先讀完整個 Issue,再讀專案的貢獻指南。
  2. 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
  3. Fork 儲存庫,在一個分支上完成修改。
  4. 送出 Pull Request,並在描述裡引用這個 Issue 編號。

研究方向

從 Doc/reference/datamodel.rst 中的元類部分開始,並在 CPython 下執行所提供的類別定義範例,以比較文件所述行為與實際觀察到的行為。檢視連結的 PR gh-123349 以及其中參考的歷史 issue,以了解目前的調查。完成的標準是直譯器行為與文件得到協調,並有明確的解決方案。

由索引模型根據 Issue 內容生成。

評估

技術堆疊
python
領域
documentation
Issue 類型
文件
難度
4/5
預估耗時
3-5 天
活躍度
停滯
描述清晰度
基本清楚
新手友好度
25/100

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。