如何在对象列表中使用str.join()

Ghi*_*ADJ 4 python

class A:
    def __init__(self, text):
        self.text = text

    def __repr__(self):
        return self.text

    def __str__(self):
        return self.text

    def __add__(self, other):
        return str(self) + other

    def __radd__(self, other):
        return other + str(self)
Run Code Online (Sandbox Code Playgroud)

我希望A对象列表与str.join() "可连接" .我应该采用哪种特殊方法来实现这一目标?

当然,我可以首先提取一个文本列表然后加入它,但这不是我想要的.

b = A('Hello')
c = A('World')
l = [b, c]

print b, c
print l
print b + ' ' + c
print ' '.join(l) # <- Error here

Hello World
[Hello, World]
Hello World
Traceback (most recent call last):
  File "sandbox.py", line 24, in <module>
    print ' '.join(l)
TypeError: sequence item 0: expected string, instance found
Run Code Online (Sandbox Code Playgroud)

che*_*ner 11

__str__仅在对象的用户想要将其转换为字符串时使用,而str.join不是.您必须strstr.join使用它们之前将对象显式转换为值.

(可能 str.join已被定义为隐式调用str它作为参数接收的iterable中的每个元素?当然.但事实并非如此.)

Python的一个原则是"明确比隐含更好".如果要str.join加入对象的字符串表示,请将对象传递strjoin.

print(' '.join(str(x) for x in l))
Run Code Online (Sandbox Code Playgroud)

唯一的方法是join将它们str隐含地视为对象,如果它们 str对象,也就是说if A是它的子类str.

class A(str):
    def __new__(cls, text):
        obj = super().__new__(cls, text)
        # Do whatever else you need to add to obj
        return obj

l = [A('hello'), A('world')]
print(' '.join(l))
Run Code Online (Sandbox Code Playgroud)

但要注意在不保证的情况下使用继承.

  • 仅仅为了这个微小的细节而子类化“str”几乎是多余的,并且可能会在可能使用该类的其他部分引起混乱。参见[spaghetti继承](http://www.catb.org/jargon/html/S/spaghetti-inheritance.html) (2认同)
  • 技术解释是现货."使'.join(l)工作的唯一方法是,如果A是str的子类." 并不意味着回答认为这是一个好主意. (2认同)