سؤال

لديّ تسلسل هرمي من فئة Python ، وأريد تمديده في وقت التشغيل. علاوة على ذلك ، فإن كل فصل في هذا التسلسل الهرمي له سمة ثابتة "dict" ، والتي أريد الكتابة فوق كل فئة فرعية. ببساطة يبدو هذا:

"DICT" هو عضو محمي (عام ولكن مع قيادة السطح)

class A(object):
    _dict = {}

    @classmethod
    def getdict(cls):
        return cls._dict

    @classmethod
    def setval(cls, name, val):
        cls._dict[name] = val

    @classmethod
    def addchild(cls, name):
        return type(name, (cls, ), { '_dict' : {} })

B = A.addchild('B')
A.setval(1, 5)

print A.getdict()
# prints: {1: 5}
# like expected

print B.getdict()
# prints: {}
# like expected

هذا يعمل تماما كما هو متوقع. السؤال الآن هو: لماذا لم يعد يعمل إذا أعلن السمة الخاصة:

الآن نفس الشيء مع "Dict" ينحض عضوًا خاصًا

class C(object):
    __dict = {}

    @classmethod
    def getdict(cls):
        return cls.__dict

    @classmethod
    def setval(cls, name, val):
        cls.__dict[name] = val

    @classmethod
    def addchild(cls, name):
        return type(name, (cls, ), { '__dict' : {} })

D = C.addchild('D')
C.setval(1, 5)

print C.getdict()
# prints: {1: 5}
# like expected

print D.getdict()
# prints: {1: 5}
# why!?

فجأة D, ، الفئة الفرعية من C, ، لديه نفس القيم في "dict" مثل فئة الفئة!؟

هل يمكن لأي شخص أن يكون لطيفًا وشرح لي ، ما سبب هذا؟ شكرا لك مقدما!

هل كانت مفيدة؟

المحلول

Phild ، كما تعلمون ، عند بادئة اسم السمة مع inderscore مزدوج __, ، مترجم Python التغييرات تلقائيًا (MANGLES) اسم السمة من __attribute ل _CLS__attribute, ، حيث CLS هو اسم الفصل.

ومع ذلك ، عندما تقول

return type(name, (cls, ), { '__dict' : {} })

المفاتيح في القاموس { '__dict' : {} } لا تحصل على مشوهة. __dict بقي على حاله.

وهكذا ينتهي الأمر مع كليهما D._C__dict و D.__dict:

(Pdb) dir(D)
['_C__dict', '__class__', '__delattr__', '__dict', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'addchild', 'getdict', 'setval']

D._C__dict يشير إلى سمة فئة C. لذلك عند الركض

C.setval(1, 5)

أنت تتغير D._C__dict إلى جانب C._C__dict. فهي واحدة ونفس الشيء.

نصائح أخرى

هنا الفصل في الوثائق حول سمات "الخاصة". وعلقت على تعريف الفصل لجعله أكثر وضوحًا:

class C(object):
    __dict = {} # This creates C.__dict__['_C__dict']

    @classmethod
    def getdict(cls):
        return cls.__dict # Uses cls.__dict__['_C__dict'] 

    @classmethod
    def setval(cls, name, val):
        cls.__dict[name] = val # Uses cls.__dict__['_C__dict'] 

    @classmethod
    def addchild(cls, name):
        return type(name, (cls, ), { '__dict' : {} }) # Creates child.__dict__['__dict']

أي كل الأطفال لديهم خاص بهم __dict سمة ، ولكن يتم استخدام واحد فقط من الفئة الأساسية.

لا تنطبق مفاهيم Java أو C ++ لـ "محمية" و "خاصة". يقوم Python بتسمية Python قليلاً ، ولكن ليس ما تتخيله.

ال __name هل بعض الأسماء يتدحرج ، مما يجعل من الصعب الوصول لأن الاسم محجب.

لك _dict و __dict هي ببساطة سمات على مستوى الفصل والتي تتقاسمها ببساطة جميع حالات الفصول.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top