Python进阶知识(四)

这篇具有很好参考价值的文章主要介绍了Python进阶知识(四)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.Python并发编程之Futures

在Python中,concurrent.futures模块提供了一种简单而强大的并发编程方式,称为"Futures"。它基于线程池(ThreadPoolExecutor)和进程池(ProcessPoolExecutor)的概念,使并发任务的管理和执行更加方便。

使用concurrent.futures模块,你可以将任务提交给执行器(Executor),然后通过Future对象来跟踪任务的状态和结果。

下面是一个简单的示例,演示了如何使用concurrent.futures模块创建一个线程池,并使用submit()方法提交任务给执行器,然后使用result()方法获取任务的结果:

pythonCopy code
from concurrent import futures

def task(name):
    print(f"Executing task {name}")
    return f"Task {name} completed"

# 创建线程池
with futures.ThreadPoolExecutor() as executor:
    # 提交任务给执行器
    future1 = executor.submit(task, "A")
    future2 = executor.submit(task, "B")

    # 获取任务结果
    result1 = future1.result()
    result2 = future2.result()

    print(result1)
    print(result2)

在上面的示例中,task()函数是一个简单的任务函数,接受一个参数name,并返回一个字符串表示任务完成。我们使用ThreadPoolExecutor()创建了一个线程池执行器,并使用submit()方法提交了两个任务(“A"和"B”)给执行器。

通过result()方法,我们可以获取任务的结果。注意,result()方法是一个阻塞调用,直到任务完成并返回结果。

concurrent.futures模块还提供了其他一些方法和功能,例如map()方法用于批量提交任务、as_completed()方法用于迭代已完成的任务、wait()方法用于等待多个任务的完成等。这些功能可以根据具体需求进行使用。

总结来说,Python的concurrent.futures模块提供了一种便捷的方式来实现并发编程,利用线程池和进程池来管理和执行任务。这可以帮助提高程序的性能和响应性,特别是在需要并行处理多个任务的场景下。

1 import concurrent.futures
2 import requests
3 import threading
4 import time
5
6 def download_one(url):
7 resp = requests.get(url)
8 print('Read {} from {}'.format(len(resp.content), url))
9
10
11 def download_all(sites):
12 with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
13      executor.map(download_one, sites)
14
15 def main():
16    sites = [
17     'https://en.wikipedia.org/wiki/Portal:Arts',
18     'https://en.wikipedia.org/wiki/Portal:History',
19     'https://en.wikipedia.org/wiki/Portal:Society',
20     'https://en.wikipedia.org/wiki/Portal:Biography',
21     'https://en.wikipedia.org/wiki/Portal:Mathematics',
22     'https://en.wikipedia.org/wiki/Portal:Technology',
23     'https://en.wikipedia.org/wiki/Portal:Geography',
24     'https://en.wikipedia.org/wiki/Portal:Science',
25     'https://en.wikipedia.org/wiki/Computer_science',
26     'https://en.wikipedia.org/wiki/Python_(programming_language)',

29     'https://en.wikipedia.org/wiki/PHP',
30     'https://en.wikipedia.org/wiki/Node.js',
31     'https://en.wikipedia.org/wiki/The_C_Programming_Language',
32     'https://en.wikipedia.org/wiki/Go_(programming_language)'
33      ]
34 start_time = time.perf_counter()
35 download_all(sites)
36 end_time = time.perf_counter()
37 print('Download {} sites in {} seconds'.format(len(sites), end_time - start_t
38
39 if __name__ == '__main__':
40 main()
41
42 ## 输出
43 Read 151021 from https://en.wikipedia.org/wiki/Portal:Mathematics
44 Read 129886 from https://en.wikipedia.org/wiki/Portal:Arts
45 Read 107637 from https://en.wikipedia.org/wiki/Portal:Biography
46 Read 224118 from https://en.wikipedia.org/wiki/Portal:Society
47 Read 184343 from https://en.wikipedia.org/wiki/Portal:History
48 Read 167923 from https://en.wikipedia.org/wiki/Portal:Geography
49 Read 157811 from https://en.wikipedia.org/wiki/Portal:Technology
50 Read 91533 from https://en.wikipedia.org/wiki/Portal:Science
51 Read 321352 from https://en.wikipedia.org/wiki/Computer_science
52 Read 391905 from https://en.wikipedia.org/wiki/Python_(programming_language)
53 Read 180298 from https://en.wikipedia.org/wiki/Node.js
54 Read 56765 from https://en.wikipedia.org/wiki/The_C_Programming_Language
55 Read 468461 from https://en.wikipedia.org/wiki/PHP
56 Read 321417 from https://en.wikipedia.org/wiki/Java_(programming_language)
57 Read 324039 from https://en.wikipedia.org/wiki/Go_(programming_language)

上面代码我们创建了一个线程池,总共有 5 个线程可以分配使用。executer.map() 与前面所讲的 Python 内置的 map() 函数类似,表示对 sites 中的每一个元素,并发地调用函数download_one()

2.Python 垃圾回收机制

在Python中,计数引用是一种内存管理技术,通过跟踪对象的引用数量来确定何时释放对象所占用的内存空间。Python使用垃圾回收机制来处理不再被引用的对象,以确保内存的有效使用。

计数引用的基本原理是每个对象都有一个计数器,用于记录当前对象被引用的次数。当一个对象被引用时,计数器加1;当一个对象的引用被删除时,计数器减1。当对象的计数器为0时,即没有任何引用指向该对象,垃圾回收机制会将该对象标记为垃圾并释放其占用的内存。

Python的计数引用机制是自动的,开发者无需显式地处理计数器。Python解释器会在合适的时机自动执行垃圾回收操作。这意味着当对象的引用计数归零时,它会被垃圾回收器自动释放,无需手动释放内存。

然而,有时候在Python中会出现循环引用的情况,即多个对象之间形成了相互引用,而没有外部引用指向它们。这种情况下,对象的引用计数永远不会归零,导致垃圾回收机制无法回收这些对象。为了解决循环引用带来的内存泄漏问题,Python引入了更高级的垃圾回收机制,称为"分代垃圾回收"(generational garbage collection)。

分代垃圾回收将对象根据其存活时间划分为不同的代(generation),并在不同的时机执行垃圾回收操作。通常,新创建的对象会被放入第0代,随着时间的推移,存活下来的对象会被转移到更高的代。垃圾回收机制会优先处理年轻代的对象,只有当某个代中的对象存活时间足够长时,才会触发垃圾回收操作。

Python的计数引用是一种基于引用计数的内存管理技术,通过追踪对象的引用数量来决定何时释放对象的内存空间。垃圾回收机制负责处理不再被引用的对象,并确保内存的有效使用。对于循环引用的情况,Python引入了分代垃圾回收机制来解决内存泄漏问题。

当一个对象不再被引用时,Python的计数引用机制会自动回收该对象的内存空间。下面是一些示例,说明Python的计数引用是如何工作的:

示例 1:

pythonCopy code
# 创建一个对象
x = [1, 2, 3]

# 创建一个引用指向同一个对象
y = x

# 删除一个引用
del x

# 此时,只有y引用指向对象
# 当y也被删除时,对象的引用计数归零,内存被回收
del y

在上面的示例中,我们创建了一个列表对象 [1, 2, 3] 并将变量 x 指向它。然后,我们又创建了变量 y 并将其指向同一个对象。当我们删除变量 x 时,引用计数减1,但对象仍然存在,因为变量 y 仍然指向它。最后,当我们删除变量 y 时,对象的引用计数归零,垃圾回收器将回收该对象的内存空间。

示例 2:

pythonCopy code
# 创建一个循环引用
a = [1, 2]
b = [a]

# 将循环引用构成闭环
a.append(b)

# 删除所有引用
del a
del b

在上面的示例中,我们创建了两个列表对象 ab。然后,我们将列表 a 作为元素添加到列表 b 中,并将列表 b 设置为列表 a 的最后一个元素,形成了循环引用。即使我们删除变量 ab,对象之间的循环引用使得它们的引用计数永远不为零,垃圾回收器无法回收它们。为了解决这个问题,Python的分代垃圾回收机制会定期检查这些循环引用,识别并回收无法访问的对象。

事实上,Python 本身能够处理这种情况,我们刚刚讲过的,可以显式调用 gc.collect() ,来 启动垃圾回收。

Python 使用标记清除(mark-sweep)算法和分代收集(generational),来启用针对循环 引用的自动垃圾回收。你可能不太熟悉这两个词,这里我简单介绍一下。

先来看标记清除算法。我们先用图论来理解不可达的概念。对于一个有向图,如果从一个节点
出发进行遍历,并标记其经过的所有节点;那么,在遍历结束后,所有没有被标记的节点,我
们就称之为不可达节点。显而易见,这些节点的存在是没有任何意义的,自然的,我们就需要
对它们进行垃圾回收。

当然,每次都遍历全图,对于 Python 而言是一种巨大的性能浪费。所以,在 Python 的垃圾 回收实现中,mark-sweep 使用双向链表维护了一个数据结构,并且只考虑容器类的对象(只 有容器类对象才有可能产生循环引用)。具体算法这里我就不再多讲了,毕竟我们的重点是关 注应用。而分代收集算法,则是另一个优化手段。

Python 将所有对象分为三代。刚刚创立的对象是第 0 代;经过一次垃圾回收后,依然存在的 对象,便会依次从上一代挪到下一代。而每一代启动自动垃圾回收的阈值,则是可以单独指定 的。当垃圾回收器中新增对象减去删除对象达到相应的阈值时,就会对这一代对象启动垃圾回 收。

事实上,分代收集基于的思想是,新生的对象更有可能被垃圾回收,而存活更久的对象也有更 高的概率继续存活。因此,通过这种做法,可以节约不少计算量,从而提高 Python 的性能。

3.Python上下文管理器

在Python中,上下文管理器(Context Manager)是一种用于管理资源的机制。它可以确保在进入和离开特定代码块时资源的正确获取和释放,无论是否发生异常。

上下文管理器通过定义__enter__()__exit__()方法来实现。__enter__()方法在进入代码块之前执行,负责获取资源或执行其他初始化操作。__exit__()方法在离开代码块时执行,负责释放资源或进行清理操作。

使用上下文管理器可以确保资源的正确释放,即使发生异常也能够执行必要的清理操作,避免资源泄漏。

Python提供了两种使用上下文管理器的方式:使用with语句和使用contextlib模块的装饰器。

使用with语句:

with open('file.txt', 'r') as file:
    # 执行文件操作
    content = file.read()
    print(content)
# 离开with代码块后,文件资源会被自动关闭

在上面的示例中,open()函数返回一个上下文管理器,它打开文件并返回文件对象。通过使用with语句,我们可以在代码块中使用文件对象,并在离开代码块时自动关闭文件资源,无需手动调用file.close()

使用contextlib模块的装饰器:

from contextlib import contextmanager

@contextmanager
def timer():
    start = time.time()
    yield
    end = time.time()
    print(f"Execution time: {end - start} seconds")

with timer():
    # 执行需要计时的代码块
    time.sleep(2)

在上面的示例中,我们使用contextlib模块的contextmanager装饰器定义了一个计时器的上下文管理器。通过使用with语句,我们可以在代码块中执行需要计时的操作,并在离开代码块时自动打印执行时间。

使用上下文管理器可以更方便地管理资源,确保资源的获取和释放在正确的时机执行。它是一种良好的编程实践,可以提高代码的可读性和健壮性。同时,Python也提供了一些内置的上下文管理器,例如文件对象、数据库连接等,在使用这些资源时可以直接使用with语句,简化了代码的编写。

4.Python数组的存储和处理Numpy模块

在Python中,NumPy(Numerical Python)是一个功能强大的库,用于处理大型、多维数组和矩阵,以及进行数值计算和科学计算。NumPy提供了高效的数组存储和处理功能,使得在Python中进行数值计算更加方便和高效。

下面是NumPy模块中数组的存储和处理的一些关键概念和功能:

4.1. NumPy数组(ndarray):

NumPy的核心数据结构是多维数组对象,称为ndarray(N-dimensional array)。它是一个固定大小的、相同类型的元素块集合。ndarray提供了高效的存储和操作多维数组数据的功能。

import numpy as np

# 创建一个一维数组
arr = np.array([1, 2, 3, 4, 5])
print(arr)
# 输出: [1 2 3 4 5]

# 创建一个二维数组
arr_2d = np.array([[1, 2, 3], [4, 5, 6]])
print(arr_2d)
# 输出:
# [[1 2 3]
#  [4 5 6]]

4.2. 创建数组:

可以使用NumPy提供的函数来创建数组,例如numpy.array()numpy.zeros()numpy.ones()numpy.arange()等。这些函数可以接受列表、元组或其他序列作为输入,并生成对应的NumPy数组。

import numpy as np

# 创建一个长度为5的零数组
zeros_arr = np.zeros(5)
print(zeros_arr)
# 输出: [0. 0. 0. 0. 0.]

# 创建一个形状为(2,3)的二维数组,元素全为1
ones_arr = np.ones((2, 3))
print(ones_arr)
# 输出:
# [[1. 1. 1.]
#  [1. 1. 1.]]

# 创建一个从0到9的一维数组
range_arr = np.arange(10)
print(range_arr)
# 输出: [0 1 2 3 4 5 6 7 8 9]

4.3. 数组属性:

ndarray对象具有多个属性,例如shape表示数组的维度和大小,dtype表示数组的数据类型,size表示数组中元素的总数等。

import numpy as np

arr = np.array([[1, 2, 3], [4, 5, 6]])
print(arr.shape)
# 输出: (2, 3)

print(arr.dtype)
# 输出: int64

print(arr.size)
# 输出: 6

4.4 数组索引和切片:

可以使用索引和切片操作来访问和修改数组中的元素。NumPy数组的索引从0开始,可以使用整数索引、切片、布尔索引等方式进行数据的访问和操作。

import numpy as np

arr = np.array([1, 2, 3, 4, 5])

print(arr[0])
# 输出: 1

print(arr[2:4])
# 输出: [3 4]

arr[3] = 10
print(arr)
# 输出: [ 1  2  3 10  5]


4.5. 数组运算:

NumPy提供了丰富的数学和逻辑运算函数,可以对数组进行元素级的数值计算,例如加法、减法、乘法、除法、求和、平均值、最大值、最小值等。这些运算可以对整个数组或数组的特定轴进行操作。

import numpy as np

arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])

# 元素级加法
result = arr1 + arr2
print(result)
# 输出: [5 7 9]

# 元素级乘法
result = arr1 * arr2
print(result)
# 输出: [ 4 10 18]

# 求和
sum_result = np.sum(arr1)
print(sum_result)
# 输出: 6

# 平均值
mean_result = np.mean(arr2)
print(mean_result)
# 输出: 5.0

# 最大值
max_result = np.max(arr1)
print(max_result)
# 输出: 3

# 最小值
min_result = np.min(arr2)
print(min_result)
# 输出: 4

4.6. 广播(Broadcasting):

NumPy的广播功能允许不同形状的数组进行算术运算,自动地将较小的数组广播(复制)到较大数组的大小,以匹配形状,并执行运算。

import numpy as np

arr1 = np.array([1, 2, 3])
arr2 = np.array([[4], [5], [6]])

result = arr1 + arr2
print(result)
# 输出:
# [[5 6 7]
#  [6
在上述示例中,数组arr1是一个2x3的数组,数组arr2是一个长度为3的一维数组。由于维度不匹配,但符合广播的规则,NumPy会自动将较小的数组arr2扩展为与arr1的形状相同,然后进行元素级的加法运算。

4.7. 数组的文件操作:

NumPy提供了函数来读取和写入数组数据到文件,例如numpy.save()numpy.load()。这使得数据的持久化和共享变得更加方便。

import numpy as np

arr = np.array([1, 2, 3, 4, 5])

# 将数组保存到文件
np.save('array.npy', arr)

# 从文件加载数组
loaded_arr = np.load('array.npy')
print(loaded_arr)
# 输出: [1 2 3 4 5]
在上面的示例中,我们使用np.save()函数将数组arr保存到名为array.npy的文件中。然后,使用np.load()函数从文件中加载数组并将其存储在loaded_arr变量中。

4.8. 高级数组操作:

NumPy还提供了其他高级的数组操作,例如数组的转置、重塑、排序、去重、聚合函数、线性代数运算、统计分析函数等。

通过利用NumPy模块,你可以高效地存储和处理大规模的数值数据,进行各种数学和科学计算,包括矩阵运算、信号处理、图像处理、统计分析、机器学习等领域。NumPy的广泛应用使得Python成为了一种强大的数值计算和科学计算语文章来源地址https://www.toymoban.com/news/detail-500373.html

import numpy as np

arr = np.array([[3, 2, 1], [4, 5, 6]])

# 转置数组
transposed_arr = arr.T
print(transposed_arr)
# 输出:
# [[3 4]
#  [2 5]
#  [1 6]]

# 重塑数组
reshaped_arr = arr.reshape(3, 2)
print(reshaped_arr)
# 输出:
# [[3 2]
#  [1 4]
#  [5 6]]

# 对数组进行排序
sorted_arr = np.sort(arr)
print(sorted_arr)
# 输出:
# [[1 2 3]
#  [4 5 6]]

# 去除数组中的重复元素
unique_arr = np.unique(arr)
print(unique_arr)
# 输出: [1 2 3 4 5 6]

# 矩阵乘法
mat1 = np.array([[1, 2], [3, 4]])
mat2 = np.array([[5, 6], [7, 8]])
mat_multiply = np.dot(mat1, mat2)
print(mat_multiply)
# 输出:
# [[19 22]
#  [43 50]]
上述示例展示了NumPy模块中一些高级数组操作的用法。这些功能包括转置数组、重塑数组、排序数组、去重数组和矩阵乘法等。它们提供了更灵活和强大的数组处理功能,可以满足复杂的数值计算和科学计算需求。

到了这里,关于Python进阶知识(四)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java进阶篇--并发编程的优点&缺点

    目录 并发编程的优点缺点 为什么要使用并发编程(优点): 并发编程的缺点: 频繁的上下文切换 线程安全 易混淆的概念 阻塞与非阻塞 阻塞模型 非阻塞模型 同步与异步 同步调用 异步调用 临界区 并发与并行 上下文切换 并发编程是指在程序中同时执行多个独立的任务或操

    2024年02月11日
    浏览(34)
  • 并发编程基础知识篇--并发编程的优点&缺点

    目录 并发编程的优点缺点 为什么要使用并发编程(优点): 并发编程的缺点: 频繁的上下文切换 线程安全 易混淆的概念 阻塞与非阻塞 阻塞模型 非阻塞模型 同步与异步 同步调用 异步调用 临界区 并发与并行 上下文切换 并发编程是指在程序中同时执行多个独立的任务或操

    2024年02月11日
    浏览(35)
  • Go 语言并发编程 及 进阶与依赖管理

    协程可以理解为 轻量级线程 ; Go更适 合高并发场景原因 之一: Go语言 一次可以创建上万协成 ; “快速”: 开多个协成 打印。 go func() : 在 函数前加 go 代表 创建协程 ; time.Sleep() : 协程阻塞,使主协程 在 子协程结束前阻塞不退出 ; 乱序输出 说明并行 ; 通过通信共享内

    2024年02月13日
    浏览(38)
  • [AIGC] 深入理解Java并发编程:从入门到进阶

    在计算机领域中,针对多核处理器的高并发需求,Java并发编程成为了一项重要的技能。Java提供了丰富的并发编程工具和API,使得开发者能够有效地利用多核处理器的优势。本文将介绍Java并发编程的基础概念、常用技术和最佳实践,帮助读者深入理解Java并发编程。 线程和进

    2024年01月21日
    浏览(37)
  • 并发编程的基础知识

    并发编程的优缺点 充分利用多核CPU的计算能力:通过并发编程的形式可以将多核CPU的计算能力发挥到极致,性能得到提升 方便进行业务拆分,提升系统并发能力和性能:在特殊的业务场景下,先天的就适合于并发编程。现在的系统动不动就要求百万级甚至千万级的并发量,

    2024年02月06日
    浏览(29)
  • 复习并发编程的基础知识(一)

    目录 进程和线程 并发和并行  如何创建一个线程? 1,继承Thread类  2,实现Runnable接口          3. Callable接口 线程Thread类的一些重要方法  守护线程: 时间长了,并发编程的基础知识总忘,来记录一下: 进程和线程 进程:资源分配的最小单元,什么是资源?CPU,内存,网

    2024年02月08日
    浏览(41)
  • java并发编程:多线程基础知识介绍

    最初的计算机只能接受一些特定的指令,用户每输入一个指令,计算机就做出一个操作。当用户在思考或者输入时,计算机就在等待。这样效率非常低下,在很多时候,计算机都处在等待状态。 后来有了 批处理操作系统 ,把一系列需要操作的指令写下来,形成一个清单,一次

    2024年02月07日
    浏览(40)
  • Python多线程与线程池(python线程池ThreadPoolExecutor)concurrent.futures高级别异步执行封装

    在进行复杂的计算或处理大量数据时,可以通过创建多个线程来同时执行多个任务,从而提高程序的执行效率。这种技术称为多线程编程。 1.1 线程简介 线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一

    2024年02月12日
    浏览(26)
  • python:并发编程(十六)

    本文将和大家一起探讨python并发编程的实际运用,会以一些我实际使用的案例,或者一些典型案例来分享。本文使用的案例是我实际使用的案例 (上篇) ,是基于之前效率不高的代码改写成并发编程的。让我们来看看改造的过程,这样就会对并发编程的高效率有个清晰地认

    2024年02月09日
    浏览(28)
  • python:并发编程(十二)

    本文将和大家一起探讨python的多协程并发编程 (下篇) ,使用内置基本库asyncio来实现并发,先通过官方来简单使用这个模块。先打好基础,能够有个基本的用法与认知,后续文章,我们再进行详细使用。 本文为python并发编程的第十二篇,上一篇文章地址如下: python:并发

    2024年02月09日
    浏览(24)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包