แสดงรายการคลาสพื้นฐานทั้งหมดในลำดับชั้นของคลาสที่กำหนดหรือไม่


139

เมื่อพิจารณาถึงคลาสFoo(ไม่ว่าจะเป็นคลาสสไตล์ใหม่หรือไม่ก็ตาม) คุณจะสร้างคลาสพื้นฐานทั้งหมดได้อย่างไร- ที่ใดก็ได้ในลำดับชั้นการสืบทอด - issubclassจาก?

คำตอบ:


198

inspect.getmro(cls)ใช้ได้กับทั้งคลาสสไตล์ใหม่และแบบเก่าและส่งกลับค่าเดียวกันกับNewClass.mro(): รายการคลาสและคลาสบรรพบุรุษทั้งหมดตามลำดับที่ใช้สำหรับวิธีการแก้ปัญหา

>>> class A(object):
>>>     pass
>>>
>>> class B(A):
>>>     pass
>>>
>>> import inspect
>>> inspect.getmro(B)
(<class '__main__.B'>, <class '__main__.A'>, <type 'object'>)

2
ไม่ทำงานสำหรับคลาส pyobjc :( ไฟล์ "/Users/rbp/Projects/zzzzzzz/macmdtypes.py" บรรทัดที่ 70 ในการบังคับพิมพ์ Inspector.getmro (เส้นทาง) ไฟล์ "/System/Library/Frameworks/Python.framework/ เวอร์ชัน / 2.7 / lib / python2.7 / Inspector.py "บรรทัด 348 ใน getmro searchbases (cls, result) File" /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/inspect .py "บรรทัด 339 ใน _searchbases สำหรับฐานใน cls .__ bases_ : AttributeError: วัตถุ 'NSTaggedDate' ไม่มีแอตทริบิวต์ '__bases '
rbp

18
@rbp ฉันสงสัยว่าคุณมีปัญหาเดียวกันที่ผมพบ: คุณกำลังพยายามที่จะทำแทนinspect.getmro(obj) inspect.getmro(type(obj))
งด

44

ดู__bases__คุณสมบัติที่มีอยู่ใน python classซึ่งมี tuple ของคลาสฐาน:

>>> def classlookup(cls):
...     c = list(cls.__bases__)
...     for base in c:
...         c.extend(classlookup(base))
...     return c
...
>>> class A: pass
...
>>> class B(A): pass
...
>>> class C(object, B): pass
...
>>> classlookup(C)
[<type 'object'>, <class __main__.B at 0x00AB7300>, <class __main__.A at 0x00A6D630>]

5
ซึ่งอาจทำให้เกิดรายการที่ซ้ำกัน และนี่คือสาเหตุที่เอกสารสำหรับgetmroระบุอย่างชัดเจนว่า "ไม่มีชั้นเรียนปรากฏมากกว่าหนึ่งครั้งในทูเพิลนี้"?
Sridhar Ratnakumar

10
ข้อควรระวัง__bases__เพิ่มขึ้นหนึ่งระดับเท่านั้น (ตามที่ยูทิลิตีเรียกซ้ำของคุณบอกเป็นนัย ๆ แต่การมองคร่าวๆที่ตัวอย่างอาจไม่เข้าใจ)
Bob Stein

34

inspect.getclasstree()จะสร้างรายการชั้นเรียนและฐานที่ซ้อนกัน การใช้งาน:

inspect.getclasstree(inspect.getmro(IOError)) # Insert your Class instead of IOError.

2
โอดี และเพื่อให้ได้ผลลัพธ์ที่ดียิ่งขึ้นให้ใช้ pprint! python -c 'import inspect; from pprint import pprint as pp; pp(inspect.getclasstree(inspect.getmro(IOError)))'
penguin359

20

คุณสามารถใช้__bases__ทูเพิลของคลาสออบเจ็กต์:

class A(object, B, C):
    def __init__(self):
       pass
print A.__bases__

ทูเปิลที่ส่งคืน__bases__มีคลาสพื้นฐานทั้งหมด

หวังว่าจะช่วยได้!


ถ้าคลาสของคุณสืบทอดมาจากคลาสที่สืบทอดมาจากคลาสจะมีเพียงส่วนแรกของเชนเท่านั้นที่อยู่ในนั้น__bases__
บอริส

เรียบง่ายและสะอาดโดยไม่ต้องนำเข้าโมดูลทั้งหมดสำหรับฟังก์ชันเดียว
Temperosa

8

ใน python 3.7 คุณไม่จำเป็นต้องนำเข้าการตรวจสอบ type.mro จะให้ผลลัพธ์

>>> class A:
...   pass
... 
>>> class B(A):
...   pass
... 
>>> type.mro(B)
[<class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
>>>

ให้ความสนใจว่าใน python 3.x ทุกคลาสสืบทอดมาจากคลาสอ็อบเจ็กต์พื้นฐาน


8

ตามเอกสาร Pythonเราสามารถใช้class.__mro__แอตทริบิวต์หรือclass.mro()วิธีการ:

>>> class A:
...     pass
... 
>>> class B(A):
...     pass
... 
>>> B.__mro__
(<class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
>>> A.__mro__
(<class '__main__.A'>, <class 'object'>)
>>> object.__mro__
(<class 'object'>,)
>>>
>>> B.mro()
[<class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
>>> A.mro()
[<class '__main__.A'>, <class 'object'>]
>>> object.mro()
[<class 'object'>]
>>> A in B.mro()
True


2

แม้ว่าคำตอบของ Jochen จะมีประโยชน์และถูกต้องมากเนื่องจากคุณสามารถรับลำดับชั้นของคลาสได้โดยใช้เมธอด. getmro () ของโมดูลการตรวจสอบสิ่งสำคัญคือต้องเน้นว่าลำดับชั้นการสืบทอดของ Python มีดังนี้:

เช่น:

class MyClass(YourClass):

คลาสที่สืบทอด

  • ชั้นเด็ก
  • คลาสที่ได้รับ
  • คลาสย่อย

เช่น:

class YourClass(Object):

คลาสที่สืบทอดมา

  • ระดับผู้ปกครอง
  • คลาสพื้นฐาน
  • ซุปเปอร์คลาส

คลาสหนึ่งสามารถสืบทอดจากคลาสอื่นได้ - แอตทริบิวต์ของคลาสนั้นได้รับการสืบทอด - โดยเฉพาะเมธอดของมันจะได้รับการสืบทอด - ซึ่งหมายความว่าอินสแตนซ์ของคลาสที่สืบทอด (ลูก) สามารถเข้าถึงที่มาของคลาสที่สืบทอด (พาเรนต์)

อินสแตนซ์ -> คลาส -> แล้วสืบทอดคลาส

โดยใช้

import inspect
inspect.getmro(MyClass)

จะแสดงลำดับชั้นภายใน Python

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.