Python设计理念是“小的核心语言”+“大的标准库”,当Python想要添加新功能时,更多思考的是改将此特性加入核心语言支持还是作为扩展放入库中。Python标准库非常庞大,包含了很多模块,要想使用某个函数,必须提前导入对应的模块,否则函数是无效的。而内置函数是解释器的一部分,它随着解释器的启动而生效。所以内置函数的数量必须被严格控制,否则Python解释器会变得庞大和臃肿。一般来说,只有那些使用频繁或者和语言本身绑定比较紧密的函数,才会被提升为内置函数。
数学运算
- abs(x):返回一个数的绝对值。
- pow(x, y, z=None):返回x的y次幂,如果提供z,则计算结果对z取模。
- round(number, ndigits=None):返回一个浮点数,舍入到指定的小数位数。
- divmod(a, b):接受两个(非复数)数字作为参数并返回由当对其使用整数除法时的商和余数组成的数字对。
- max(iterable, *[, key, default]):返回可迭代对象的最大值。
- min(iterable, *[, key, default]):返回可迭代对象的最小值。
- sum(iterable, /, start=0):从start开始计算iterable的总和。
类型转换
- int(x, base=10):将一个数字或字符串转换为整数。
- float(x):将一个字符串或数字转换为浮点数。
- str(object=”):将对象转换为字符串。
- bool(x):将一个值转换为布尔值。
- list(iterable):将可迭代对象转换为列表。
- tuple(iterable):将可迭代对象转换为元组。
- set(iterable):将可迭代对象转换为集合。
- dict(**kwargs):创建一个字典。
- bool(object=False, /):返回Bool值
- str():返回字符串
- complex():返回复数
- bytearray():返回字节数组
- bytes():返回不可变字节数组
- memoryview():根据传入参数创建一个新的内存查看对象
- ord():返回Unicode字符对应的整数
- chr():返回整数对应的Unicode字符
- bin():将整数转换成二进制字符串
- oct():将整数转化为8进制字符串
- hex():将整数转换成16进制字符串
- frozenset():根据传入参数创建一个不可变集合
- enumerate(iterable, start=0):返回一个枚举对象,枚举对象是一个由索引和值组成的元组。
- range(start, stop[, step]):生成从start到stop的数字序列,步长为step。
- iter(object, sentinel):根据传入的参数创建一个新的可迭代对象
- slice(start, stop[, step]):根据传入的参数创建一个新的切片对象
- super():根据传入的参数创建一个新的子类和父类关系的代理对象
- object():创建一个新的object对象
memoryview()
memoryview是Python中的一个内置类,它提供了一种在不复制对象内容的情况下访问数组或缓冲区协议支持对象的方式
memoryview对象允许你在不进行数据复制的情况下访问同一块内存中的数据片段,因此在处理大型数据集时非常高效。
特点
- 高效的数据访问:memoryview提供了一种访问内存中数据的方式,而不需要复制数据,从而提高了处理速度和效率。
- 支持切片:memoryview对象支持切片操作,可以方便地访问和修改数据的子集。
- 多种格式:支持不同的格式(例如,字节、整数、浮点数等),类似于struct模块的格式描述符。
- 与缓冲区协议兼容:memoryview可以作用于任何实现了缓冲区协议的对象,比如bytes、bytearray、array.array、numpy.ndarray等。
基本用法
# 创建一个字节数组 data = bytearray(b'Hello, World!') # 创建一个memoryview对象 mv = memoryview(data) # 访问memoryview中的数据 print(mv[0]) # 输出: 72,对应于'H'的ASCII码 # 修改memoryview中的数据 mv[0] = 104 # 将'H'修改为'h' print(data) # 输出: bytearray(b'hello, World!')
切片操作
# 使用切片创建memoryview的子视图 sub_mv = mv[0:5] # 修改子视图中的数据 sub_mv[0] = ord('J') print(data) # 输出: bytearray(b'Jello, World!')
与不同数据格式一起使用
import struct # 创建一个包含整数的字节数组 numbers = bytearray(struct.pack('i'*3, 1, 2, 3)) # 创建memoryview对象,并指定数据格式为整数 mv_numbers = memoryview(numbers).cast('i') # 访问和修改整数数据 print(mv_numbers[0]) # 输出: 1 mv_numbers[0] = 10 print(mv_numbers.tolist()) # 输出: [10, 2, 3]
应用场景
- 大数据处理:在处理大规模数据时,memoryview可以避免数据复制,节省内存和提高性能。
- 图像处理:对于图像数据,memoryview可以用于高效地访问和修改像素数据。
- 网络通信:在网络编程中,可以使用memoryview处理接收到的数据包,避免不必要的复制。
enumerate()
enumerate()是Python的一个内置函数,用于遍历可迭代对象(如列表、元组或字符串)时,同时获取元素的索引和值。它非常适合在循环中需要元素的索引和对应值的情况。
基本用法
#创建一个列表 fruits = ['apple', 'banana', 'cherry'] #使用 enumerate 遍历列表 for index, value in enumerate(fruits): print(index, value) #输出: #0 apple #1 banana #2 cherry
指定起始索引
#使用 enumerate,指定起始索引为 1 for index, value in enumerate(fruits, start=1): print(index, value) #输出: #1 apple #2 banana #3 cherry
与其他数据类型一起使用
#使用 enumerate 遍历字符串 for index, char in enumerate("hello"): print(index, char) #输出: #0 h #1 e #2 l #3 l #4 o
应用场景
- 索引追踪:在循环中需要同时获得元素及其索引的情况。
- 数据处理:在处理数据时,enumerate()可以用来跟踪每个元素的位置,尤其是在需要调试或日志记录时。
- 简化代码:通过使用 enumerate(),可以避免手动维护一个索引变量,从而使代码更加简洁和易读。
注意事项:enumerate()返回的是一个迭代器,而不是一个列表。如果需要一个列表,可以使用 list()函数将其转换为列表。
iter()
iter()是Python的一个内置函数,用于创建一个迭代器对象。迭代器是Python中用于迭代(遍历)集合中的元素的一种方式。iter()函数可以帮助你创建一个可以从头开始遍历集合的迭代器。
基本用法
numbers = [1, 2, 3, 4, 5] #创建一个迭代器对象 it = iter(numbers) #使用 next()获取元素 print(next(it)) #输出:1 print(next(it)) #输出:2 #使用 for 循环遍历迭代器 for num in it: print(num) #输出: #3 #4 #5
使用 sentinel 参数
当你有一个可调用对象时,可以使用 sentinel 参数来创建一个迭代器,该迭代器会一直调用这个对象直到返回一个特定的值为止。
def number_generator(): for i in range(1, 6): yield i #创建一个迭代器 it = iter(number_generator(), -1) #使用 next()获取元素 print(next(it)) #输出:1 print(next(it)) #输出:2 #使用 for 循环遍历迭代器 for num in it: print(num) #输出: #3 #4 #5
应用场景
- 数据处理:在处理大量数据时,使用迭代器可以逐个访问元素,而不是一次性加载整个集合到内存中。
- 文件读取:在读取大文件时,可以使用迭代器逐行读取文件内容,这样可以节省内存。
- 自定义迭代器:如果你想要为一个类或对象实现定制化的迭代逻辑,可以通过实现 __iter__()和 __next__()方法来创建自定义的迭代器。
注意事项
- 当迭代器中没有更多的元素时,next()会引发 StopIteration 异常。通常情况下,你不需要显式处理这个异常,因为大多数循环结构(如 for 循环)会自动处理它。
- 如果你需要多次遍历同一个迭代器,可以使用 list()或者其他容器类型来存储迭代器的结果,然后再进行操作。
slice()
slice()是Python的一个内置函数,用于创建一个切片对象。切片对象可以用来指定如何在序列(如列表、元组、字符串等)中提取子集。切片是处理序列数据的一个非常强大且灵活的工具。
基本用法
#创建一个列表 numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] #创建一个 slice 对象 s = slice(2, 8, 2) #使用 slice 对象提取子集 subset = numbers[s] print(subset) #输出:[2, 4, 6]
使用切片对象
你可以将 slice 对象与序列结合使用,以实现复杂的切片操作。
#创建一个字符串 text = "Hello, World!" #创建一个 slice 对象 s = slice(7, 12) #使用 slice 对象提取子集 subset = text[s] print(subset) #输出:World
切片对象的属性
切片对象有三个只读属性:start、stop 和 step,它们对应于创建 slice 对象时的参数。
#获取 slice 对象的属性 print(s.start) #输出:7 print(s.stop) #输出:12 print(s.step) #输出:None(因为步长没有指定)
应用场景
- 数据处理:在处理数据时,切片可以用来提取和操作子集。
- 数组操作:在处理多维数组时,切片可以用来提取特定的行、列或子数组(例如在 NumPy 中)。
- 字符串操作:切片可以用来提取字符串的子串。
注意事项
- 切片操作不会引发 IndexError。即使 start 或 stop 超出序列的范围,切片操作会自动处理,并返回可能的最大子集。
- slice 对象本身并不执行任何切片操作,它只是一个定义如何切片的描述符。实际的切片操作由序列对象(如列表、字符串等)来执行。
super()
super()是Python的一个内置函数,用于在继承层次中调用父类的方法。它是在面向对象编程中处理多重继承和方法重写时非常有用的工具。super()函数可以帮助你避免硬编码父类的名字,这使得代码更具可扩展性和易于维护。
单继承
class Animal: def speak(self): print("Animal is speaking") class Dog(Animal): def speak(self): super().speak() print("Dog is barking") dog = Dog() dog.speak() #输出: #Animal is speaking #Dog is barking
多重继承
class A: def method(self): print("Method from class A") class B: def method(self): print("Method from class B") class C(A, B): def method(self): super().method() print("Method from class C") c = C() c.method() #输出: #Method from class A #Method from class C
方法解析顺序(MRO)
在多重继承中,super()会根据方法解析顺序(MRO)来决定调用哪个父类的方法。Python使用C3线性化算法来确定MRO。
MRO示例:
class A: def method(self): print("Method from class A") class B(A): def method(self): print("Method from class B") super().method() class C(A): def method(self): print("Method from class C") super().method() class D(B, C): def method(self): print("Method from class D") super().method() d = D() d.method() # 输出: # Method from class D # Method from class B # Method from class C # Method from class A
注意事项
- 在Python3中,如果没有提供参数,super()会自动推断出当前类和当前对象。
class A: def method(self): print("Method from class A") class B(A): def method(self): super().method() # 不需要提供参数 print("Method from class B") b = B() b.method() # 输出: # Method from class A # Method from class B
- 在Python2中,super()的用法略有不同,需要明确地提供类和对象作为参数。
- 使用super()可以确保在继承层次中正确地调用基类的方法,即使类名发生改变也不会影响到代码的运行。
object()
object()是Python中的一个内置函数,用于创建一个最基本的空对象。所有的类在默认情况下都是从object类继承而来的,因为object是Python中所有类的基类。它是Python的顶层基类,这意味着所有的类都是直接或间接地继承自object。
创建一个空对象
# 创建一个最基本的空对象 obj = object() # 输出对象的默认字符串表示 print(obj) # 输出: <object object at 0x...>
自定义类继承 object
在Python3中,所有的类默认都是新式类,隐式继承自object,因此通常不需要显式地继承object。然而,在Python2中,明确继承object可以让类成为新式类。
# 定义一个自定义类 class MyClass(object): # 在Python3中,class MyClass:就足够了 def __init__(self, name): self.name = name # 创建类的实例 instance = MyClass("Python") print(instance.name) # 输出: Python
应用场景
- 基类:当你希望定义一个新的类层次结构时,可以明确地从object继承,以确保在Python2中使用新式类。
- 占位符对象:在某些情况下,你可能需要一个简单的占位符对象,可以使用object()来实现。
- 理解继承机制:了解object的作用有助于理解Python的类继承机制和方法解析顺序(MRO)。
注意事项
- 属性限制:不能在object实例上动态添加属性,因为它是一个最基本的对象,没有__dict__来存储实例属性。
- 不需要手动调用:通常情况下,你不需要显式地调用object(),因为它主要用于作为其他类的基类。
序列操作
- all():判断每个元素是否为True
- any():判断是否存在True的元素
- filter():使用指定方法进行元素过滤
- map():使用指定方法去作用传入的每个可迭代对象的元素,生成新的可迭代对象
- next():返回可迭代对象中的下一个元素值
- reversed():反转序列生成新的可迭代对象
- sorted():对可迭代对象进行排序,返回一个新的列表
- zip(*iterables):将多个可迭代对象作为参数,将对应的元素打包成一个个元组。
filter()
def if_odd(x): # 定义奇数判断函数 return x % 2 == 1 a = list(range(1, 10)) # 定义序列 print(list(filter(if_odd, a))) # 筛选序列中的奇数 # [1, 3, 5, 7, 9]
map()
a = map(ord, 'abcd') print(list(a)) # [97, 98, 99, 100]
zip()
x = [1, 2, 3] # 长度3 y = [4, 5, 6, 7, 8] # 长度5 print(list(zip(x, y))) # 取最小长度3 # [(1, 4), (2, 5), (3, 6)]
对象操作
- help():返回对象的帮助信息
- dir([object]):不带参数时,返回当前范围内的变量、方法和定义的类型列表。带参数时,返回该对象的属性、方法列表。
- id(object):返回对象的唯一标识符。
- hash():获取对象的哈希值
- type(object):返回对象的类型。
- len(s):返回序列或集合的长度。
- ascii():返回对象的可打印表字符串表现方式
- format():格式化显示值
dir()
import math print(dir(math)) # ['__doc__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'pi', 'pow', 'radians', 'remainder', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau', 'trunc']
format()
format()是Python的一个内置函数,用于格式化字符串。它提供了一种灵活且强大的方式来控制字符串的显示格式。format()函数可以通过指定格式代码来格式化数字、日期、字符串等数据类型,并将它们插入到字符串的占位符中。
基本用法
# 格式化整数 formatted_number = format(12345, ',') print(formatted_number) # 输出: 12,345 # 格式化浮点数 formatted_float = format(123.456789, '.2f') print(formatted_float) # 输出: 123.46 # 格式化百分比 formatted_percent = format(0.1234, '.2%') print(formatted_percent) # 输出: 12.34%
使用format()处理字符串
虽然format()常用于数值类型,但它也可以用于字符串处理。
# 将字符串转换为大写 formatted_string = format('hello', '>10') print(formatted_string) # 输出: ' hello'(右对齐,宽度为10)
自定义格式
format_spec可以包含多个部分,用于更复杂的格式化:
- 对齐方式:<, >, ^ 分别表示左对齐、右对齐和居中对齐。
- 填充字符:可以在对齐符号前指定一个字符作为填充字符。
- 宽度:指定输出的最小宽度。
- 精度:对于浮点数,指定小数点后的位数。
- 类型:指定格式化的类型,比如d(十进制整数)、f(浮点数)、b(二进制)、x(十六进制)等。
# 综合示例 formatted_output = format(123.456, '0>10.2f') print(formatted_output) # 输出: '0000123.46'
应用场景
- 数值格式化:用于控制数值的显示格式,比如货币、百分比、科学计数法等。
- 字符串对齐:用于在固定宽度的字段中对齐文本,比如生成表格。
- 日期和时间格式化:在格式化日期和时间时使用。
注意事项
- format()函数与字符串的format()方法是相关的,后者提供了更复杂和全面的字符串插值功能。
- 格式说明符必须与要格式化的值的类型兼容,否则会引发ValueError。
- 对于复杂的格式化需求,特别是在处理多个变量时,format()方法或f-string(在Python 3.6+中可用)可能会更加方便和可读。
反射操作
- __import__():
- isinstance(object, classinfo):检查对象是否是classinfo的实例。
- issubclass(class, classinfo):检查class是否是classinfo的子类。
- callable(object):检查对象是否可调用。
- getattr(object, name[, default]):返回对象的属性值。
- setattr(object, name, value):设置对象的属性值。
- hasattr(object, name):检查对象是否有指定的属性。
- delattr(object, name):删除对象的属性。
- repr():返回一个对象的字符串表现形式(给解释器)
__import__()
__import__()是Python的一个内置函数,用于动态导入模块。它主要用于在运行时根据字符串名称导入模块,而不是在编写代码时静态地导入模块。__import__()函数通常在需要动态加载模块的情况下使用,例如在配置文件中指定模块名称并根据这些名称加载模块。
语法
__import__(name, globals=None, locals=None, fromlist=(), level=0)
参数
- name: 要导入的模块名称。
- globals: 可选参数,字典,通常为当前全局命名空间。默认为None。
- locals: 可选参数,字典,通常为当前局部命名空间。默认为None。
- fromlist: 可选参数,列表,包含要从模块导入的属性名称。默认为空列表()。
- level: 可选参数,整数,用于确定导入相对模块的方式。默认为0,表示绝对导入。
动态导入模块
# 动态导入模块 module = __import__('math') # 使用模块 print(module.sqrt(16)) # 输出: 4.0
导入模块中的特定属性
# 动态导入模块中的特定属性 module = __import__('math', fromlist=['sqrt']) # 使用模块 print(module.sqrt(16)) # 输出: 4.0
相对导入
在Python 3中,可以使用level参数来进行相对导入。
# 假设当前目录结构如下: # main_package/ # ├── __init__.py # └── subpackage/ # ├── __init__.py # └── module.py # 在subpackage/module.py中 from .. import __init__ as parent_init # 在subpackage/__init__.py中 module = __import__('subpackage.module', level=1) # 使用模块 print(module.parent_init.__file__) # 输出: /path/to/main_package/__init__.py
应用场景
- 动态加载模块:在运行时根据用户输入或配置文件中的信息动态加载模块。
- 框架和库:许多框架和库使用__import__() 来动态加载组件或模块,以提高灵活性和可扩展性。
注意事项
- __import__()函数主要用于内部使用,对于大多数开发者来说,使用import语句或import_module()更为直观和推荐。
- __import__()的globals和locals参数通常不需要设置,除非你正在实现一些高级的动态导入逻辑。
- 使用__import__()进行动态导入时,需要注意安全问题,特别是当导入的模块名称来自不可信源时。
变量操作
- globals():返回表示当前全局符号表的字典。
- locals():返回表示当前局部符号表的字典。
- vars([object]):返回对象的__dict__属性,如果不带参数,就等同于locals()。
交互操作
- “`html
- input(prompt=None):从标准输入接收用户输入并返回字符串。
print(*objects, sep=’ ‘, end=’\n’, file=sys.stdout, flush=False):将对象打印到文本流文件中,默认输出到控制台。
文件操作
open()
open()是Python的一个内置函数,用于打开文件并返回一个文件对象。通过这个文件对象,您可以读取、写入和操作文件。open()是处理文件输入和输出(I/O)操作的核心函数之一。
语法
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
参数
- file: 要打开的文件的路径(可以是绝对路径或相对路径)。
- mode: 指定打开文件的模式,默认为’r’(只读模式)。常用模式包括:
- ‘r’: 读取(默认)。
- ‘w’: 写入(会截断文件)。
- ‘a’: 追加(写入到文件末尾)。
- ‘b’: 二进制模式。
- ‘t’: 文本模式(默认)。
- ‘+’: 更新(可读可写)。
- 例如,’rb’表示以二进制读取模式打开文件。
- buffering: 设置缓冲策略。0表示无缓冲,1表示行缓冲,>1表示定长缓冲(缓冲区大小为该值),-1表示系统默认缓冲策略。
- encoding: 指定文本模式下的编码(如’utf-8’)。
- errors: 设置错误处理策略(如’ignore’、’replace’)。
- newline: 控制新行字符的处理方式。
- closefd: 如果为False,文件描述符将不会关闭。
- opener: 自定义打开器,返回一个打开的文件描述符。
返回值
- 返回一个文件对象,该对象提供了用于操作文件的各种方法,如read()、write()、close() 等。
读取文件
with open('example.txt', 'r', encoding='utf-8') as file: content = file.read() print(content)
使用with语句可以确保文件在使用完毕后自动关闭。
写入文件
with open('example.txt', 'w', encoding='utf-8') as file: file.write("Hello, World!")
追加到文件
with open('example.txt', 'a', encoding='utf-8') as file: file.write("\nAppend this line.")
读取二进制文件
with open('image.png', 'rb') as file: data = file.read()
注意事项
- 文件不存在: 以’r’ 模式打开一个不存在的文件会引发 FileNotFoundError。
- 文件覆盖: 以’w’ 模式打开文件会清空文件内容。如果不想覆盖,可以使用 ‘a’ 模式。
- 编码: 在处理文本文件时,指定正确的编码非常重要,特别是在处理非ASCII文本时。
- 文件关闭: 使用with 语句可以确保文件正确关闭,防止资源泄漏。
编译执行
compile()
compile()是Python的一个内置函数,用于将源代码字符串编译为字节码对象。这个字节码对象可以使用exec()或eval()函数执行。compile()函数在需要动态执行代码的情况下非常有用,例如从配置文件读取代码并执行,或在交互式解释器中执行用户输入的代码。
语法
compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1)
参数
- source: 要编译的源代码,可以是一个字符串或AST(抽象语法树)对象。
- filename: 用于错误提示的文件名,可以是实际文件名或一个标识字符串。
- mode: 指定编译代码的类型,取值可以是’exec’、’eval’ 或 ‘single’。
- ‘exec’: 用于多行代码块。
- ‘eval’: 用于单个表达式。
- ‘single’: 用于单个交互式语句。
- flags: 可选参数,用于控制编译过程的标志。
- dont_inherit: 可选参数,布尔值,用于控制是否继承当前环境的编译标志。
- optimize: 可选参数,指定优化级别。
返回值
返回一个代码对象,该对象可以通过exec()或eval()执行。
编译和执行多行代码
source_code = """ for i in range(5): print(i) """ # 编译代码 code_object = compile(source_code, '<string>', 'exec') # 执行代码 exec(code_object)
编译和执行表达式
expression = "3*4+5" # 编译表达式 code_object = compile(expression, '<string>', 'eval') # 执行表达式并获取结果 result = eval(code_object) print(result) # 输出: 17
编译交互式语句
statement = "print('Hello, World!')" # 编译交互式语句 code_object = compile(statement, '<string>', 'single') # 执行语句 exec(code_object)
应用场景
- 动态代码执行:在运行时动态生成和执行代码,例如在REPL环境中。
- 代码分析和转换:在代码分析工具中,将源代码转换为AST进行处理。
- 脚本执行:从文件或网络读取代码并执行。
注意事项
- 编译后的代码对象可以在不同的命名空间中执行,通过exec() 和 eval() 提供的字典参数控制。
- 在使用compile() 时,确保来源的代码是可信的,以避免安全风险。
- compile()返回的代码对象是不可变的,但可以多次执行。
exec()
“`exec() 是 Python 的一个内置函数,用于动态执行 Python 代码。它可以执行由字符串或代码对象表示的 Python 语句。这使得 exec() 成为一个非常强大的工具,特别是在需要动态生成和执行代码的场景中。
语法
exec(object, globals=None, locals=None)
参数
- object: 要执行的代码,可以是一个字符串或代码对象。
- globals: 可选参数,指定在执行代码时使用的全局命名空间。可以是一个字典。
- locals: 可选参数,指定在执行代码时使用的局部命名空间。可以是一个字典。
执行字符串代码
code = """ for i in range(5): print(i) """ exec(code)
使用命名空间
globals_dict = {'x': 5} locals_dict = {} exec('y = x + 10', globals_dict, locals_dict) print(locals_dict['y']) # 输出: 15
在这个例子中,exec() 在指定的全局和局部命名空间中执行代码,结果被存储在 locals_dict 中。
动态生成代码
def create_function(): func_code = """ def dynamic_function(): print("This is a dynamically created function.") """ exec(func_code, globals()) create_function() dynamic_function() # 输出: This is a dynamically created function.
应用场景
- 动态代码执行:在运行时生成和执行代码,例如从配置文件或用户输入中读取代码。
- 代码生成:自动生成和执行 Python 代码片段。
- 调试和测试:在调试或测试环境中动态执行测试代码。
注意事项
- 安全性:执行来自不可信来源的代码可能导致安全漏洞,因此要特别小心,避免在生产环境中使用 exec() 执行不受信任的代码。
- 性能:动态执行代码可能会影响性能,尤其是在频繁调用的情况下。
- 可读性和维护性:大量使用 exec() 可能导致代码难以理解和维护,因此应谨慎使用。
eval()
eval() 是 Python 的一个内置函数,用于动态执行表达式字符串,并返回表达式的值。与 exec() 不同的是,eval() 只能用于执行单个表达式,而不能执行多条语句或复杂的代码块。
语法
eval(expression, globals=None, locals=None)
参数
- expression: 要求值的表达式字符串。
- globals: 可选参数,指定在执行表达式时使用的全局命名空间。可以是一个字典。
- locals: 可选参数,指定在执行表达式时使用的局部命名空间。可以是一个字典。
基本用法
expression = "3 * (4 + 5)" result = eval(expression) print(result) # 输出: 27
使用命名空间
globals_dict = {'x': 10} locals_dict = {'y': 5} result = eval('x + y', globals_dict, locals_dict) print(result) # 输出: 15
在这个例子中,eval() 使用提供的全局和局部命名空间来计算表达式的值。
动态表达式
def evaluate_expression(expr): return eval(expr) result = evaluate_expression("100 / 5") print(result) # 输出: 20.0
应用场景
- 动态计算:在运行时计算表达式的值,尤其是在需要根据用户输入或配置进行计算的情况下。
- 简化代码:在某些情况下,可以通过 eval() 来减少代码复杂性,例如在配置驱动的应用程序中。
- 交互式环境:在 REPL(Read-Eval-Print Loop)或其他交互式环境中,动态执行用户输入的表达式。
注意事项
- 安全性:与 exec() 类似,eval() 也存在安全风险。执行来自不可信来源的表达式可能导致安全漏洞,因此要特别小心。尽量避免在生产环境中使用 eval() 处理不受信任的输入。
- 性能:动态求值表达式可能影响性能,尤其是在频繁调用的情况下。
- 可读性和维护性:大量使用 eval() 可能导致代码难以理解和维护,因此应谨慎使用。
装饰器
- @property:标示属性的装饰器
- @classmethod:标示方法为类方法的装饰器
- @staticmethod:标示方法为静态方法的装饰器
@property
@property 是 Python 中的一种装饰器,用于将类的方法转换为只读属性。这种方式允许您定义类的属性,同时可以在访问属性时执行额外的逻辑,如验证或计算。这种方法提供了一种优雅的方式来管理类的属性访问,同时保持接口的简洁性。
以下是一个简单的示例,展示如何使用 @property 来定义一个只读属性:
class Circle: def __init__(self, radius): self._radius = radius @property def radius(self): return self._radius @property def area(self): return 3.14159 * (self._radius ** 2) # 使用示例 circle = Circle(5) print(circle.radius) # 输出: 5 print(circle.area) # 输出: 78.53975
在这个例子中,radius 和 area 都是通过 @property 装饰的方法,但可以像属性一样访问。
扩展功能
除了只读属性,@property 还可以与 @
读写属性
class Rectangle: def __init__(self, width, height): self._width = width self._height = height @property def width(self): return self._width @width.setter def width(self, value): if value > 0: self._width = value else: raise ValueError("Width must be positive") @property def height(self): return self._height @height.setter def height(self, value): if value > 0: self._height = value else: raise ValueError("Height must be positive") # 使用示例 rect = Rectangle(10, 20) print(rect.width) # 输出: 10 rect.width = 15 print(rect.width) # 输出: 15
在这个例子中,width和height属性既可以读取,也可以设置,并且在设置时进行了简单的验证。
优点
- 封装:通过@property,可以在不改变外部接口的情况下,增加对属性访问的控制。
- 灵活性:可以在访问属性时动态计算值或执行其他逻辑。
- 易于使用:允许类的使用者以更自然的方式访问属性,而不需要了解底层实现细节。
注意事项
- 使用@property 时,应确保计算属性的代价较小,因为每次访问属性时都会调用方法。
- 虽然@property 提供了访问控制,但在某些情况下,直接使用公开的属性可能会更简单和更有效。
@classmethod
@classmethod是Python中的一个装饰器,用于定义类方法。类方法与实例方法不同,它们是绑定到类而不是实例的。使用@classmethod可以让方法在类级别上操作,而不需要实例化类。类方法的第一个参数通常命名为cls,用于表示类本身。
以下是一个使用@classmethod的简单示例:
class Circle: pi = 3.14159 def __init__(self, radius): self.radius = radius @classmethod def from_diameter(cls, diameter): radius = diameter / 2 return cls(radius) # 使用示例 circle = Circle.from_diameter(10) print(circle.radius) # 输出: 5.0
在这个例子中,from_diameter是一个类方法,它根据给定的直径创建一个Circle实例。
特点
- 类级别访问: 类方法可以访问类变量和其他类方法,但不能直接访问实例变量。
- 工厂方法: 类方法常用于实现工厂模式,以不同的方式创建类的实例。
- 继承友好: 类方法在继承中也能正常工作,cls参数会自动传递正确的子类。
与 @staticmethod 的区别
- @classmethod: 接受类作为第一个参数(通常命名为cls),可以访问和修改类状态。
- @staticmethod: 不接受类或实例作为参数,类似于普通的函数,只是被放在类的命名空间中。
示例:与 @staticmethod 对比
class Example: count = 0 @classmethod def increment_count(cls): cls.count += 1 @staticmethod def greet(name): return f"Hello, {name}!" # 使用示例 Example.increment_count() print(Example.count) # 输出: 1 print(Example.greet("World")) # 输出: Hello, World!
在这个例子中,increment_count是一个类方法,用于修改类变量count,而greet是一个静态方法,不依赖于类或实例的状态。
@staticmethod
@staticmethod是Python中的一个装饰器,用于定义静态方法。静态方法与类方法和实例方法不同,它们不需要访问类或实例本身。它们类似于普通的函数,但属于类的命名空间,可以在类的上下文中使用。
以下是一个使用@staticmethod的简单示例:
class MathOperations: @staticmethod def add(x, y): return x + y @staticmethod def multiply(x, y): return x * y # 使用示例 print(MathOperations.add(5, 3)) # 输出: 8 print(MathOperations.multiply(5, 3)) # 输出: 15 # 也可以通过实例调用 math_ops = MathOperations() print(math_ops.add(5, 3)) # 输出: 8
在这个例子中,add和multiply是静态方法,它们执行简单的数学运算,而不依赖于类或实例的状态。
特点
- 不依赖于类或实例: 静态方法不接受 cls 或 self 参数,不能访问或修改类和实例的状态。
- 逻辑归属: 静态方法通常用于那些逻辑上属于类但不需要与类或实例交互的方法。
- 调用方式灵活: 可以通过类名或实例来调用静态方法。
与 @classmethod 的区别
- @staticmethod: 不接受类或实例作为参数,类似于普通函数,只是放在类的命名空间中。
- @classmethod: 接受类作为第一个参数(通常命名为cls),可以访问和修改类状态。
示例:与 @classmethod 对比
class Example: count = 0 @classmethod def increment_count(cls): cls.count += 1 @staticmethod def greet(name): return f"Hello, {name}!" # 使用示例 Example.increment_count() print(Example.count) # 输出: 1 print(Example.greet("World")) # 输出: Hello, World!
在这个例子中,increment_count是一个类方法,用于修改类变量count,而greet是一个静态方法,不依赖于类或实例的状态。
其他函数
breakpoint()
breakpoint()是Python3.7引入的一个内置函数,用于在代码中插入断点以便进行调试。这个函数提供了一种简单而一致的方式来调用调试器,而无需在代码中显式导入调试模块(如pdb)。
工作原理
- 默认情况下,breakpoint()会调用 breakpointhook() 函数,而 sys.breakpointhook() 默认调用 pdb.set_trace(),启动Python的内置调试器。
可以通过设置环境变量 PYTHONBREAKPOINT 来自定义调试器。例如,将 PYTHONBREAKPOINT 设置为 ‘0’ 可以禁用 breakpoint(),或者设置为自定义调试器的导入路径来使用其他调试器。
使用示例
def example_function(): x = 10 y = 20 breakpoint() # 在此处插入断点 z = x + y print(z) example_function()
运行上述代码时,程序会在 breakpoint() 处暂停,并启动调试器。在调试器中,你可以输入命令来检查变量 x 和 y 的值,或继续执行程序。
自定义调试器
通过环境变量 PYTHONBREAKPOINT,你可以指定不同的调试器。例如:
export PYTHONBREAKPOINT=yourmodule.yourdebugger
在这种情况下,breakpoint() 会调用 yourmodule.yourdebugger() 而不是默认的 pdb.set_trace()。
禁用断点
如果不需要调试,可以将 PYTHONBREAKPOINT 设置为 ‘0’,这样 breakpoint() 调用将被忽略:
export PYTHONBREAKPOINT=0
优势
- 简单易用:不需要在代码中显式导入 pdb 或其他调试模块。
- 灵活性:可以通过环境变量轻松切换调试器或禁用断点。
- 一致性:提供了一种一致的方法来处理调试,而无需在代码中进行大量更改。
注意事项
- 确保在生产环境中不会无意中留下 breakpoint() 调用,因为这会导致程序暂停。
- 在需要跨平台或在不同环境中运行代码时,利用 PYTHONBREAKPOINT 环境变量来控制调试行为。
异步迭代
在 Python 中,aiter() 和 anext() 是与异步迭代相关的内置函数,用于支持异步迭代器(async iterator)。
aiter()
aiter() 函数用于获取一个对象的异步迭代器。它接受一个可迭代对象作为参数,并返回一个异步迭代器对象。
示例:
import asyncio class AsyncNumbers: def __init__(self, max): self.max = max async def __aiter__(self): for i in range(self.max): await asyncio.sleep(1) # 模拟耗时操作 yield i async def main(): async for number in aiter(AsyncNumbers(5)): print(number) asyncio.run(main())
在这个例子中,AsyncNumbers 类定义了一个异步迭代器,我们使用 aiter() 来创建异步迭代器并遍历它。
anext()
anext() 函数用于从异步迭代器中获取下一个项目。如果异步迭代器没有更多的项目,则引发 StopAsyncIteration 异常。
示例:
import asyncio class AsyncNumbers: def __init__(self, max): self.max = max self.current = 0 async def __aiter__(self): return self async def __anext__(self): if self.current < self.max: await asyncio.sleep(1) # 模拟耗时操作 result = self.current self.current += 1 return result else: raise StopAsyncIteration async def main(): numbers = AsyncNumbers(5) async_iterator = aiter(numbers) while True: try: number = await anext(async_iterator) print(number) except StopAsyncIteration: break asyncio.run(main())
在这个例子中,AsyncNumbers 类定义了一个异步迭代器,我们使用 aiter() 来创建异步迭代器,并通过 anext() 来获取每个元素。
内置常量
builtins 模块还定义了一些常量,这些常量在 Python 中预定义:
- None:表示没有值。
- True 和 False:布尔类型的两个值。
- Ellipsis:省略号常量,通常用于多维数组切片。
- __debug__:如果解释器以优化模式启动,则为 False;否则为 True。
内置类型
builtins 模块定义了一些核心数据类型,这些类型构成了 Python 编程的基础:
- int:整数类型。
- float:浮点数类型。
- complex:复数类型。
- str:字符串类型。
- list:列表类型。
- tuple:元组类型。
- set:集合类型。
- dict:字典类型。
- frozenset:不可变集合类型。
- bool:布尔类型。
参考链接: