Python __str__ และรายการ


108

ใน Java ถ้าฉันเรียก List.toString () มันจะเรียกเมธอด toString () โดยอัตโนมัติในแต่ละอ็อบเจกต์ภายในรายการ ตัวอย่างเช่นถ้ารายการของฉันมีวัตถุ o1, o2 และ o3 list.toString () จะมีลักษณะดังนี้:

"[" + o1.toString() + ", " + o2.toString() + ", " + o3.toString() + "]"

มีวิธีรับพฤติกรรมคล้ายกันใน Python หรือไม่? ฉันใช้เมธอด __str __ () ในคลาสของฉัน แต่เมื่อฉันพิมพ์รายการวัตถุโดยใช้:

print 'my list is %s'%(list)

ดูเหมือนว่า:

[<__main__.cell instance at 0x2a955e95f0>, <__main__.cell instance at 0x2a955e9638>, <__main__.cell instance at 0x2a955e9680>]

ฉันจะให้ python เรียก __str__ ของฉันโดยอัตโนมัติสำหรับแต่ละองค์ประกอบภายในรายการ (หรือ dict สำหรับเรื่องนั้น) ได้อย่างไร


สำหรับการอ้างอิงมีPEP 3140: "str (container) should call str (item), not repr (item)"ซึ่งถูกปฏิเสธ
Alexey

คำตอบ:


134

การเรียกสตริงในรายการ python เรียก__repr__เมธอดในแต่ละองค์ประกอบภายใน สำหรับบางรายการ__str__และ__repr__จะเหมือนกัน หากคุณต้องการพฤติกรรมนั้นให้ทำ:

def __str__(self):
    ...
def __repr__(self):
    return self.__str__()

7
การระบุ__str__ด้วย__repr__มักจะไม่เห็นด้วยกับโมเดลข้อมูล Pythonดังนั้นโซลูชันการทำความเข้าใจรายการที่เสนอโดย @ daniel-lew จึงเป็น pythonic มากกว่า
Ioannis Filippidis

2
ไม่มีข้อโต้แย้ง. ฉันตอบคำถามตามที่ถามซึ่งบ่อยครั้งที่ผู้มาใหม่ใน python ต้องการคิดถึงปัญหา แต่นั่นไม่ได้หมายความว่าเป็นวิธีที่ดีที่สุดในการตอบ
David Berger

1
Python ควรสอดคล้องกับแบบจำลองข้อมูลของตัวเองและทำสิ่งเดียวกันสำหรับ primitives และ aggregates ทั้งหมด
Terrence Brannon

2
ฉันคิดว่าพฤติกรรมเริ่มต้นสำหรับรายการ python นั้นผิดธรรมดา ฉันคาดหวังว่าstr()ในรายการที่ส่งคืนstr()สำหรับแต่ละองค์ประกอบภายใน
SuperGeo

21

คุณสามารถใช้การทำความเข้าใจรายการเพื่อสร้างรายการใหม่ด้วยแต่ละรายการ str () 'd โดยอัตโนมัติ:

print([str(item) for item in mylist])

6
หรือprint(map(str, mylist))สั้นกว่าหน่อย
anula

4
ปัญหาอย่างหนึ่งคือถ้ารายการใน mylist อาจเป็นรายการด้วย
Breandán Dalton

7

สองสิ่งง่ายๆที่คุณสามารถทำได้ใช้mapฟังก์ชันหรือใช้ความเข้าใจ

แต่นั่นทำให้คุณได้รับรายการสตริงไม่ใช่สตริง ดังนั้นคุณต้องเข้าร่วมสตริงด้วยกัน

s= ",".join( map( str, myList ) )

หรือ

s= ",".join( [ str(element) for element in myList ] )

จากนั้นคุณสามารถพิมพ์อ็อบเจ็กต์สตริงคอมโพสิตนี้

print 'my list is %s'%( s )

4

ขึ้นอยู่กับสิ่งที่คุณต้องการใช้ผลลัพธ์นั้นบางที__repr__อาจจะเหมาะสมกว่า:

import unittest

class A(object):
    def __init__(self, val):
        self.val = val

    def __repr__(self):
        return repr(self.val)

class Test(unittest.TestCase):
    def testMain(self):
        l = [A('a'), A('b')]
        self.assertEqual(repr(l), "['a', 'b']")

if __name__ == '__main__':
    unittest.main()

3

ฉันเห็นด้วยกับคำตอบก่อนหน้านี้เกี่ยวกับการใช้ความเข้าใจในรายการเพื่อทำสิ่งนี้ แต่คุณสามารถซ่อนสิ่งนั้นไว้เบื้องหลังฟังก์ชันได้อย่างแน่นอนหากนั่นคือสิ่งที่ลอยอยู่ในเรือของคุณ

def is_list(value):
    if type(value) in (list, tuple): return True
    return False

def list_str(value):
    if not is_list(value): return str(value)
    return [list_str(v) for v in value]

เพื่อความสนุกสนานฉันทำ list_str () ซ้ำ str () ทุกอย่างที่มีอยู่ในรายการ


+1 สิ่งนี้มีประโยชน์เมื่อใช้งาน__str__และ__repr__แยกกัน
vincent gravitas


0

ควรจะพอเพียง

เมื่อพิมพ์รายการเช่นเดียวกับคลาสคอนเทนเนอร์อื่น ๆ องค์ประกอบที่มีอยู่จะถูกพิมพ์โดยใช้__repr__เนื่องจาก__repr__มีไว้เพื่อใช้สำหรับการแสดงวัตถุภายใน ถ้าเราโทรไปhelp(object.__repr__)มันจะบอกเราว่า:

Help on wrapper_descriptor:

__repr__(self, /)
    Return repr(self).

และถ้าเราเรียกhelp(repr)มันจะส่งออก:

Help on built-in function repr in module builtins:

repr(obj, /)
    Return the canonical string representation of the object.

    For many object types, including most builtins, eval(repr(obj)) == obj.

หาก__str__ถูกนำไปใช้กับอ็อบเจ็กต์และ__repr__จะไม่แสดงrepr(obj)เอาต์พุตเริ่มต้นเช่นเดียวกับprint(obj)เมื่อไม่มีการใช้งานเหล่านี้

ดังนั้นวิธีเดียวคือนำไปใช้__repr__กับชั้นเรียนของคุณ วิธีหนึ่งที่ทำได้คือ:

class C:           
    def __str__(self):
        return str(f"{self.__class__.__name__} class str ")

C.__repr__=C.__str__       
ci = C()    


print(ci)       #C class str 
print(str(ci))  #C class str 
print(repr(ci)) #C class str 

-3

ผลลัพธ์ที่คุณได้รับเป็นเพียงชื่อโมดูลของออบเจ็กต์ชื่อคลาสและที่อยู่หน่วยความจำเป็นเลขฐานสิบหกเนื่องจาก__repr__ฟังก์ชันจะไม่ถูกแทนที่

__str__ใช้สำหรับการแสดงสตริงของอ็อบเจ็กต์เมื่อใช้การพิมพ์ แต่เนื่องจากคุณกำลังพิมพ์รายการของวัตถุและไม่ได้ทำซ้ำในรายการเพื่อเรียกใช้strวิธีการสำหรับแต่ละรายการจึงพิมพ์การแสดงวัตถุออกมา

ในการ__str__เรียกใช้ฟังก์ชันคุณจะต้องทำสิ่งนี้:

'my list is %s' % [str(x) for x in myList]

หากคุณแทนที่__repr__ฟังก์ชันคุณสามารถใช้วิธีการพิมพ์ได้เหมือนเดิม:

class cell:
    def __init__(self, id):
        self.id = id
    def __str__(self):
        return str(self.id) # Or whatever
    def __repr__(self):
        return str(self) # function invoked when you try and print the whole list.

myList = [cell(1), cell(2), cell(3)]
'my list is %s' % myList

จากนั้นคุณจะได้รับ " my list is [1, 2, 3]" เป็นผลลัพธ์ของคุณ


คำตอบนี้ดูเหมือนจะตอบคำถามที่ไม่เกี่ยวข้องกันเลย แน่ใจหรือว่าวางถูกที่แล้ว?
Blckknght

ใช่หน้านี้ที่ฉันต้องการให้คำตอบมีลิงก์ไปยังหน้านี้จากโพสต์อื่นดังนั้นจึงแนะนำฉันมาที่นี่และฉันตอบที่นี่โดยคิดว่าผู้ชายที่ตั้งคำถามจะมาที่นี่อีกครั้งและดูคำตอบของฉัน. ความไม่สะดวก !!!
panagiwtis koligas

หากคำถามอื่นถูกปิดเนื่องจากซ้ำกับคำถามนี้ก็ถือว่าคำตอบที่มีอยู่ที่นี่ควรดูแลคำถามอื่นอยู่แล้ว หากไม่เป็นเช่นนั้นคุณควรตั้งค่าสถานะเพื่อเปิดคำถามนั้นอีกครั้งแทนที่จะโพสต์คำตอบที่เข้าใจยากที่นี่ซึ่งจะถูกลบไปเกือบหมด ตอนนี้เป็นไปได้ที่คุณจะมีบางอย่างที่จะพูดซึ่งไม่ได้ครอบคลุมคำตอบอื่น ๆ อีก 8 ข้อที่นี่ แต่คุณต้องทำให้คำตอบของคุณมีความหมายในบริบทของหน้านี้เนื่องจากเป็นคำถามที่คุณกำลังตอบอยู่ และอย่าโพสต์คำตอบที่เหมือนกันสองคำ!
Blckknght

1
โอ้แม้ว่าตอนนี้ฉันจะดูอีกครั้ง แต่ดูเหมือนว่า @charliebeckwith ได้แก้ไขโพสต์ของคุณให้แตกต่างไปจากเดิมโดยสิ้นเชิงแทนที่จะโพสต์คำตอบของตัวเองด้วยเหตุผลที่อธิบายไม่ได้ นั่นไม่ใช่วิธีการแก้ไขโดยปกติ ...
Blckknght

@blckknght ฉันเริ่มแก้ไขมันก่อนที่ฉันจะรู้ว่าคำตอบคืออะไร อธิบายไม่ได้โดยสิ้นเชิงว่าทำไมฉันถึงไปต่อ
charliebeck กับ
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.