Python 内置函数是解释器自带的工具,不需要 import 就能用。它们覆盖了类型转换、序列操作、格式化、对象反射等基础能力,任何项目都会反复碰到。
先把”有多少个”这件事说清楚。dir(builtins) 里去掉下划线开头的名字,一共 151 个,但它们不是同一种东西:
| 类别 | 数量 | 例子 |
|---|---|---|
| 内置函数 | 43 | print、len、sorted、open |
| 内置类型 | 26 | int、str、list、dict、range |
| 异常类型 | 71 | ValueError、TypeError、KeyError |
| 常量 | 5 | True、False、None、Ellipsis、NotImplemented |
所以”Python 有 69 个内置函数”是 2015 年前后 Python 2.7 时代的旧数字,现在已经不准确了。日常说的”内置函数”通常指的是能直接调用的那批——既包括 print 这种纯函数,也包括 int、list 这些兼作类型和转换器的对象。Python 3.12 起还多了 aiter、anext、breakpoint 等。
下面按用途分组说明。
类型转换与构造
这一组既能把已有对象转成目标类型,也能凭空构造一个空对象或从可迭代对象生成新对象。
print(int("123")) # 123
print(int("1010", 2)) # 10,二进制字符串转整数
print(int()) # 0
print(int(3.99)) # 3,向零截断int() 的第二个参数 base 范围是 2–36,前缀 0x/0o/0b 会被自动识别:
print(int("0x1f", 16)) # 31
print(int("1f", 16)) # 31,不写 0x 也行float() 接受整数、字符串和科学计数法:
print(float(123)) # 123.0
print(float("3.14")) # 3.14
print(float("1e-3")) # 0.001str()、repr() 的区别值得单独记:str 面向阅读者,repr 面向开发者,尽量给出能还原对象的表示。
print(str([1, 2, 3])) # [1, 2, 3]
print(repr([1, 2, 3])) # [1, 2, 3]
print(str("Python")) # Python
print(repr("Python")) # 'Python'bool() 遵循”空即假”规则:
print(bool(0)) # False
print(bool([])) # False
print(bool("")) # False
print(bool([1])) # True容器类型的构造器支持从可迭代对象生成:
print(list("Python")) # ['P', 'y', 't', 'h', 'o', 'n']
print(tuple([1, 2, 3])) # (1, 2, 3)
print(set([1, 2, 2, 3])) # {1, 2, 3}
print(frozenset([1, 2])) # frozenset({1, 2})
print(dict(name="Alice")) # {'name': 'Alice'}
print(dict([("a", 1)])) # {'a': 1}dict() 的三种初始化方式——关键字参数、映射对象、可迭代的键值对——在实际项目里都能见到,选哪种取决于数据来源。
字节类型:
print(bytes("Python", "utf-8")) # b'Python'
ba = bytearray("abc", "utf-8")
ba[0] = 97 # 改的是字节值,97 对应 'a'
print(ba) # bytearray(b'abc')bytes 不可变,bytearray 可变,常用于缓冲区处理。
complex() 直接构造复数:
print(complex(3, 4)) # (3+4j)
print(complex("3+4j")) # (3+4j)memoryview() 在不复制数据的前提下访问二进制缓冲区:
mv = memoryview(bytes("abc", "utf-8"))
print(mv[0]) # 97range() 不是生成器而是序列类型,可以索引、可以 len:
print(list(range(5))) # [0, 1, 2, 3, 4]
print(list(range(2, 10, 2))) # [2, 4, 6, 8]
print(len(range(10))) # 10序列与集合操作
统计、排序、遍历类函数。
print(len([1, 2, 3])) # 3
print(len({"name": "Alice", "age": 18})) # 2,字典算键值对数max/min 的 key 参数指定比较依据,default 处理空序列:
print(max([1, 3, 2])) # 3
print(max("abc", key=ord)) # 'c'
print(max([], default=0)) # 0
print(max(1, 2, 3)) # 3,也可直接比多个参数sum() 的第二个参数是初始值:
print(sum([1, 2, 3])) # 6
print(sum([1, 2, 3], start=10)) # 16sorted() 返回新列表,不改原对象,这一点和 list.sort() 不同:
nums = [3, 1, 2]
print(sorted(nums)) # [1, 2, 3]
print(nums) # [3, 1, 2],原列表没变
print(sorted([(2, "b"), (1, "a")], key=lambda x: x[0]))
1. [(1, 'a'), (2, 'b')]reversed() 返回反向迭代器,要看内容得先转成序列:
print(list(reversed([1, 2, 3]))) # [3, 2, 1]enumerate() 和 zip() 是遍历时最常用的两个:
for idx, val in enumerate(["a", "b", "c"], start=1):
print(idx, val)
1. 1 a
1. 2 b
1. 3 c
print(list(zip([1, 2], ["a", "b"]))) # [(1, 'a'), (2, 'b')]
print(list(zip([1, 2, 3], ["a", "b"]))) # [(1, 'a'), (2, 'b')],按最短的截断Python 3 里 zip/map/filter 返回的是迭代器而不是列表,要一次看完得包一层 list()。
all() 和 any() 遵循空集合语义——空序列 all 返回 True,空序列 any 返回 False:
print(all([True, 1, "a"])) # True
print(all([True, 0])) # False
print(all([])) # True
print(any([False, 0, ""])) # False
print(any([False, 1])) # True
print(any([])) # Falsefilter() 的过滤函数返回真值时保留元素,第二个参数为 None 时按真值过滤:
def is_even(x):
return x % 2 == 0
print(list(filter(is_even, [1, 2, 3, 4]))) # [2, 4]
print(list(filter(None, [0, 1, "", True]))) # [1, True]map() 对每个元素应用函数:
print(list(map(lambda x: x * 2, [1, 2, 3]))) # [2, 4, 6]
print(list(map(lambda x, y: x + y, [1, 2], [3, 4]))) # [4, 6]map 多序列时按最短的截断,多余的元素会被丢弃——这个行为经常被忽略。
输入输出与格式化
print() 的四个参数:
print("Hello", "Python", sep="-") # Hello-Python
print("End", end="!") # End!
print("无换行", end="") # 不加换行符完整签名是 print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)。end 默认是换行符 '\n'(一个反斜杠加 n),不是字母 n。flush=True 会强制刷新缓冲区,在需要实时输出的场景(如进度条)里有用。
input() 返回的永远是字符串,需要自己转换类型:
name = input("请输入姓名:")
print(f"你好,{name}")format() 是 str.format 语法的函数形式:
print(format(3.14159, ".2f")) # 3.14
print(format("Python", ">10")) # ' Python'
print(format(255, "x")) # 'ff'实际写代码时用 f-string 更顺手:
name = "Alice"
age = 18
print(f"{name} 今年 {age} 岁")help() 打开对象的帮助信息,是交互式探索时最实用的一个:
help(list) # 交互环境下会打印详细文档
help(list.append) # 查看单个方法数学与数值
print(abs(-5)) # 5
print(abs(3 + 4j)) # 5.0,复数返回模
print(abs(3.14 - 5)) # 1.8599999999999998,浮点误差是真实存在的最后一条不是 bug。浮点数用二进制表示,3.14 无法精确存储,所以减法结果会带尾差。需要严格十进制运算时用 decimal.Decimal:
from decimal import Decimal
print(Decimal("3.14") - Decimal("5")) # -1.86round() 的行为和”四舍五入”不完全一致——它用的是银行家舍入(round-half-to-even),恰好在 .5 位置时取偶数:
print(round(2.5)) # 2
print(round(3.5)) # 4
print(round(3.14159, 2)) # 3.14这在会计场景容易引起争议,处理金额通常要显式用 Decimal 而不是 round。
divmod() 一次拿到商和余数:
print(divmod(10, 3)) # (3, 1)
print(divmod(10.5, 3)) # (3.0, 1.5)pow() 的三参数形式做模幂运算,比先算幂再取模高效:
print(pow(2, 3)) # 8
print(pow(2, 3, 5)) # 3,(2**3) % 5
print(pow(2, 10, 1000)) # 24,模幂在密码学里常用进制转换:
print(hex(255)) # '0xff'
print(oct(8)) # '0o10'
print(bin(5)) # '0b101'这些返回的是字符串,要整数得配 int(..., 16)。
字符与编码值互转:
print(chr(65)) # 'A'
print(chr(128512)) # '😀'
print(ord('A')) # 65
print(ord('😀')) # 128512chr() 的合法范围是 0 到 0x10FFFF(1114111),超出抛 ValueError。
ascii() 返回纯 ASCII 表示,非 ASCII 字符用转义序列——注意输出里是反斜杠 u:
print(ascii('😀')) # '\U0001f600'
print(ascii('Python你好')) # 'Python\u4f60\u597d'对象与属性操作
反射类函数,用来在运行时查看和操作对象。
id() 返回对象身份标识:
a = [1, 2, 3]
b = a
print(id(a) == id(b)) # True,同一个对象type() 既能查类型,也能动态建类:
print(type(123)) # <class 'int'>
MyClass = type("MyClass", (object,), {"name": "test"})
print(MyClass.name) # testdir() 不带参数时列出当前作用域的变量:
print(dir(list)[:5]) # 列表类的前几个属性名
print(dir()) # 当前作用域的名字四个属性操作函数:
class Person:
name = "Alice"
p = Person()
print(getattr(p, "name")) # 'Alice'
print(getattr(p, "age", 18)) # 18,属性不存在且给了默认值
setattr(p, "age", 18)
print(p.age) # 18
print(hasattr(p, "name")) # True
delattr(p, "age")
print(hasattr(p, "age")) # Falsegetattr 不给默认值且属性不存在时会抛 AttributeError。delattr 同理。
类型判断:
class Animal:
pass
class Dog(Animal):
pass
print(isinstance(123, int)) # True
print(isinstance([1, 2], (list, tuple))) # True,元组表示"任一"
print(isinstance(True, int)) # True,bool 是 int 的子类
print(issubclass(Dog, Animal)) # Trueisinstance(True, int) 返回 True 是因为 bool 继承自 int,这点在做数值类型判断时经常需要单独排除。
vars() 返回对象的 __dict__:
class Person:
name = "Alice"
p = Person()
print(vars(p)) # {'name': 'Alice', '__module__': '__main__'}
print(vars()) # 当前作用域的局部变量字典迭代器与生成器
it = iter([1, 2, 3])
print(next(it)) # 1
print(next(it)) # 2iter() 带 sentinel 参数时,可以把可调用对象变成迭代器,迭代到返回值等于哨兵为止:
import sys
it = iter(sys.stdin.readline, "") # 读到空行停止
for line in it:
print(line, end="")next() 迭代器耗尽时抛 StopIteration,给了 default 就返回默认值:
it = iter([1, 2, 3])
print(next(it)) # 1
print(next(it, "已结束")) # 已结束动态执行与编译
compile() 把源码编译成代码对象,eval() 执行单个表达式并返回结果,exec() 执行语句块。
code = compile("print('Hello Python')", "<string>", "exec")
exec(code)
1. Hello Python
print(eval("1 + 2 * 3")) # 7eval 只接受表达式,exec 接受语句块:
exec("""
def add(a, b):
return a + b
print(add(2, 3))
""")
1. 5这两个函数是代码注入的入口。只要表达式内容来自用户输入,就等同于让对方在你的进程里执行任意代码:
user_input = "__import__('os').system('rm -rf /')"
1. eval(user_input) # 千万别这么写要”执行用户给的数据”,用 ast.literal_eval(),它只解析字面量:
import ast
print(ast.literal_eval("[1, 2, 3]")) # [1, 2, 3]常用但容易忽略的一组
callable() 判断对象是否可调用:
print(callable(len)) # True
print(callable("abc")) # Falsehash() 返回对象的哈希值,字典和集合靠它定位元素。可变对象不可哈希:
print(hash("abc") == hash("abc")) # True
try:
hash([1, 2]) # TypeError: unhashable type: 'list'
except TypeError as exc:
print(f"不可哈希:{exc}")globals() 和 locals() 返回当前作用域的字典,调试时有用:
def demo():
local_var = 1
return locals()
print(demo()) # {'local_var': 1}slice() 构造切片对象:
s = slice(1, 5, 2)
print(list(range(10))[s]) # [1, 3]breakpoint()(3.7+)在当前行插入调试器断点,等价于 import pdb; pdb.set_trace():
def compute(x):
breakpoint()
return x * 2aiter() 和 anext()(3.10+)是异步版本的迭代接口:
async def main():
agen = aiter([1, 2, 3])
print(await anext(agen)) # 1类与函数相关的内置类型
这几个平时当装饰器用,实质是描述符:
class Math:
@staticmethod
def add(a, b):
return a + b
print(Math.add(2, 3)) # 5class Person:
name = "Human"
@classmethod
def get_name(cls):
return cls.name
print(Person.get_name()) # Humanclass Person:
def __init__(self, age):
self._age = age
@property
def age(self):
return self._age
@age.setter
def age(self, value):
if value < 0:
raise ValueError("年龄不能为负")
self._age = value
p = Person(18)
print(p.age) # 18,像访问属性一样调用property 让方法表现得像属性,同时保留读写校验的能力。
super() 调用父类实现,避免硬编码类名:
class Animal:
def speak(self):
print("Animal speaks")
class Dog(Animal):
def speak(self):
super().speak()
print("Dog barks")
Dog().speak()
1. Animal speaks
1. Dog barks解释器控制与退出
exit() 和 quit() 终止解释器。它们其实是 site 模块注入的交互式辅助对象,在脚本里应该用 sys.exit():
import sys
sys.exit(0) # 正常退出
sys.exit(1) # 异常退出sys.exit() 抛的是 SystemExit 异常,可以被捕获:
import sys
try:
sys.exit(3)
except SystemExit as exc:
print("退出码:", exc.code)使用注意事项
- 别覆盖内置名字。
list = [1, 2]之后list(...)就调不到了。可以用builtins.list访问原始对象。 - 分清返回迭代器还是列表。
map/filter/zip/reversed都返回迭代器,只能遍历一次,且不直接支持索引。 - 优先用 C 实现的版本。
sum比循环累加快,any/all有短路优化。 - 注意空序列语义。
all([])是True,这在写校验逻辑时经常反直觉。 eval/exec只处理可信内容。外部数据用ast.literal_eval或专门的解析器。
相关文档
- Python 内置函数详解 —— 本篇
- Python 35个关键字详解 ——
def、lambda等关键字的用法 - Python 标准库全解析 ——
os、sys、json等标准库模块