注明:以下均属于个人实验结果加上理解所得,如有错误请在评论区指出,谢谢!
话说回来,有那么一天,我在测试代码。突然,我惊讶的发现,我的代码有问题:
tuple_name = (1, 2, 3)
print("tuple_name:%s" % (tuple_name))
运行结果,会爆出下面这个大大的Error,还是个“TypeError”
TypeError:not all arguments converted during string formatting
那么先冷静的分析一下:
1、爆出的“Error” 说的是“TypeError”,“类型错误”。也就是说“%s”它不认为“tuple”是个字符串。
2、把“tuple”换成“list”,这个“Error”瞬间消失,而且还很乖乖的把“list”输出了。难道说“%s”和“list”有什么不可告人的秘密不成?
就在我百思不得其解的时候,突然手抖,在“(tuple_name)”的“tuple_name”后面多加了一个“,”,源码又变成这个样子:
tuple_name = (1, 2, 3)
print("tuple_name:%s" % (tuple_name,))
随之我又按下了F5。没想到它竟然输出了,还是输出了“tuple”,如下所示:
tuple_name:(1, 2, 3) # 运行结果
这个偶然make me陷入了沉思,这一切背后的真相究竟是什么呢?
首先,在这个问题上,忽略了一个非常本质的问题,“tuple”怎么定义的?
答:地球人都知道“tuple_name = (元素,元素,元素......)”。
那么,只有一个元素的“tuple”怎么定义的?
答:为了防止定义出来的变量不是“tuple”,只有一个元素时,必须在后面加上逗号。
也就是“tuple_name = (元素,)”。
好了,不卖关子了,直接下结论。
1、首先,“print("tuple_name:%s" % (tuple_name,))” 作为格式化输出,“%s”替代的是后面的“%”身后跟的括号里的东西。而地球人都知道,“()”除了“优先运算”,还可以用来定义“tuple”。所以,“%()”实际上是输出“%”后接的“tuple”内部的东西。
2、“()”除了定义“tuple”,还具有“优先运算”的功能。完成该功能后,“()”就相当于去掉一样。最典型的就是为什么“tuple”中只有一个元素时,一定一定要在元素后面加上一个逗号,否则,直接变成了整型数值或者浮点型数值或者字符串赋值语句了。
3、“print("tuple_name:%s" % (tuple_name,))”,首先跟“%”紧紧挨着的“()”,会生成一个只有一个元素的“tuple”,而这个元素就是“tuple_name”。因为“%s”它比较万能,不确定用什么的时候就用“%s”,“%s”是可以将这一个“tuple_name”全部输出的。就像用“%s”输出“list_name”一样。
4、而“print("tuple_name:%s" % (tuple_name))”,生成“tuple”跟第3点同理。但是,这对“()”突然发现你生成的“tuple”只有一个元素,而且后面没有逗号啊。于是(应该是Python内部机制的优先级),“()”又把功能换成了“优先运算”,也就是相当于什么都不做。“print("tuple_name:%s" % (tuple_name))”就转变成了“print("tuple_name:%s" % tuple_name)”。如果再把“tuple_name”用它原来的样子换掉:
①、如果“tuple_name = (1,)”,就变成了“print("tuple_name:%s" % (1,))”。“%s”一看,艾玛,大材小用,让我做“%d”应该干的活。于是就正常输出了一个“1”,而且“1”前后没有括号。
②、如果“tuple_name = (1, 2, 3)”,反而变成了“print("tuple_name:%s" % (1, 2, 3))”。“%s”表示一个人干三个人的活遭不住啊,还没有额外工资,于是就把“TypeError”叫过来,让他爆出“Error”,罢工。(因为一个“%s”输出三个值,替换的数目不匹配啊,所以才会爆出“TypeError”。才会说出那句经典的“not all arguments converted during string formatting”)。
于是乎,答案揭晓。
果然“tuple”和“%s”有着不可告人的秘密。“print”真亮,比太阳还亮!