لا ينبغي __metaclass__ إجبار استخدام metaclass في بيثون؟
-
03-07-2019 - |
سؤال
ولقد تم في محاولة لمعرفة المزيد عن metaclasses في بيثون. أحصل على الفكرة الرئيسية، ولكن أنا لا يمكن أن يبدو لتفعيل آلية. كما أفهمها، يمكنك تحديد M لتكون على metaclass عند بناء K الفئة عن طريق وضع __metaclass__
إلى M على المستوى العالمي أو فئة. لاختبار هذا الخروج، كتبت البرنامج التالي:
p = print
class M(type):
def __init__(*args):
type.__init__(*args)
print("The rain in Spain")
p(1)
class ClassMeta:
__metaclass__ = M
p(2)
__metaclass__ = M
class GlobalMeta: pass
p(3)
M('NotMeta2', (), {})
p(4)
ولكن، عندما كنت تشغيله، وأحصل على الإخراج التالية:
C:\Documents and Settings\Daniel Wong\Desktop>python --version Python 3.0.1 C:\Documents and Settings\Daniel Wong\Desktop>python meta.py 1 2 3 The rain in Spain 4
ويجب أن لا أرى "المطر في اسبانيا" بعد 1 و 2؟ ما الذي يحدث هنا؟
المحلول
في بيثون 3 (الذي تستخدمه) يتم تحديد metaclasses التي كتبها معلمة الكلمة الرئيسية في تعريف الفئة:
class ClassMeta(metaclass=M):
pass
وتحديد ملكية من الدرجة __metaclass__
أو المتغير العالمي في بناء الجملة القديمة من بيثون 2.x و لا تعد معتمدة. انظر أيضا "ما هو الجديد في بيثون 3" و <ل أ href = "http://www.python.org/dev/peps/pep-3115/" يختلط = "نوفولو noreferrer"> PEP 2115 .
نصائح أخرى
وهذا يعمل كما هو متوقع في بيثون 2.6 (وأقدم)، ولكن في 3.0 المحددة metaclasses مختلف:
class ArgMeta(metaclass=M): ...
وبناء جملة metaclasses ديه تغير في بايثون 3.0. السمة __metaclass__
لم يعد الخاصة إما في الدرجة ولا مستوى الوحدة النمطية. أن تفعل ما نحاول القيام به، تحتاج إلى تحديد metaclass
كحجة رئيسية للبيان class
:
p = print
class M(type):
def __init__(*args):
type.__init__(*args)
print("The rain in Spain")
p(1)
class ClassMeta(metaclass=M): pass
والعائد:
1
The rain in Spain
وكما كنت تتوقع.