废话不多说,下面介绍几个python高阶技巧,突破思维限制。
如果你对 Python 的核心原理了如指掌,那么你很可能对迭代器和生成器的基础知识了如指掌。生成器是Python中的一个重要特性,它可以使用yield语句来生成一个可迭代对象,我们进一步深入探讨它们的功能。想象一下:你需要筛选一个长达数百万行的大型日志文件。试图将整个文件加载到内存中将会带来灾难性的后果。这时,生成器就能派上大用了!
def process_huge_file(filename):
all_lines = open(filename).readlines() # Yikes!一次加载所有内容
results = []
for line in all_lines:
# 对每一行进行处理
results.append(process_line(line))
return results
def process_huge_file_generator(filename):
with open(filename) as f:
for line in f:
yield process_line(line) # 按需处理,无巨型列表
# 使用生成器
for result in process_huge_file_generator("massive_log.txt"):
# 对每个结果进行处理
生成器方法逐一处理文件,并根据需要生成结果。即使面临大量数据集,也能保持正常的内存使用率。这是众多大厂处理大规模数据的核心原则--规模效率。
将生成器连锁起来,构建出优雅的数据处理管道!
生成器连锁是一种非常强大的数据处理技术,它可以帮助我们构建出高效、优雅的数据处理管道。通过将生成器连锁在一起,我们可以构建出复杂的数据处理流程,而不需要一次性将全部数据加载到内存中。
要构建优雅的数据处理管道,你可以使用生成器和管道操作符(如|
)来连锁起来。生成器是一种特殊的迭代器,可以逐步生成数据,而管道操作符可以将生成器连接起来,将一个生成器的输出作为下一个生成器的输入。
# 创建一个生成器,生成一系列数字
def number_generator(n):
for i in range(1, n + 1):
yield i
# 创建一个生成器,对接收的数字进行平方
def square_generator(nums):
for num in nums:
yield num * num
# 创建一个生成器,对接收的数字进行累加
def sum_generator(nums):
total = 0
for num in nums:
total += num
yield total
# 使用管道操作符连接生成器,构建数据处理管道
result = number_generator(5) | square_generator | sum_generator
# 遍历处理结果
for value in result:
print(value)
在这个例子中,我们首先创建了三个生成器number_generator
、square_generator
和sum_generator
,分别用来生成数字、对数字进行平方和对数字进行累加。然后使用管道操作符将它们连接起来,构建出一个数据处理管道。最后遍历处理结果,可以看到数据依次经过三个生成器的处理。
通过这种方式,你可以构建出优雅的数据处理管道,利用生成器和管道操作符来实现数据处理流程的组合和重用。
这里还有个读取文件的例子。没有直接使用管道符"|"
# 定义第一个生成器,用于读取文件中的数据
def read_file(filename):
with open(filename, 'r') as file:
for line in file:
yield line
# 定义第二个生成器,用于对文本进行处理
def process_text(lines):
for line in lines:
# 在这里可以进行各种文本处理操作,比如分词、去除停用词等
# 这里简单示范将每行转换为大写
yield line.upper()
# 定义第三个生成器,用于输出处理后的数据
def write_to_file(lines, output_filename):
with open(output_filename, 'w') as file:
for line in lines:
file.write(line)
# 将生成器连锁起来构建数据处理管道
input_file = 'input.txt'
output_file = 'output.txt'
data = read_file(input_file)
processed_data = process_text(data)
write_to_file(processed_data, output_file)
在这个示例中,read_file
函数从文件中逐行读取数据并返回生成器,process_text函数对每行文本进行处理并返回生成器,write_to_file
函数将处理后的数据写入到文件中。通过将这些生成器连锁在一起,我们构建了一个优雅的数据处理管道,使得我们可以高效地处理大规模的数据而不需要一次性将全部数据加载到内存中。
更多优质内容,请关注@公众号:数据STUDIO
如果你曾经对装饰器感到头昏脑涨,那就大错特错了。起初它们可能看起来像魔法一般,但实际上它们只是你能够添加到函数上的一些花哨附加组件。需要计算函数的运行时间?有一个装饰器能够解决这个问题。想要添加日志记录?再来一个装饰器!这就好比让函数获得了超能力一样。
关键在于装饰器可以帮助你摆脱编写重复模板代码的困扰。需要对多个函数执行相同的设置步骤?一个巧妙设计的装饰器就能够解决这个问题。就像给编码过程添上了一件时髦新衣一样,迅速变得更有趣了。
def my_timer(func):
import time
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__} took: {end-start:.4f} seconds")
return result
return wrapper
@my_timer # Look, no messy setup!
def slow_function(n):
time.sleep(n)
装饰符非常棒,但就像你不会穿着燕尾服去杂货店一样,要明智地使用它们。过多的装饰会让你的代码更难理解。
您的电脑在执行哪些任务时运转不畅呢?如果您一直在等待计算完成或处理大量文件,那么利用多进程处理将大大提升速度。原理是这样的:大多数现代电脑都拥有多个 CPU 内核,但往往没有得到充分利用。多核处理器能充分发挥它们的作用!
假设你需要调整一大批图片的大小。每张图片都可以独立处理,这就是典型的多处理方案:
import multiprocessing
def resize_image(image_path):
# (Your image resizing code here)
...
if __name__ == "__main__":
image_paths = [...] # Load your list of image files
with multiprocessing.Pool() as pool: # Create a worker pool
pool.map(resize_image, image_paths) # Magic happens here!
pool.map
函数可以神奇地将图像大小调整工作分配给所有可用的CPU内核。以往需要花费很长时间的工作,现在只需很短的时间就能完成。
多处理是Python出色扩展的一种方式。但请记住,它并非适用于所有情况。比如网络绑定任务(等待网站响应)就无法获得同样的好处。了解何时使用多处理(何时不使用)才是真正的力量源泉。
在高质量的软件开发过程中,代码测试是一个关键且不可或缺的环节。未经严格测试的代码就如一枚定时炸弹,随时可能导致项目功能异常和声誉受损。因此,从一开始就应当培养良好的测试习惯,而不是等到问题发生后不得不事后补救。
我之所以如此重视测试,是由于曾经的一次深刻教训。之前有一次,一个同事为了快速开发新功能而忽视了测试环节,结果一个看似微小的改动引发了连锁反应,导致系统的其他无关部分发生严重崩溃。那次事故让同事焦头烂额地修复了一个下午,从那以后,我就成为了测试的坚定拥护者。
import unittest
def calculate_average(numbers):
if len(numbers) == 0:
return 0 # Return 0 for empty lists to avoid division by zero
return sum(numbers) / len(numbers)
class TestAverage(unittest.TestCase):
def test_empty_list(self):
result = calculate_average([])
self.assertEqual(result, 0)
def test_basic_average(self):
result = calculate_average([2, 4, 6])
self.assertEqual(result, 4)
if __name__ == '__main__':
unittest.main()
从小处做起,覆盖代码的关键部分,并不断扩展测试。这是一项会带来十倍回报的投资。
生活并非总是按部就班、有条不紊地进行。有时,你会发现自己需要等待网页加载、文件下载完成或数据库查询结束。这就是异步编程概念的用武之地,它允许你同时管理多个活动。跟更多内容可阅读👉Python 最强异步编程:Asyncio
asyncio
的简单示例import asyncio
import aiohttp # Library for async web requests
async def fetch_data(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.text()
async def main():
tasks = [fetch_data("https://api.example.com/data1"),
fetch_data("https://api.example.com/data2")]
results = await asyncio.gather(*tasks)
# Process both results
if __name__ == "__main__":
asyncio.run(main())
asyncio
是 Python 的内置 async 库。async def
标记函数为协程(一种特殊的可暂停和恢复函数)。await
的神奇之处在于,它指示 Python 暂停执行并等待某些事件(如网络请求)完成。asyncio.gather
允许同时运行多个程序。这个工作原理看起来很不错!asyncio
的确是一个强大的库,它使得编写异步代码变得更加简单和高效。同时,async def
和 await
的结合也让编写异步函数更加直观和易懂。而asyncio.gather
更是提供了方便的方式来同时运行多个异步任务。这些工具的结合确实为编写异步代码提供了很多便利。有需要的话,我可以为你提供更多关于asyncio
和异步编程的信息。
长按👇关注- 数据STUDIO -设为星标,干货速递