استبدال طريقة __Str__ في كائن القائمة في بيثون

StackOverflow https://stackoverflow.com/questions/931699

  •  06-09-2019
  •  | 
  •  

سؤال

هذا يبدو وكأنه يجب أن يكون بسيطا:

اريد list مثل أي شيء آخر list, ، إلا أنه لديه مختلفة .__str__ طريقة.

  1. محاولة لتحديد object.__str__ = foo النتائج في خطأ للقراءة فقط
  2. محاولة الفرعية list يعني أنك بحاجة إلى بعض الطرق لتحويل القائمة list إلى مثيل الفئة الفرعية. هذا يتطلب إما نسخ جميع الصفات يدويا (ألم ضخم)، أو نسخها بطريقة أو بأخرى تلقائيا، والتي لا أعرف كيفية القيام به.
  3. محاولة كتابة غلاف حول list كائن يعني أنه لا بد لي من معرفة بعض الطرق لإرسال جميع الرسائل إلى كائن ملفوف باستثناء .__str__ التي تعامل مع طريقتي الخاصة. لا أعرف كيفية القيام بذلك.

أي بدائل أو حلول # 2 أو # 3 محل تقدير كبير. شكرا!

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

المحلول

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

class myList(list):
    def __new__(cls, data=None):
        obj = super(myList, cls).__new__(cls, data)
        return obj

    def __str__(self):
        return 'myList(%s)' % list(self)

    def __add__(self, other):
        return myList(list(self) + list(other))

>>> l = myList(range(5))
>>> print l
myList([0, 1, 2, 3, 4])
>>> print l + [1, 2]
myList([0, 1, 2, 3, 4, 1, 2])
>>> l.sort()
>>> print l
myList([0, 1, 2, 3, 4])

نصائح أخرى

إذا كنت ترغب في تجاوز __str__ للحاويات الأخرى (على سبيل المثال، tuple)، يمكنك الاستفادة من الميراث المتعدد:

class PrettyStr(object):
    def __str__(self):
        ret = ''

        if isinstance(self, (list, tuple)):
            ret = ''.join(str(elem) for elem in self)
        else:
            pass  # handle other types here

        return ret


class MyList(PrettyStr, list):
    pass


class MyTuple(PrettyStr, tuple):
    pass


if __name__ == "__main__":
    print MyList([1, 2, 3, 4])
    print MyTuple((1, 2, 3, 4))

يمكنك تمديد فئة القائمة وتجاوزها:

class myList(list):
  def __str__(self):
    # do something
    return "something"

تحرير: إزالة جزء غير صحيح من الإجابة التي اقترح استبدال ديناميكيا __str__ في كائن القائمة، غير مسموح به في تنفيذ قوائم Python.

أنا مبرمج Java لكنني أعتقد أن هذا هو ما تريد (اختباره مع بيثون 2.6):

>>> class myList(list):
...   def __str__(self):
...     return "aaa"
...
>>> def myListWrapper(list):
...   return myList(list)
...
>>> a = [1, 2, 3]
>>> type(a)
<type 'list'>
>>> b = myListWrapper(a)
>>> type(b)
<class '__main__.myList'>
>>> print(a)
[1, 2, 3]
>>> print(b)
aaa
class MyList(list):
     def __str__(self):
             return "foo"

str(MyList([1, 2, 3]))

"فو"

str(MyList(list([1, 2, 3])))

"فو"

تعليقاتي السابقة كإجابة. كما ترون أن قائمة إعلانات تقبل أي تسلسل في منشئها.

الذي يرفع السؤال: لماذا تريد تجاوز طريقة __str__؟

لن يكون من الأفضل إنشاء فئة لتغليف كائنك؟

class MyContainer(object):
    def __init__(self, list):
        self.containedList = list

    def __str__(self):
        print('All hail Python')

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

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

ماذا عن لف القائمة؟

>>> class StrList(object):
    def __init__(self, data=None):
        self._data = data or []
    def __str__(self):
        return "StrList!"
    def __getattr__(self, attr):
        if attr == "_data":
            return self.__dict__[attr]
        return getattr(self._data, attr)
    def __setattr__(self, key, val):
        if key == "_data":
            self.__dict__[key] = val
        else:
            setattr(self._data, key, val)
    def __getitem__(self, index):
        return self._data[index]
    def __setitem__(self, index, value):
        self._data[index] = value


>>> l = StrList(range(3))
>>> print l
StrList!
>>> l[0]
0
>>> for x in l:
    print x


0
1
2
>>> l[0] = "spam"
>>> l.append("egg")
>>> print list(l)
['spam', 1, 2, 'egg']
>>> 
Ex = ["a", 2, 4] #our_list
Ex(-1) = "xuxu_beleza" #the_name_of_your_list(index) = new_item 
Print(Ex) 
["a", 2, "xuxu_beleza"] #our_new_list

**list[index] = new_item**
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top