بيثون التأمل: كيفية الحصول على قائمة "لم يتم فرزها" من سمات الكائن؟
-
11-07-2019 - |
سؤال
والتعليمة البرمجية التالية
import types
class A:
class D:
pass
class C:
pass
for d in dir(A):
if type(eval('A.'+d)) is types.ClassType:
print d
والمخرجات
C
D
وكيف يمكنني الحصول عليه لإخراج بالترتيب الذي تم تعريف هذه الفئات في مدونة؟ أي بمعنى.
D
C
هل هناك أي طريقة أخرى غير استخدام inspect.getsource (A)، وتحليل ذلك؟
المحلول
ويضم وحدة inspect
أيضا وظيفة findsource
. تقوم بإرجاع الصفوف (tuple) خطوط المصدر ورقم السطر حيث يتم تعريف الكائن.
>>> import inspect
>>> import StringIO
>>> inspect.findsource(StringIO.StringIO)[1]
41
>>>
وظيفة findsource
بالبحث في الواقع الحوض الصغير الملف المصدر وبالبحث عن المرشحين المحتملين إذا تم منحها فئة وجوه.
ونظرا لمن طريقة، فونكأيشن-، traceback-، frame-، أو رمز الكائن، يبدو ببساطة على السمة co_firstlineno
من (الواردة) رمز الكائن.
نصائح أخرى
ملاحظة أن هذا التوزيع يتم بالفعل بالنسبة لك تفتيش في - نلقي نظرة على inspect.findsource
، الذي يبحث في وحدة لتعريف الفئة وإرجاع عدد المصدر والخط. يجب أن يكون الترتيب على هذا العدد خط (قد تحتاج أيضا إلى تقسيم من فئات محددة في وحدات منفصلة) إعطاء حق النظام.
ولكن، لا يبدو هذه الوظيفة إلى أن تكون موثقة، وفقط باستخدام تعبير عادي للعثور على الخط، لذلك قد لا تكون موثوقة جدا.
وثمة خيار آخر هو استخدام metaclasses، أو بطريقة أخرى ليأمر إما صراحة أو ضمنا المعلومات إلى كائن. على سبيل المثال:
import itertools, operator
next_id = itertools.count().next
class OrderedMeta(type):
def __init__(cls, name, bases, dct):
super(OrderedMeta, cls).__init__(name, bases, dct)
cls._order = next_id()
# Set the default metaclass
__metaclass__ = OrderedMeta
class A:
class D:
pass
class C:
pass
print sorted([cls for cls in [getattr(A, name) for name in dir(A)]
if isinstance(cls, OrderedMeta)], key=operator.attrgetter("_order"))
ولكن هذا هو تغيير تدخلية إلى حد ما (يتطلب وضع metaclass من أي الطبقات كنت ترغب في أن OrderedMeta)
لا، لا يمكنك الحصول على تلك السمات في الترتيب الذي تبحث عنه. يتم تخزين سمات الثعبان في ديكت (اقرأ: hashmap)، الذي لا يوجد لديه الوعي أجل الإدراج.
وبالإضافة إلى ذلك، أود أن تجنب استخدام وحدة التقييم من قبل ببساطة قائلا
if type(getattr(A, d)) is types.ClassType:
print d
في حلقة الخاص بك. لاحظ أنه يمكنك أيضا تكرار فقط من خلال أزواج مفتاح / قيمة في A.__dict__
وAFAIK، لا - ليس هناك *. وذلك لأن كل من سمات الفئة التي يتم تخزينها في القاموس (والذي هو، كما تعلمون، غير مرتبة).
*: أنه قد يكون في الواقع الممكن، ولكن هذا يتطلب إما الديكور أو ربما metaclass القرصنة. هل أي من تلك تهمك؟
وأنا لا أحاول أن أكون سطحي هنا، ولكن سيكون من الممكن بالنسبة لك لتنظيم الفئات في المصدر أبجديا؟ أجد أن عندما يكون هناك الكثير من الطبقات في ملف واحد وهذا يمكن أن تكون مفيدة في حد ذاتها.