一、开篇:为什么"42"不等于42
在python中,"42"和42是两个完全不同的东西——一个是字符串,一个是整数。它们看起来很像(都是数字),但行为截然不同:
print("42" + "42") # "4242" —— 字符串拼接
print(42 + 42) # 84 —— 数学加法
# print("42" + 42) # typeerror!不能混用
类型转换就是在不同类型之间建起的"桥梁"。今天这篇文章,我们将深入掌握python中最常用的三种类型(int、float、str)之间的互相转换——包括各种边界情况、常见陷阱和最佳实践。
类型转换不只是int()、float()、str()这么简单——它还涉及精度问题、进制转换、格式化等更深层的知识。
二、int():将任意值转换为整数
2.1 基本用法
# int(x) —— 将x转换为整数
# 从字符串转换
print(int("42")) # 42
print(int("-10")) # -10
print(int("+5")) # 5
print(int(" 100 ")) # 100 —— 自动去除前后空格
print(int("0")) # 0
# 从浮点数转换(截断,不是四舍五入!)
print(int(3.14)) # 3
print(int(3.99)) # 3 —— 注意:是截断不是四舍五入!
print(int(-3.14)) # -3
print(int(-3.99)) # -3 —— 向零截断
# 从布尔值转换
print(int(true)) # 1
print(int(false)) # 0
2.2 进制转换
# int(x, base) —— 按指定进制解析字符串
# base=2: 二进制
print(int("1010", 2)) # 10
print(int("11111111", 2)) # 255
# base=8: 八进制
print(int("755", 8)) # 493
print(int("0o755", 8)) # 493 —— 可以带前缀
# base=16: 十六进制
print(int("ff", 16)) # 255
print(int("0xff", 16)) # 255 —— 可以带前缀
print(int("ff", 16)) # 255 —— 不区分大小写
# base=0: 根据前缀自动推断
print(int("0b1010", 0)) # 10 —— 0b前缀表示二进制
print(int("0o755", 0)) # 493 —— 0o前缀表示八进制
print(int("0xff", 0)) # 255 —— 0x前缀表示十六进制
print(int("42", 0)) # 42 —— 无前缀表示十进制
# base范围:2-36(或者0)
# 当base>10时,使用字母a-z表示10-35
print(int("z", 36)) # 35 —— z在36进制中表示35
2.3 不能转换的情况
# 以下都会抛出 valueerror
# int("3.14") # 不能直接从浮点字符串转换
# int("1,000") # 不能有千位分隔符
# int("0x12", 10) # base=10时不接受前缀
# int("abc") # 非数字字符串
# int("") # 空字符串
# int("12ab") # 混合字符串
# int("12.0") # 浮点格式
# ✅ 处理方法:
# 浮点字符串 → 先float再int
print(int(float("3.14"))) # 3
# 带千位分隔符 → 先清理
print(int("1,000,000".replace(",", ""))) # 1000000
# 使用locale处理本地化数字
import locale
# locale.setlocale(locale.lc_all, '')
# print(locale.atoi("1,000,000")) # 依赖于系统locale设置
2.4 int()的高级用法
# int() 也可以用于自定义类
class hexadecimal:
def __init__(self, hex_str):
self.hex_str = hex_str
def __int__(self):
"""定义如何转为整数"""
return int(self.hex_str, 16)
hex_num = hexadecimal("ff")
print(int(hex_num)) # 255
# int() 的舍入选择
import math
# 截断(int()的默认行为)
print(int(3.7)) # 3
# 向下取整(floor)
print(math.floor(3.7)) # 3
print(math.floor(-3.7)) # -4
# 向上取整(ceil)
print(math.ceil(3.7)) # 4
print(math.ceil(-3.7)) # -3
# 四舍五入(round)
print(round(3.7)) # 4
print(round(3.2)) # 3
print(round(3.5)) # 4 —— python使用银行家舍入
print(round(4.5)) # 4 —— 偶数侧!
# 向零取整
print(int(3.7)) # 3
print(int(-3.7)) # -3
三、float():将任意值转换为浮点数
3.1 基本用法
# float(x) —— 将x转换为浮点数
# 从字符串转换
print(float("3.14")) # 3.14
print(float("10")) # 10.0
print(float("-2.5")) # -2.5
print(float(" .5 ")) # 0.5 —— 可以省略整数部分
print(float("5.")) # 5.0 —— 可以省略小数部分
# 从整数转换
print(float(42)) # 42.0
print(float(-10)) # -10.0
# 从布尔值转换
print(float(true)) # 1.0
print(float(false)) # 0.0
# 科学计数法
print(float("1e-3")) # 0.001
print(float("2.5e4")) # 25000.0
print(float("-1.23e+2")) # -123.0
3.2 特殊值
# 无穷大
print(float("inf")) # inf
print(float("+inf")) # inf
print(float("-inf")) # -inf
print(float("infinity")) # inf
import math
print(float("inf") == math.inf) # true
print(1.0 / 0.0) # inf —— 不会抛出异常!
print(float("inf") > 10**100) # true
# 非数字 (nan)
print(float("nan")) # nan
print(math.isnan(float("nan"))) # true
print(float("nan") == float("nan")) # false —— nan不等于任何值,包括自身!
3.3 浮点精度问题
# ⚠️ 浮点数不是精确的
# 经典问题
print(0.1 + 0.2) # 0.30000000000000004
print(0.1 + 0.2 == 0.3) # false!
# 原因:0.1在二进制中是无限循环小数
# 就像1/3在十进制中:0.3333...
# 解决方案1:使用round()
print(round(0.1 + 0.2, 10)) # 0.3
# 解决方案2:使用decimal
from decimal import decimal
print(decimal('0.1') + decimal('0.2')) # 0.3
# 解决方案3:使用math.isclose()
import math
print(math.isclose(0.1 + 0.2, 0.3)) # true
# 浮点数的精度限制
print(1.0 + 1e-16) # 1.0 —— 太小被忽略了
print(float(10**100)) # 1e+100 —— 大数可以表示
3.4 float()的边界情况
# 精度限制
import sys
print(sys.float_info)
# max=1.7976931348623157e+308
# min=2.2250738585072014e-308
# dig=15 (有效数字位数)
# 溢出
# float(10**1000) # overflowerror!
# 下溢
print(float(10**-400)) # 0.0 —— 接近零但被截断为0
# 自定义类实现__float__
class percentage:
def __init__(self, value):
self.value = value
def __float__(self):
return self.value / 100.0
p = percentage(75)
print(float(p)) # 0.75
四、str():将任意值转换为字符串
4.1 基本用法
# str(x) —— 将x转换为字符串
# 数字转字符串
print(str(42)) # "42"
print(str(3.14)) # "3.14"
print(str(1e10)) # "10000000000.0"
# 布尔值转字符串
print(str(true)) # "true"
print(str(false)) # "false"
# 容器类型
print(str([1, 2, 3])) # "[1, 2, 3]"
print(str({"a": 1})) # "{'a': 1}"
print(str((1, 2))) # "(1, 2)"
print(str({1, 2, 3})) # "{1, 2, 3}"
# none
print(str(none)) # "none"
4.2 str() vs repr()
# str(): 给人类看的,追求可读性
# repr(): 给开发者/调试用的,追求准确性
import datetime
# 日期时间
dt = datetime.datetime(2024, 1, 15, 14, 30, 0)
print(str(dt)) # "2024-01-15 14:30:00" —— 给人看的
print(repr(dt)) # "datetime.datetime(2024, 1, 15, 14, 30)" —— 可执行代码
# 字符串
s = "hello\tworld\n"
print(str(s)) # hello world(有换行)
print(repr(s)) # 'hello\tworld\n' —— 显示转义字符
# 浮点数
print(str(1/3)) # "0.3333333333333333"
print(repr(1/3)) # "0.3333333333333333" —— 对浮点数通常一样
# 自定义类的str vs repr
class point:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return f"point({self.x}, {self.y})"
def __repr__(self):
return f"point(x={self.x}, y={self.y})"
p = point(3, 4)
print(str(p)) # point(3, 4) —— 简洁表示
print(repr(p)) # point(x=3, y=4) —— 详细表示
# 没有__str__时,str()会调用__repr__()
# 没有__repr__时,默认显示内存地址
4.3 格式化数字转为字符串
# f-string / format() —— 格式化的类型转换
num = 255
pi = 3.14159265
# 十进制
print(f"{num}") # "255"
# 二进制/八进制/十六进制
print(f"{num:b}") # "11111111"
print(f"{num:o}") # "377"
print(f"{num:x}") # "ff"
print(f"{num:x}") # "ff"
print(f"{num:#b}") # "0b11111111" —— 带前缀
# 浮点数格式化
print(f"{pi:.2f}") # "3.14" —— 保留2位小数
print(f"{pi:.4e}") # "3.1416e+00" —— 科学计数法
print(f"{pi:.2%}") # "314.16%" —— 百分比
# 对齐和填充
print(f"{42:>10}") # " 42" —— 右对齐
print(f"{42:<10}") # "42 " —— 左对齐
print(f"{42:^10}") # " 42 " —— 居中
print(f"{42:0>10}") # "0000000042" —— 零填充
# 千位分隔符
print(f"{1234567:,}") # "1,234,567"
print(f"{1234567.89:,.2f}") # "1,234,567.89"
# bin()/oct()/hex() 函数
print(bin(255)) # "0b11111111"
print(oct(255)) # "0o377"
print(hex(255)) # "0xff"
五、三种类型互转速查
5.1 转换矩阵
# ============= 转换速查表 =============
# str → int
print(int("42")) # 42
# str → float
print(float("3.14")) # 3.14
# str → str
print(str("hello")) # "hello"
# int → int
print(int(42)) # 42
# int → float
print(float(42)) # 42.0
# int → str
print(str(42)) # "42"
# float → int (截断)
print(int(3.99)) # 3
# float → float
print(float(3.14)) # 3.14
# float → str
print(str(3.14)) # "3.14"
# bool → int
print(int(true)) # 1
# bool → float
print(float(false)) # 0.0
# bool → str
print(str(true)) # "true"
# none → str
print(str(none)) # "none"
# none → int/float → 报错
# int(none) # typeerror
# float(none) # typeerror
5.2 安全转换函数
def safe_int(value, default=0):
"""安全转换为int,失败返回默认值"""
try:
return int(value)
except (valueerror, typeerror):
return default
def safe_float(value, default=0.0):
"""安全转换为float,失败返回默认值"""
try:
return float(value)
except (valueerror, typeerror):
return default
def safe_str(value, default=""):
"""安全转换为str"""
if value is none:
return default
try:
return str(value)
except exception:
return default
# 测试
print(safe_int("42")) # 42
print(safe_int("abc")) # 0 —— 默认值
print(safe_int("3.14")) # 0 —— int不能直接转
print(safe_int("3.14".split('.')[0])) # 3 —— 手动处理
print(safe_float("3.14")) # 3.14
print(safe_float("abc")) # 0.0
print(safe_float(none)) # 0.0
print(safe_str(none)) # ""
print(safe_str(42)) # "42"
六、实战案例
6.1 智能类型转换器
class smartconverter:
"""智能类型转换器:自动推断并转换"""
@staticmethod
def auto_convert(value_str):
"""自动识别字符串类型并转换"""
s = value_str.strip()
# 空值
if not s:
return none
# 布尔值
if s.lower() in ('true', 'false'):
return s.lower() == 'true'
# none
if s.lower() in ('null', 'none', 'nil'):
return none
# 整数
try:
# 检查是否为纯整数格式
if s.isdigit() or (s.startswith('-') and s[1:].isdigit()):
return int(s)
except valueerror:
pass
# 浮点数
try:
# 包含一个小数点且只有数字和负号
clean = s.replace('.', '', 1).replace('-', '', 1)
if clean.isdigit() and s.count('.') <= 1:
return float(s)
except valueerror:
pass
# 十六进制
if s.startswith('0x') or s.startswith('0x'):
try:
return int(s, 16)
except valueerror:
pass
# 默认:保持字符串
return s
@staticmethod
def batch_convert(values):
"""批量转换"""
return [smartconverter.auto_convert(v) for v in values]
# 测试
test_values = [
"42", "3.14", "-10", "true", "false",
"null", "0xff", "hello", " 123 ", "",
]
for v in test_values:
result = smartconverter.auto_convert(v)
print(f"{v!r:12} → {result!r:10} (type: {type(result).__name__})")
6.2 csv数据清洗器
class csvdatacleaner:
"""csv数据清洗器 —— 批量类型转换"""
type_map = {
"int": int,
"float": float,
"str": str,
"bool": lambda x: x.lower() in ("true", "1", "yes"),
}
def __init__(self, column_types):
"""
column_types: {"列名": "int", "年龄": "int", ...}
"""
self.column_types = column_types
def clean_row(self, row):
"""清洗一行数据,按列定义的类型转换"""
cleaned = {}
for col, value in row.items():
target_type = self.column_types.get(col, "str")
converter = self.type_map.get(target_type, str)
try:
cleaned[col] = converter(value) if value else none
except (valueerror, typeerror):
cleaned[col] = none # 转换失败用none
print(f" ⚠️ 列'{col}'的值'{value}'无法转为{target_type}")
return cleaned
def clean_data(self, rows):
"""批量清洗"""
cleaned_rows = []
errors = []
for i, row in enumerate(rows):
cleaned = self.clean_row(row)
# 检查是否有转换失败的
has_error = any(
v is none and row.get(k) is not none and row.get(k) != ""
for k, v in cleaned.items()
)
if has_error:
errors.append(i)
cleaned_rows.append(cleaned)
print(f"清洗完成: {len(rows)}行, {len(errors)}行有问题")
return cleaned_rows
# 测试
raw_data = [
{"name": "张三", "age": "25", "score": "85.5", "active": "true"},
{"name": "李四", "age": "abc", "score": "92.0", "active": "1"},
{"name": "王五", "age": "30", "score": "n/a", "active": "false"},
]
cleaner = csvdatacleaner({
"name": "str",
"age": "int",
"score": "float",
"active": "bool",
})
cleaned = cleaner.clean_data(raw_data)
for row in cleaned:
print(row)
七、本章小结
本文我们全面掌握了int、float、str三种类型之间的转换:
- int():截断小数(不是四舍五入)、支持2-36进制、不能直接转浮点字符串。特殊:
int(true)=1。 - float():支持科学计数法、特殊值(inf、nan)、有精度限制。注意浮点数的二进制表示问题。
- str():几乎任何值都可以转为字符串。
str()给人看,repr()给开发者看。 - 格式化:f-string/format提供了丰富的数字格式化选项(进制、精度、对齐、千位分隔符)。
- 安全转换:使用try-except包裹转换操作,提供默认值,避免程序因转换失败而崩溃。
类型转换是python编程中的基础功。掌握好这三种核心类型的转换及其边界情况,能让你在数据处理时游刃有余。
以上就是python基础指南之int、float、str三大数据类型互转详解的详细内容,更多关于python数据类型转换的资料请关注代码网其它相关文章!
发表评论