python 用法小结及常见错误

环境信息

  • Python3

字符串转换为变量名

locals() 方法

>>> str1 = 666
>>> a = 'str1'
>>>
>>>
>>> locals()[a]
666

vars() 方法


>>>
>>> str1 = 666
>>> a = 'str1'
>>>
>>>
>>>
>>> vars()[a]
666
>>>

eval() 方法

>>> str1 = 666
>>> a = 'str1'
>>>
>>>
>>> eval(a)
666

yield

yield 指令和 return 相似,都是用来在函数中返回。使用 yield 关键字创建生成器函数时,生成器函数并不会在传统意义上 返回 。相反,生成器函数在遇到 yield 语句时会暂停其执行,并返回一个值给调用者。生成器函数的状态会被保存,因此在下一次调用时,它可以从暂停的地方继续执行。

yield 指令 将函数转换成生成器( Generator ,它在函数中产生一个值,然后暂停函数并保存其状态(下一次调用函数会从此状态恢复执行),再次恢复执行时再生成(返回) yield 的值。

每次调用生成器函数时,并不会立即执行,会创建一个新的生成器对象。

第一次使用 next() 或在 for 循环中开始迭代生成器时,生成器函数开始执行,直到遇到第一个 yield 语句。 yield 会暂停生成器函数的执行,并将一个值返回给调用者。再次调用 next() 或继续迭代( for )时,生成器函数从上次暂停的 yield 处继续执行,直到遇到下一个 yield 语句或执行结束。

生成器函数在没有 yield 语句时结束执行,相当于隐式地在最后一个 yield 语句之后遇到 return

当生成器函数结束时,进一步调用 next() 会引发 StopIteration 异常,表示生成器中的值已被全部生成。

yield 有以下优点:

  • 能够以更高效的方式处理大量数据,因为它不需要一次性将所有数据存储在内存中。 通过减少内存消耗,提高程序性能。
  • 它提供了一种新的方法来控制函数的执行流程,使得函数可以在任意点暂停和恢复。 生成器函数在被暂停后(遇到 yield )不会继续执行,直到再次调用 next() 或通过迭代器进行迭代( for )。

yield 读取大文本数据

在处理大文本数据(如超过 10G)时,如果一次性读取所有文本内容,在可用内存较小的情况下可能出现内存不足导致程序执行失败。这时候可以考虑使用 yield 来批量加载数据。

定义如下函数读取文件内容:

def read_large_file(file_path):
"""
Generator function to read a large file line by line.
"""
with open(file_path, 'r') as file:
for line in file:
yield line

使用以下方法使用大文本中的数据

  1. next 方法。调用生成器函数( read_large_file ),会返回一个 Generator 对象,通过 next() 方法会迭代调用生成器的下一个值( yield 表达式的值)

    file_path = 'large_file.txt'

    # next 方法: 首先
    line = read_large_file(file_path)

    next(line) # 返回第一行
    next(line) # 返回第二行,以此类推可以读取所有行

  2. for 循环。调用生成器函数返回一个生成器对象,这个对象实现了迭代器协议。

    def read_large_file(file_path):
    """
    Generator function to read a large file line by line.
    """
    with open(file_path, 'r') as file:
    for line in file:
    yield line

    # Usage example
    file_path = 'large_file.txt'
    for line in read_large_file(file_path):
    print(line.strip())

分批读取大文件中的数据

在处理大文件的过程中,如果需要批量多行读取文件内容,参考以下代码

def read_file_in_chunks(file_path, chunk_size=1024):
"""
Generator function to read a file in chunks.
"""
with open(file_path, 'r') as file:
while True:
chunk = file.readlines(chunk_size)
if not chunk:
break
for line in chunk:
yield line

# Usage example
file_path = 'large_file.txt'
for line in read_file_in_chunks(file_path):
print(line.strip())

enumerate

enumerate 是 Python 内置函数之一,用于遍历可迭代对象(如列表、元组或字符串)时获取元素和对应的索引。

语法 :

enumerate(iterable, start=0)
  • iterable : 任何可迭代对象(如列表、字符串、元组、文件对象等)。
  • start : 索引的起始值,默认为 0 。如果要让索引号从 1 开始,配置 start=1
# 示例列表
>>> fruits = ['apple', 'banana', 'cherry']

# 使用 enumerate 获取元素及其索引
>>> for index, fruit in enumerate(fruits):
... print(index, fruit)
...
0 apple
1 banana
2 cherry
>>>


# 使用 enumerate 获取元素及其索引,并将起始索引改为 1
>>> for index, fruit in enumerate(fruits, start=1):
... print(index, fruit)
...
1 apple
2 banana
3 cherry

# 使用 enumerate 获取文件中的行号及其内容
>>> f = open('temp_file')
>>> for line_number, line in enumerate(f):
... print(line_number, line)
...
0 85d37fac5cc284914b5d6f79982942b8/Y1iY3k1U.ts

1 85d37fac5cc284914b5d6f79982942b8/Y1x0V8Rc.ts

2 85d37fac5cc284914b5d6f79982942b8/Y22fhGiC.ts

3 85d37fac5cc284914b5d6f79982942b8/Y3p95oau.ts

常见错误

NameError: name ‘null‘ is not defined

使用 evalstring 转化成 dict 时出错,经过排查,发现 string 数据中包含 null ,在转换时就会报错: NameError: name ‘null‘ is not defined

解决方法

使用 json 进行转换

try:
response_dict = eval(response)
except NameError:
response_dict = json.loads(str(response.decode()))