استبدال طريقة __Str__ في كائن القائمة في بيثون
-
06-09-2019 - |
سؤال
هذا يبدو وكأنه يجب أن يكون بسيطا:
اريد list
مثل أي شيء آخر list
, ، إلا أنه لديه مختلفة .__str__
طريقة.
- محاولة لتحديد
object.__str__ = foo
النتائج في خطأ للقراءة فقط - محاولة الفرعية
list
يعني أنك بحاجة إلى بعض الطرق لتحويل القائمةlist
إلى مثيل الفئة الفرعية. هذا يتطلب إما نسخ جميع الصفات يدويا (ألم ضخم)، أو نسخها بطريقة أو بأخرى تلقائيا، والتي لا أعرف كيفية القيام به. - محاولة كتابة غلاف حول
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**