python %与format

本文详细解析了在Python 2.7中,Unicode和字符串混合使用时出现的UnicodeDecodeError错误原因及解决方案。通过对比%与format的不同行为,阐述了在不同数据类型混用场景下的处理策略。

python: 2.7.10
问题类似如下:

# en_name-->unicode
>>> en_name=u'zhongguo'
# cn_name-->str
>>> cn_name=u'中国'.encode('utf-8')
>>> """en_name: %s, cn_name: %s""" % (en_name, cn_name)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)

从上可知,当unicode,str同时存在时,报错了

解决思路
1.只有unicode或者str,会不会报错

>>> """en_name:%s""" % (en_name)
u'en_name:zhongguo'
>>> """cn_name:%s""" % (cn_name)
'cn_name:\xe4\xb8\xad\xe5\x9b\xbd'

没有报错,而且你会发现,当参数为unicode, 返回结果也是unicode,如果是str,结果就是str

2.如果包含了unicode和str,结果是什么类型呢?

>>> """en_name:%s, cn_name:%s""" % (en_name, 'zhongwenming')
u'en_name:zhongguo, cn_name:zhongwenming'

结果表明,是unicode类型

因此,我们猜测当参数既有unicode又有str,%到底发生了什么

"""en_name: %s, cn_name: %s""" % (en_name, cn_name)
将参数转换成unicode
1. unicode(en_name)   ---> pass
2. unicode(cn_name)   ---> fail 
报UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)

如果是这样的话,一切就解释的通了,
比如:
参数只有str类型的话,将每个参数str(params), 不会报错
参数只有unicode类型的话,将每个参数unicode(params), 也不会报错
只有混合使用的话,并且str中有非ASCII码时,就会报错


如果将% 替换为format就不会报错,这是为什么了?

>>> """en_name: {}, cn_name: {}""".format(en_name, cn_name)
'en_name: zhongguo, cn_name: \xe4\xb8\xad\xe5\x9b\xbd'

statement % params
statement.format(params)

这是因为format跟%不一样的地方,
format的返回类型与statement有关
%的返回类型与params有关

所以使用了format, statement是str类型,因此str()作用所有参数,没有报错

>>> u"""en_name: {}, cn_name: {}""".format(u'中国', u'中'.encode('utf-8'))
报错UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)

题外话:
1.为什么用%, 而不用format
项目是很老的项目,之前很多代码都使用了这种方式。所以很难说全部改掉这种用法

### Python 中 `%` 运算符的用法 #### 求模运算 在数值计算中,`%` 是求模运算符,用于返回两个整数相除后的余数。例如: ```python result = 10 % 3 # result 的值为 1 ``` 此操作广泛应用于判断奇偶性、实现循环队列等功能[^1]。 #### 字符串格式化 除了作为数学运算符外,在字符串处理方面,`%` 可以用于格式化字符串。它允许将变量嵌入到字符串模板中,从而动态生成所需的内容。基本语法如下: ```python formatted_string = format_specifier % values ``` 其中 `format_specifier` 定义了占位符及其对应的格式,而 `values` 则提供了实际的数据填充这些占位符。常见的占位符包括但不限于以下几种: - `%s`: 表示字符串类型的占位符; - `%d`, `%i`: 整型数据的占位符; - `%f`: 浮点数的占位符; 下面是一个简单的例子展示如何利用 `%` 来完成字符串格式化任务: ```python name = "Alice" age = 25 greeting = "Hello, my name is %s and I am %d years old." % (name, age) print(greeting) # 输出: Hello, my name is Alice and I am 25 years old. ``` 此外,还可以通过字典形式指定参数名称来进行更灵活的替换[^2]: ```python data = {'first': 'John', 'last': 'Doe'} output = "%(first)s %(last)s" % data print(output) # 输出 John Doe ``` 值得注意的是,尽管 `%` 风格的字符串格式化仍然有效并被许多开发者所熟悉,但在现代 Python 编程实践中推荐使用 `.format()` 方法或者 f-string(自 Python 3.6 开始支持),因为它们提供更加直观且功能丰富的接口[^4]。 ### 示例代码对比三种不同方式实现相同效果 以下是分别采用传统 `%` 方式、`.format()` 函数以及最新引入的 f-string 实现同样目标的例子: ```python # 使用 % percent_style = '%s is %d years old.' % ('Tom', 30) # 使用 .format() dot_format_style = '{} is {} years old.'.format('Jerry', 28) # 使用 f-string fstring_style = f'{name} is {age} years old.' print(percent_style) # Tom is 30 years old. print(dot_format_style) # Jerry is 28 years old. print(fstring_style) # Alice is 25 years old. ``` 以上每种方法都可以达到预期的结果,但是随着版本迭代进步,后者往往具备更好的可读性和扩展性[^5]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值