1
2
3
4
5
6
7
作者:李晓辉

联系方式:

1. 微信:Lxh_Chat

2. 邮箱:939958092@qq.com
  1. Python 系列(一) 从零开始认识 Python,入门其实没那么难
  2. Python 系列(二) 学 Python 的第一步,把开发环境搭建好
  3. Python 系列(三) 基础语法避坑指南,缩进、大小写、续行与注释
  4. Python 系列(四) Python 输入输出详解,print()、input() 与常见避坑指南
  5. Python 系列(五) 数值类型与运算符详解,整除、浮点精度与进制转换实战
  6. Python 系列(六) 字符串处理实战,查找、替换、切片与日志分析
  7. Python 系列(七) 类型转换详解,int()、float()、str() 与金额计算避坑
  8. Python 系列(八) Python 流程控制入门,掌握 if、elif 和 else
  9. Python 系列(九) Python 逻辑运算符详解,and、or、not 一篇搞懂
  10. Python 系列(十) while、for 循环实战,彻底搞懂 range、break 与 continue

为什么 int("98.76") 会报错,而 int(98.76) 却可以?为什么 input() 拿到的数字必须先转换成 int 才能相加?为什么金额计算时,不能简单地使用 float 计算,再用 str() 转成字符串输出?

这些问题看起来很基础,却是 Python 初学者经常遇到的坑。在处理用户输入、读取配置文件、分析日志以及编写 Linux 运维脚本时,类型转换几乎无处不在。

上一篇我们学习了字符串的创建、常用方法和切片操作。现在,程序已经能够处理文本了,接下来就要解决一个重要问题:如何将字符串转换成数字,又如何将数字转换成字符串?

这篇文章将从基础规则讲起,结合实际代码和运维场景,把 Python 的数值与字符串类型转换讲清楚。

为什么需要类型转换?

先看一个简单的例子。

1
2
3
4
a = input("请输入第一个整数:")
b = input("请输入第二个整数:")

print(a + b)

运行程序,输入两个数字:

1
2
3
请输入第一个整数:10
请输入第二个整数:20
1020

咦?输入的是 10 和 20,为什么结果不是 30,而是 1020?

原因就在于 input() 的返回值。

input() 始终返回字符串。 即使用户输入的是数字,Python 也不会自动将它转换成整数。

可以通过 type() 查看变量的类型:

1
2
3
4
a = input("请输入一个数字:")

print(a)
print(type(a))

输入 10 后,输出如下:

1
2
3
请输入一个数字:10
10
<class 'str'>

这里的 10 实际上是字符串 "10",不是整数 10。

对于字符串,+ 运算符表示拼接,因此:

1
print("10" + "20")

输出:

1
1020

如果需要进行数学运算,就必须先将字符串转换为数值。

1
2
3
4
a = int(input("请输入第一个整数:"))
b = int(input("请输入第二个整数:"))

print(a + b)

运行结果:

1
2
3
请输入第一个整数:10
请输入第二个整数:20
30

这就是类型转换最常见的应用场景。

需要注意的是,Python 是强类型、动态类型语言。强类型意味着不同类型的数据不会在所有运算中自动进行隐式转换;动态类型则意味着变量不需要提前声明固定的数据类型。

例如,整数和浮点数可以直接相加:

1
print(3 + 2.5)

输出:

1
5.5

但是整数和字符串不能直接相加:

1
print(3 + "2")

会抛出 TypeError。

1
2
3
4
5
Traceback (most recent call last):
File "<python-input-87>", line 1, in <module>
print(3 + "2")
~~^~~~~
TypeError: unsupported operand type(s) for +: 'int' and 'str'

因此,编写程序时,不仅要关注变量的值,还要关注变量的类型。

Python 常用类型转换函数

先认识一下常用的转换函数。

函数作用示例
int()转换为整数int("123")
float()转换为浮点数float("12.5")
str()转换为字符串str(123)
bool()转换为布尔值bool(1)
chr()将整数码点转换为字符chr(65)
ord()获取单个字符的 Unicode 码点ord("A")
bin()将整数转换为二进制字符串bin(10)
oct()将整数转换为八进制字符串oct(10)
hex()将整数转换为十六进制字符串hex(255)

这些函数中,int()、float()、str() 等既可以用于类型转换,也可以看作对应类型的构造器。

接下来逐一学习它们的用法和注意事项。

字符串转换为整数

使用 int() 转换整数

如果字符串表示一个合法的整数,就可以使用 int() 转换。

1
2
3
4
5
number = int("123")

print(number)
print(type(number))
print(number + 10)

输出:

1
2
3
123
<class 'int'>
133

转换之后,变量 number 的类型就变成了 int,可以参与整数运算。

这在运维脚本中非常常见。例如,从用户输入中读取服务器数量、端口号或重试次数,都可能需要将字符串转换为整数。

1
2
3
server_count = int(input("请输入服务器数量:"))

print("需要检查的服务器数量:", server_count)

不过,这段代码有一个前提:用户必须输入合法的整数。如果输入 abc 或 12.5,转换就会失败。

为什么 int(“98.76”) 会报错?

看下面两段代码:

1
2
print(int(98.76))
print(int("98.76"))

第一行输出:

1
98

第二行则会抛出:

1
2
3
4
5
Traceback (most recent call last):
File "<python-input-100>", line 2, in <module>
print(int("98.76"))
~~~^^^^^^^^^
ValueError: invalid literal for int() with base 10: '98.76'

为什么会有这样的区别?

因为 int() 对不同类型的参数采用不同的转换规则。

  • int(98.76):参数本身是浮点数,转换时会舍弃小数部分。
  • int("98.76"):参数是字符串,而 "98.76" 并不是合法的整数形式,因此转换失败。

如果确实需要把带小数的字符串转换为整数,可以先转换为浮点数,再转换为整数:

1
2
3
number = int(float("98.76"))

print(number)

输出:

1
98

但这里有一个容易忽略的细节:浮点数转整数是向零截断,不是四舍五入。

1
2
3
print(int(98.76))
print(int(-98.76))
print(int(98.99))

输出:

1
2
3
98
-98
98

如果需要四舍五入,可以考虑 round(),但要注意 Python 对恰好位于两个整数中间的数采用“舍入到偶数”的规则。

1
2
3
print(round(98.6))
print(round(98.5))
print(round(99.5))

输出:

1
2
3
99
98
100

所以,int()、round() 和直接转换字符串是三种不同的操作,不要混淆。

字符串转换为浮点数

如果输入的数据包含小数,可以使用 float()。

1
2
3
4
5
6
price = float("19.9")
temperature = float("36.5")

print(price)
print(temperature)
print(type(price))

输出:

1
2
3
19.9
36.5
<class 'float'>

float() 可以处理整数形式的字符串,也可以处理带小数点的字符串。

1
2
3
print(float("100"))
print(float("12.5"))
print(float("-3.14"))

输出:

1
2
3
100.0
12.5
-3.14

它还可以处理科学计数法:

1
2
print(float("1.5e3"))
print(float("2.5e-2"))

输出:

1
2
1500.0
0.025

在 Linux 运维场景中,读取 CPU 使用率、内存使用率、响应时间等数据时,经常需要将文本转换为数值,以便进一步计算。

例如:

1
2
3
4
5
cpu_usage = float("78.5")
memory_usage = float("63.2")

print("CPU 使用率:", cpu_usage, "%")
print("内存使用率:", memory_usage, "%")

但是,float() 也不是万能的。

1
float("hello")

会抛出 ValueError,因为 "hello" 不是合法的浮点数表示。

1
2
3
4
5
Traceback (most recent call last):
File "<python-input-111>", line 1, in <module>
float("hello")
~~~~~^^^^^^^^^
ValueError: could not convert string to float: 'hello'

另外,浮点数在计算机内部通常使用二进制浮点格式表示,并不是所有十进制小数都能被精确表示。金额计算时尤其需要注意这一点,后面会专门介绍。

指定进制转换为整数

除了十进制,计算机中还经常使用二进制、八进制和十六进制。

Python 的 int() 可以通过第二个参数指定输入字符串的进制。

1
2
3
4
print(int("101", 2))
print(int("101", 8))
print(int("101", 10))
print(int("101", 16))

输出:

1
2
3
4
5
65
101
257

这四个结果为什么不同?

因为同样的字符 "101",在不同进制下代表不同的数值:

  • 二进制 101:(1 \times 2^2 + 0 \times 2^1 + 1 \times 2^0 = 5)
  • 八进制 101:(1 \times 8^2 + 0 \times 8^1 + 1 \times 8^0 = 65)
  • 十进制 101:数值就是 101。
  • 十六进制 101:(1 \times 16^2 + 0 \times 16^1 + 1 \times 16^0 = 257)

如果输入的字符串不符合指定进制的规则,就会转换失败。

1
print(int("123", 2))

运行后会抛出 ValueError,因为二进制只能使用 0 和 1,不能出现 2 或 3。

1
2
3
4
5
Traceback (most recent call last):
File "<python-input-115>", line 1, in <module>
print(int("123", 2))
~~~^^^^^^^^^^
ValueError: invalid literal for int() with base 2: '123'

在 Linux 运维中,这种转换可以用于分析十六进制掩码、处理协议字段,或者解析以特定进制保存的配置值。

例如:

1
2
3
4
5
6
hex_string = "ff"

number = int(hex_string, 16)

print(number)
print(number + 1)

输出:

1
2
255
256

这里的 "ff" 是十六进制字符串,转换成整数后才可以正常参与数学运算。

数字转换为字符串

使用 str() 转换

当需要将数字与文本拼接、生成日志或输出格式化内容时,可以使用 str()。

1
2
3
4
5
6
7
number = 123

text = str(number)

print(text)
print(type(text))
print("服务器数量:" + text)

输出:

1
2
3
123
<class 'str'>
服务器数量:123

需要注意的是,str() 只是将对象转换为字符串表示,并不会改变原对象本身的类型。

1
2
3
4
5
6
number = 123

text = str(number)

print(type(number))
print(type(text))

输出:

1
2
<class 'int'>
<class 'str'>

变量 number 仍然是整数,变量 text 才是字符串。

实际开发中,如果只是输出内容,通常不需要手动调用 str()。print() 可以接收多个参数,而 f-string 可以更方便地将数值嵌入文本中。

1
2
3
4
server_count = 20

print("服务器数量:", server_count)
print(f"服务器数量:{server_count}")

这两种写法都可以输出服务器数量。

将整数转换为二进制、八进制和十六进制字符串

Python 提供了三个常用函数:

1
2
3
4
5
number = 255

print(bin(number))
print(oct(number))
print(hex(number))

输出:

1
2
3
0b11111111
0o377
0xff

注意,这三个函数返回的都是字符串。

它们的前缀分别表示:

  • 0b:二进制。
  • 0o:八进制。
  • 0x:十六进制。

如果不希望显示前缀,可以使用格式化语法:

1
2
3
4
5
6
number = 255

print(format(number, "b"))
print(format(number, "o"))
print(format(number, "x"))
print(format(number, "X"))

输出:

1
2
3
4
11111111
377
ff
FF

其中,x 输出小写十六进制字母,X 输出大写字母。

这种方式在日志输出、调试位掩码以及查看二进制数据时很有用。

字符与整数之间的转换

Python 还提供了 ord() 和 chr(),用于字符与 Unicode 码点之间的转换。

1
2
print(ord("A"))
print(chr(65))

输出:

1
2
65
A

ord() 用于获取单个字符的 Unicode 码点,chr() 则将合法的 Unicode 码点转换为对应字符。

再看一个例子:

1
2
print(ord("中"))
print(chr(20013))

输出:

1
2
20013
中

需要注意,ord() 接收的是长度为 1 的字符串,而不是任意长度的字符串。

1
print(ord("AB"))

这会抛出 TypeError。

1
2
3
4
5
Traceback (most recent call last):
File "<python-input-130>", line 1, in <module>
print(ord("AB"))
~~~^^^^^^
TypeError: ord() expected a character, but string of length 2 found

另外,ord() 获取的是 Unicode 码点,并不等于字符在 UTF-8 编码中的字节值。处理字符编码时,需要区分字符、码点和字节这几个概念。

转换失败怎么办?使用异常处理

前面已经多次看到,类型转换并不总是成功。

例如:

1
int("hello")

会抛出 ValueError。

1
2
3
4
5
Traceback (most recent call last):
File "<python-input-132>", line 1, in <module>
int("hello")
~~~^^^^^^^^^
ValueError: invalid literal for int() with base 10: 'hello'

如果程序没有处理这个异常,运行就可能中断。因此,在读取用户输入、配置文件或外部接口数据时,应该考虑转换失败的情况。

使用 try-except 捕获异常

1
2
3
4
5
try:
age = int(input("请输入年龄:"))
print(f"你的年龄是:{age}")
except ValueError:
print("输入错误,请输入有效的整数。")

当用户输入合法整数时,程序正常执行;如果输入 abc、18.5 或空字符串,就会进入 except 分支,提示用户重新检查输入。

这里捕获的是 ValueError,因为这些输入的问题在于无法按照整数规则完成转换。

不过,这段代码只会提示错误,不会自动要求用户再次输入。如果希望用户一直输入,直到获得合法结果,可以使用循环。

循环校验,直到输入合法

下面模拟一个简单的工号输入场景:工号必须是正整数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
while True:
try:
raw = input("请输入工号,必须是正整数:")
emp_id = int(raw)

if emp_id <= 0:
raise ValueError("工号必须大于 0")

break

except ValueError:
print("工号格式错误,请重新输入。")

print(f"工号录入成功:{emp_id}")

这里有几个值得注意的地方:

  • input() 先获取字符串。
  • int(raw) 尝试将字符串转换为整数。
  • emp_id <= 0 用于检查业务规则。
  • 如果输入不合法,就通过 raise ValueError 主动抛出异常。
  • break 只有在输入通过校验后才会执行。

要特别注意,能够成功转换,不代表输入一定符合业务要求。

例如,int("-10") 可以成功,但如果工号必须为正数,仍然应该拒绝这个值。

在生产脚本中,除了数据类型,还要校验取值范围、必填条件和业务规则。

金额计算为什么不建议直接使用 float?

来看一个常见的购物场景。

1
2
3
4
5
6
price = float(input("请输入商品价格:"))
quantity = int(input("请输入购买数量:"))

total = price * quantity

print("总价:", total)

输入价格 19.9,购买数量 3,结果可能是:

1
2
3
请输入商品价格:19.9
请输入购买数量:3
总价: 59.699999999999996

为什么不是 59.7?

这是因为 float 通常采用 IEEE 754 二进制浮点数表示。像 19.9 这样的十进制小数,无法被二进制浮点格式精确表示,因此计算结果可能出现微小误差。

这并不意味着 float 不好用。它非常适合许多数值计算,例如测量数据、科学计算和性能指标分析。

但对于金额这类需要严格控制十进制精度的业务,通常更适合使用 decimal.Decimal。

使用 Decimal 进行金额计算

1
2
3
4
5
6
7
8
from decimal import Decimal

price = Decimal(input("请输入商品价格:"))
quantity = int(input("请输入购买数量:"))

total = price * quantity

print(f"总价:{total:.2f}")

输入:

1
2
请输入商品价格:19.9
请输入购买数量:3

输出:

1
总价:59.70

这里有两个关键点。

第一,使用 Decimal 处理金额时,应该优先从字符串构造:

1
2
3
from decimal import Decimal

print(Decimal("0.1") + Decimal("0.2"))

输出:

1
0.3

不要先将十进制小数转换成 float,再传给 Decimal:

1
2
3
from decimal import Decimal

print(Decimal(0.1))

输出:

1
0.1000000000000000055511151231257827021181583404541015625

这种写法会保留浮点数 0.1 的实际二进制近似值,因此得到的结果可能包含许多额外的小数位。

第二,{total:.2f} 表示以两位小数的格式输出。这主要是输出格式控制,并不意味着所有业务计算都已经自动完成了金额舍入。

如果业务要求每一步都按特定规则舍入,例如按照分进行结算,就需要明确规定舍入时机和舍入方式,并使用 Decimal.quantize() 等方法实现。

记住:金额计算不仅要考虑数据类型,还要考虑精度、舍入规则和业务要求。

类型转换在 Linux 运维中的应用

类型转换不仅是入门语法,也是编写自动化运维脚本的基础。

假设你从配置文件或命令输出中获取了 CPU 使用率:

1
2
3
4
5
6
cpu_usage = "78.5"

if float(cpu_usage) > 80:
print("CPU 使用率过高,请检查服务器。")
else:
print("CPU 使用率正常。")

由于 cpu_usage 是字符串,必须先转换为浮点数,才能与数值 80 进行比较。

再看一个内存容量计算的例子:

1
2
3
4
5
6
7
8
9
memory_total = "16384"
memory_used = "12288"

total = int(memory_total)
used = int(memory_used)

usage = used / total * 100

print(f"内存使用率:{usage:.2f}%")

输出:

1
内存使用率:75.00%

这个例子中,两个变量最初都是字符串。转换成整数后,程序才能执行除法和乘法计算。

不过,真实的 Linux 命令输出通常包含单位、表头或其他文本。例如,free -h 会输出带有 Gi、Mi 等单位的容量,不能简单地对整行文本调用 int()。实际编写脚本时,还需要先解析出目标字段,再根据单位转换数值。

同样,从日志中提取的响应时间、从 API 返回的数值字段,以及从环境变量读取的端口号,都需要根据实际数据格式进行类型转换和校验。

可以用下面的流程理解整个过程:

flowchart TD
    A["用户输入 / 配置文件 / 日志"] --> B["获取原始字符串"]
    B --> C{"需要数值运算吗?"}
    C -->|否| D["保留字符串"]
    C -->|是| E["使用 int() / float() / Decimal()"]
    E --> F{"转换成功吗?"}
    F -->|是| G["检查业务规则和取值范围"]
    F -->|否| H["捕获异常并提示或记录错误"]
    G --> I{"校验通过吗?"}
    I -->|是| J["执行计算"]
    I -->|否| H
    J --> K["格式化输出或写入日志"]

这个流程不仅适用于 Python 初学练习,也适用于实际的运维自动化程序。

综合练习:安全的数值输入与输出

最后,写一个综合示例,将前面学到的知识串起来。

要求:

  • 提示用户输入一个整数。
  • 将输入转换为整数,并计算加 10 的结果。
  • 输出二进制、八进制和十六进制表示。
  • 捕获非法输入,避免程序直接中断。

参考代码:

1
2
3
4
5
6
7
8
9
10
11
12
try:
raw = input("请输入一个整数:")
num = int(raw)

print("原值 + 10 =", num + 10)
print("二进制:", bin(num))
print("八进制:", oct(num))
print("十六进制:", hex(num))
print("字符串形式:", str(num))

except ValueError:
print("输入无效,请输入合法整数。")

输入:

1
请输入一个整数:255

输出:

1
2
3
4
5
原值 + 10 = 265
二进制: 0b11111111
八进制: 0o377
十六进制: 0xff
字符串形式: 255

如果输入 hello,程序不会直接因为 ValueError 而终止,而是输出:

1
输入无效,请输入合法整数。

你可以继续尝试输入 -10、0、12.5 和空字符串,观察不同输入的处理结果。

写在最后

这一篇我们学习了 Python 数值与字符串之间的转换规则。

需要重点掌握的内容有:

  • input() 始终返回字符串,数学运算前要根据需要转换类型。
  • int() 可以转换合法整数形式的字符串,也可以将浮点数向零截断为整数;int("98.76") 则会报错。
  • float() 可以转换合法的浮点数字符串,但要注意二进制浮点数的精度问题。
  • str() 可以将数值转换为字符串,但不会改变原变量的类型。
  • int(x, base) 可以将指定进制的字符串转换为整数,bin()、oct() 和 hex() 可以将整数转换为相应进制的字符串。
  • ord() 和 chr() 用于 Unicode 字符与码点之间的转换。
  • 使用 try-except 处理非法输入,并进一步检查业务规则和取值范围。
  • 金额计算优先考虑 Decimal,从字符串构造,并明确舍入规则。

类型转换看起来只是几行代码,却决定了程序能否正确处理真实数据。 尤其是在 Linux 运维自动化中,用户输入、命令输出、配置文件和 API 数据往往都是以文本形式进入程序。先理解数据类型,再进行转换、校验和计算,才能写出更加可靠的 Python 脚本。