☰
Python基础之数据类型的转换详解(int/str/list等互转)
2026/10/13 3:31:10 网站建设 项目流程

前言


Python 是动态类型语言,变量本身没有类型,类型属于它指向的对象。数据类型转换(type conversion)分两类:一类是显式转换,用int()、str()、list()这类构造器主动把对象转成另一种类型;另一类是隐式转换,比如1 + 1.0里整数会被自动提升为浮点数,但这类隐式提升只在数值类型之间发生,字符串和数字之间不会自动转换。


初学者最容易踩的误解有两个。第一,以为int("12.5")能得到12——实际上它会直接抛ValueError,int()只认整数字符串。第二,以为list("abc")是把整个字符串当成一个元素放进列表——实际上它会把字符串拆成单个字符,得到['a', 'b', 'c'],同理list()用在任何可迭代对象上都是「消费其元素」,而不是「包一层」。


还有一个反直觉的点:str()并不等于「把值转成人类可读的文本」这件事没有代价,对列表、字典这类容器,str()得到的是repr风格的表示,里面带引号和括号,它不是JSON,eval回去也不是推荐的解析方式。本文把常用类型之间的互转、转换规则和边界条件讲清楚。


一、三大构造器:int / float / str


这三个构造器的签名和边界要记准:




写法结果说明



int("123")123默认按十进制解析

int(" -12_345 ")-12345允许前后空白、正负号、数字间单个下划线

int("FACE", 16)64206第二个参数是进制,取值 0 或 2~36

int(123.45)123浮点转整数向零截断,不是四舍五入

float("3.14")3.14接受十进制、科学计数法、inf、nan等

str(42)"42"调用对象的__str__



int()的进制参数是位置参数,int("01110011", base=2)也可以写成关键字形式,结果都是115。当base=0时,字符串按代码里的字面量规则解析,前缀决定进制:int("0x1f", 0)是31,int("0b101", 0)是5。


注意int()的截断方向和round()完全不同:


# 适用于 Python 3.8+
print(int(2.9)) # 2 —— 向零截断
print(int(-2.9)) # -2 —— 也是向零,不是向下取整
print(round(2.5)) # 2 —— 银行家舍入,.5 取偶

二、字符串与容器互转


字符串到列表有两条完全不同的路,选错了结果差很远:


# 适用于 Python 3.8+
s = "hello world"

print(list(s)) # ['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd']
print(s.split()) # ['hello', 'world'] —— 按空白切词
print(s.split(" ")) # ['hello', 'world'] —— 按单个空格切
print(s.split("o")) # ['hell', ' w', 'rld']

list(s)逐字符拆分,s.split(sep)按分隔符切分,这是最容易混的一对。split()不传参数或传None时启用特殊的空白算法:把连续空白当成一个分隔符,并且结果里不会有空字符串;一旦传入具体的分隔符,就会保留空串:


# 适用于 Python 3.8+
print(" a b ".split()) # ['a', 'b']
print(",a,,b,".split(",")) # ['', 'a', '', 'b', '']

列表合回字符串只有一个正确姿势:


# 适用于 Python 3.8+
parts = ["hello", "world"]
print(" ".join(parts)) # 'hello world'
print("-".join("abc")) # 'a-b-c' —— 因为字符串本身也是可迭代对象

"".join()的调用者是「分隔符」,参数才是「要被连接的序列」,别把顺序记反。而且它要求序列里每一个元素都是字符串,有一个整数就会抛TypeError。


字符串与数字之间不能隐式互转,必须显式写转换:


# 适用于 Python 3.8+
n = 42
print("答案是 " + str(n)) # 拼接,先转字符串
print(f"答案是 {n}") # f-string 会自动调用格式化,不需要手写 str()
# print("答案是 " + n) # TypeError: can only concatenate str

三、容器之间的互转


list()、tuple()、set()、dict()都是构造器,把可迭代对象转成对应容器:


# 适用于 Python 3.8+
t = (1, 2, 2, 3)
print(list(t)) # [1, 2, 2, 3]
print(set(t)) # {1, 2, 3} 去重,且不保证顺序
print(tuple([1, 2])) # (1, 2)

pairs = [("a", 1), ("b", 2)]
print(dict(pairs)) # {'a': 1, 'b': 2}
print(dict(a=1, b=2)) # {'a': 1, 'b': 2}

几个必须记住的性质:



  • set()去重后会丢掉重复元素和原有顺序,需要保序去重时不能用它。

  • dict()接受「键值对的可迭代对象」或关键字参数,但关键字参数的键必须是合法标识符,dict(**{"a-b": 1})这种带连字符的键会报错。

  • 容器的转换是浅拷贝:list(inner_list)只复制外层,里面的可变对象仍然共享。


四、转换的失败模式与安全写法


转换不是总能成功,字符串转数字尤其如此。可用的手段有三层:


# 适用于 Python 3.8+
def to_int(s, default=None):
try:
return int(s)
except (ValueError, TypeError):
return default

print(to_int("42")) # 42
print(to_int("abc")) # None
print(to_int(None)) # None —— TypeError 也被接住了

int("12.5")会抛ValueError,想处理小数文本要先float()再取整:int(float("12.5"))得到12。反过来,float("12")是合法的,得到12.0。


判断一个字符串是不是数字,用str自带的方法比正则更直接:




方法判断范围例子



s.isdigit()只认数字字符"²".isdigit()为真,但int("²")会失败

s.isdecimal()只认能构成十进制的字符比isdigit更严格

s.isnumeric()范围最宽,含分数、罗马数字等"½".isnumeric()为真



所以「判断能否转成 int」不能只靠isdigit(),最稳妥的还是try/except。


常见坑点



  1. 以为 int() 能吃小数字符串


❌int("12.5")→ValueError: invalid literal for int() with base 10: '12.5'


✅int(float("12.5"))→12,或先用Decimal("12.5")做精确解析



  1. 把 list(s) 当成 split


❌list("a,b")以为得到['a', 'b'],实际得到['a', ',', 'b']


✅ 想切词用"a,b".split(",")



  1. join 要求元素全是字符串


❌"-".join([1, 2, 3])→TypeError: sequence item 0: expected str instance, int found


✅"-".join(str(x) for x in [1, 2, 3])



  1. 字符串和数字直接相加


❌"id_" + 5→TypeError,Python 不会偷偷把 5 变成"5"


✅"id_" + str(5),或用 f-stringf"id_{5}"



  1. 用 set() 做保序去重


❌list(set(["b", "a", "b"]))顺序不可控,可能变成['a', 'b']


✅ 3.7+ 用list(dict.fromkeys(["b", "a", "b"]))保序去重



  1. 把 int() 当成四舍五入


❌int(2.9)期望得到3,其实是2;int(-2.9)也不是-3


✅ 明确语义:截断用int(),取整用math.floor()/math.ceil(),舍入用round()



  1. 用 eval() 把字符串转回容器


❌eval("[1, 2, 3]")能从字符串还原列表,但它会执行任意代码,绝不能用于外部输入


✅ 解析 JSON 数据用json.loads();ast.literal_eval()也只适用于字面量且需谨慎评估



  1. 忽略浮点的转换误差


❌float("0.1")得到的并不是精确的 0.1,直接和0.1比较可能出错


✅ 需要精确十进制时用decimal.Decimal("0.1"),比较浮点用math.isclose()


总结




目标写法关键点



字符串转整数int(s, base=10)不吃小数点,向零截断

字符串转浮点float(s)接受科学计数法、inf、nan

数字转字符串str(n)/ f-string拼接前必须显式转换

字符串转列表s.split(sep)不传 sep 才启用空白折叠

列表转字符串sep.join(seq)调用者是分隔符,元素必须全为 str

容器互转list()/tuple()/set()/dict()浅拷贝,set丢顺序



数据类型转换的难点不在语法,而在边界:哪些字符串能转、截断方向、空串与None怎么处理。把int()截断、split()的空格折叠、join()的元素类型要求这三点记牢,再配合try/except兜住解析失败,绝大多数转换场景都不会出问题。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询