Python字符串插值和元组切片?

5

我正在使用Python 2.7,想了解Python字符串插值使用元组的原因。我在编写以下代码时遇到了TypeErrors

def show(self):
    self.score()
    print "Player has %s and total %d." % (self.player,self.player_total)
    print "Dealer has %s showing." % self.dealer[:2]

输出:

Player has ('diamond', 'ten', 'diamond', 'eight') and total 18
Traceback (most recent call last):
File "trial.py", line 43, in <module>
    Blackjack().player_options()
  File "trial.py", line 30, in player_options
    self.show()
  File "trial.py", line 27, in show
    print "Dealer has %s showing." % (self.dealer[:2])
TypeError: not all arguments converted during string formatting

我发现需要修改第四行代码,这是引起错误的地方,将其修改为:

print "Dealer has %s %s showing." % self.dealer[:2]

使用两个%s运算符,一个用于元组切片中的每个项目。当我检查这行代码时,我添加了一个print type(self.dealer[:2]),并得到以下输出:

<type 'tuple'> 

正如我所料,为什么像Player has %s and total %d." % (self.player,self.player_total)这样的未切片元组可以很好地格式化,而像self.dealer[:2]这样的切片元组却不行呢?它们都是相同类型的,为什么不能直接传递切片,而需要显式地格式化切片中的每个项呢?

3个回答

6

字符串插值需要为元组参数的每个元素指定格式代码。相反,您可以使用新的.format字符串方法:

>>> dealer = ('A','J','K')
>>> print 'Dealer has {} showing'.format(dealer[:2])
Dealer has ('A', 'J') showing

需要注意的是,如果只传入一个参数,会打印出元组的字符串表示形式,带有括号和逗号。可以使用元组解包将参数单独发送,但此时需要两个格式化占位符。

>>> print 'Dealer has {} {} showing'.format(*dealer[:2])
Dealer has A J showing

从Python 3.6开始,有f-字符串。可以将表达式放入花括号中:

>>> dealer = ('A','J','K')
>>> print(f'Dealer has {dealer[0]} {dealer[1]} showing')
Dealer has A J showing

你用.format做的这个是Python3中通常的方法,对吧? - tijko
2
是的,但它也被移植到 Python 2.6 及以上版本。早期版本(我相信是 3.0 和 2.6)不支持 {},而是使用{0}表示位置参数的放置。在新代码中,推荐使用.format - Mark Tolonen

5

这个切片没有问题。如果传递了元素数量不正确的元组文字,您将会得到相同的错误。

"Dealer has %s showing." % self.dealer[:2]

与以下内容等同:

"Dealer has %s showing." % (self.dealer[0], self.dealer[1])

显然,这是一个错误。 如果您想在不使用元组解包的情况下格式化self.dealer[:2]:
"Dealer has %s showing." % (self.dealer[:2],)

这很有道理,谢谢。我误解了正在发生的事情。我以为传递元组切片时是一个较小的整个元组,而不是传递两个单独的参数。这就是正在发生的事情,对吗? - tijko
2
你永远不会传递“两个单独的参数”。在语法上,“string”%(foo,bar)是一个包含%二进制运算符和两个文字操作数(字符串和元组)的表达式。即使在著名的Pythonic“a,b = b,a”中,您也要使用元组进行操作。字符串插值只是为字符串重载的%运算符。 - Eldar Abusalimov

3

您的错误源于第二个格式化操作中传入了不正确数量的参数。

"dealer has %s %s showing" % self.dealer[:2]

或者

"dealer has %s showing" % list(self.dealer[:2])

或者

"dealer has %s showing" % self.dealer[0] #or self.dealer[1]

这与不使用元组字面量无关。


1
当您首次发布时,涉及参数数量的'TypeError'错误以及您的评论时,我仍然没有意识到元组切片被分解为两个单独的参数而不是'整个'元组切片。当@Eldar Abusalimov发表评论时,我终于意识到了我的错误。 - tijko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接