سؤال

إن ورث سمة الفصل من فئة سوبر وتغيير قيمة الفئة الفرعية لاحقًا يعمل بشكل جيد:

class Unit(object):
    value = 10

class Archer(Unit):
    pass

print Unit.value
print Archer.value

Archer.value = 5

print Unit.value
print Archer.value

يؤدي إلى الإخراج:
10
10
10
5
وهو أمر جيد تمامًا: يرث آرتشر القيمة من الوحدة ، لكن عندما أقوم بتغيير قيمة آرتشر ، تظل قيمة الوحدة دون مساس.

الآن ، إذا كانت القيمة الموروثة قائمة ، فإن تأثيرات النسخ الضحلة وتتأثر قيمة الفئة الفائقة أيضًا:

class Unit(object):
    listvalue = [10]

class Archer(Unit):
    pass

print Unit.listvalue
print Archer.listvalue

Archer.listvalue[0] = 5

print Unit.listvalue
print Archer.listvalue

انتاج:
10
10
5
5

هل هناك طريقة "لنسخ عميق" قائمة عند ورثها من الفئة الفائقة؟

شكرا جزيلا
سانو

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

المحلول

إنها ليست مسألة نسخ ضحلة أو عميقة ، إنها مسألة مراجع ومهام.

إنها الحالة الأولى Unit.value و Archer.value هما المتغيران الذي يشير إلى نفس القيمة. عندما تفعل Archer.value = 5, ، أنت تقوم بتعيين إشارة جديدة إلى acher.value.

لحل مشكلتك ، تحتاج إلى تعيين قيمة قائمة جديدة إلى Archer.list.

إذا كانت هذه القيم سيتم الوصول إليها فقط بواسطة طرق الفصل ، فإن أبسط الحلول هو القيام بالمهمة عند تهيئة الفئة.

نصائح أخرى

إجابة مايكل لطيفة وبسيطة ، ولكن إذا كنت ترغب في تجنب الاضطرار إلى إضافة هذا الخط إلى كل فئة فرعية للوحدة - ربما يكون لديك مجموعة من القوائم الأخرى مثل تلك ، فإن metaclass هي وسيلة سهلة لحل المشكلة

class UnitMeta(type):
    def __init__(self, *args):
        super(UnitMeta, self).__init__(*args)
        self.listvalue = [10]

class Unit(object):
    __metaclass__ = UnitMeta
    pass

class Archer(Unit):
    pass

print Unit.listvalue
print Archer.listvalue

Archer.listvalue[0] = 5

print Unit.listvalue
print Archer.listvalue

انتاج:

[10]
[10]
[10]
[5]

يمكنك أيضًا تمديد هذه الفكرة نفسها للعثور تلقائيًا ونسخ القوائم (والديكتات) المحددة في الوحدة

class UnitMeta(type):
    def __init__(self, *args):
        super(UnitMeta, self).__init__(*args)
        for superclass in self.__mro__:
            for k,v in vars(superclass).items():
                if isinstance(v, (list, dict, )):
                    setattr(self, k, type(v)(v))

class Unit(object):
    __metaclass__ = UnitMeta
    listvalue = [10]

class Archer(Unit):
    pass

يمكنك نسخ القائمة في تعريف Archer:

class Archer(Unit):
    listvalue = Unit.listvalue[:]
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top