سؤال

أنا حقا عالق على سبب حدة كتلة التعليمات البرمجية التالية 1 في الإخراج 1 بدلا من الإخراج 2؟

كتلة الكود 1:

class FruitContainer:
       def __init__(self,arr=[]):
           self.array = arr
       def addTo(self,something):
           self.array.append(something)
       def __str__(self):
           ret = "["
           for item in self.array:
               ret = "%s%s," % (ret,item)
           return "%s]" % ret

arrayOfFruit = ['apple', 'banana', 'pear']
arrayOfFruitContainers = []

while len(arrayOfFruit) > 0:
   tempFruit = arrayOfFruit.pop(0)
   tempB = FruitContainer()
   tempB.addTo(tempFruit)
   arrayOfFruitContainers.append(tempB)

for container in arrayOfFruitContainers:
   print container 

**Output 1 (actual):**
[apple,banana,pear,]
[apple,banana,pear,]
[apple,banana,pear,]

**Output 2 (desired):**
[apple,]
[banana,]
[pear,]

الهدف من هذا الرمز هو التكرار من خلال صفيف ولف كل في كائن أحد الوالدين. هذا هو تخفيض الكود الفعلي الذي يضيف جميع التفاح إلى كيس من التفاح وما إلى ذلك. تخميني هو ذلك، لسبب ما، إما استخدام نفس الكائن أو التمثيل كما لو كانت حاوية الفاكهة تستخدم صفيف ثابتة. ليس لدي أي فكرة عن كيفية إصلاح هذه.

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

المحلول

يحتوي الكود الخاص بك على وسيطة افتراضية لتهيئة الفصل. يتم تقييم قيمة الوسيطة الافتراضية مرة واحدة، في وقت ترجمة، لذلك يتم تهيئة كل مثيل مع نفس القائمة. تغييره مثل ذلك:

def __init__(self, arr=None):
    if arr is None:
        self.array = []
    else:
        self.array = arr

ناقشت هذا أكثر اكتمالا هنا: كيفية تحديد فئة في بيثون

نصائح أخرى

يجب ألا تستخدم قيمة قابلة للتغيير (مثل []) للوسيطة الافتراضية بطريقة. يتم حساب القيمة مرة واحدة، ثم تستخدم لكل الاحتجاج. عند استخدام قائمة فارغة كقيمة افتراضية، يتم استخدام نفس القائمة في كل مرة يتم فيها استدعاء الأسلوب بدون الوسيطة، حتى مع تعديل القيمة بواسطة مكالمات الدالة السابقة.

القيام بذلك بدلا من ذلك:

def __init__(self,arr=None):
    self.array = arr or []

كما يقول NED، المشكلة هي أنك تستخدم قائمة كوسيطة افتراضية. هناك مزيد من التفاصيل هنا. وبعد الحل هو التغيير __init__ وظيفة على النحو التالي:

       def __init__(self,arr=None):
           if arr is not None:
               self.array = arr
           else:
               self.array = []

حلا أفضل من النجاح في أي شيء - في هذا المثال بالذات، وليس بشكل عام - هو علاج معلمة ARR إلى __init__ كمجموعة مضمنة من العناصر إلى التهيئة مسبقا من fruitcontainer مع، بدلا من صفيف لاستخدامها للتخزين الداخلي:

class FruitContainer:
  def __init__(self, arr=()):
    self.array = list(arr)
  ...

سيسمح لك ذلك بالمرور في أنواع أخرى غير قابلة للتنفيذ لتهيئة الحاوية الخاصة بك، مما يتوقع مستخدمي Python الأكثر تقدما أن يكونوا قادرين على القيام به:

myFruit = ('apple', 'pear') # Pass a tuple
myFruitContainer = FruitContainer(myFruit)
myOtherFruit = file('fruitFile', 'r') # Pass a file
myOtherFruitContainer = FruitContainer(myOtherFruit)

سوف نوفده أيضا علة التعرجات المحتملة الأخرى:

myFruit = ['apple', 'pear']
myFruitContainer1 = FruitContainer(myFruit)
myFruitContainer2 = FruitContainer(myFruit)
myFruitContainer1.addTo('banana')
'banana' in str(myFruitContainer2)

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

ملحوظة: هذا النهج ليس كذلك دائما الجواب الصحيح: "إن لم يكن بلا" أفضل في حالات أخرى. فقط اسأل نفسك: هل أتخلى عن مجموعة من الأشياء، أو حاوية قابلة للتغيير؟ إذا كانت الفئة / الوظيفة التي أجرتها كائناتي لتغيير تخزين التخزين، فهل ستكون (أ) مفاجأة أو (ب) مرغوب فيه؟ في هذه الحالة، سأجادل بأنه (أ)؛ وبالتالي، فإن القائمة (...) مكالمة هي أفضل حل. إذا كان (ب)، "إن لم يكن بلا" سيكون النهج الصحيح.

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