欢迎使用我们高级Python编程指南的第2部分!初学者教程涵盖了语法,数据结构,功能,类和模块等核心概念。
现在,让我们更深入地研究一些经验丰富的Python开发人员使用的技术。本指南假定您已经对Python基本知识有很强的掌握。
面向对象的设计原理
python支持面向对象的编程,使开发人员可以将代码整理到类层次结构中,并以现实世界实体进行建模。
掌握OOP技术是在Python设计和构建强大的大规模应用的关键。
一些关键面向对象的设计原理:
- 封装
这涉及将相关的属性和行为捆绑到单个类中。例如,一个人的班级将封装诸如姓名,年龄和行走和说话之类的行为之类的属性。
封装允许通过定义明确的接口以及信息隐藏对数据进行控制。方法充当接口,而属性则保持私密以隐藏复杂性。
- 继承
类可以继承父母类的常用状态和行为。例如,学生班可以从基础课程中继承,以避免重写重复的代码。儿童课只需要定义学生独有的属性和方法。
继承可以重复使用代码和多态性。子类可以根据需要扩展,覆盖或修改继承的逻辑。
- 抽象
这涉及仅通过公共接口揭示相关的数据/方法,同时隐藏不必要的实现详细信息。例如,抽象类形状可以定义一个区域()方法,而混凝土子类圆圈则实现实际区域计算。
抽象可通过分离高级和低级逻辑来降低复杂性,并散发夫妻代码。接口有助于维持抽象。
- 作曲
这是指将对象组合到建模复杂行为。对象可以通过构图使用其他对象,而不是单独依靠继承。例如,汽车类可以组成轮子或发动机等物体,而不是直接继承其功能。
构图为复杂对象交互提供了灵活性和封装。
遵循这些原则,Python程序可以以有组织的,面向对象的方式实现域实体和业务逻辑。让我们看一些示例。
我们将使用遗传,多态性,封装和组成的动物,动物园管理员和围栏建模动物园管理系统:
# Animal base class
class Animal:
def __init__(self, name, species):
self.name = name
self.species = species
def make_sound(self):
print(f"{self.name} says Rawwwr!")
# Inherited child classes
class Lion(Animal):
def make_sound(self):
print(f"{self.name} says Roar!")
class Snake(Animal):
def make_sound(self):
print(f"{self.name} says Hiss!")
# Zookeeper class
class Zookeeper:
def __init__(self, name):
self.name = name
def feed_animal(self, animal):
print(f"{self.name} is feeding the {animal.species} named {animal.name}")
animal.make_sound() # Polymorphism
# Enclosure class
class Enclosure:
def __init__(self, id, animals):
self.id = id
self.animals = animals
def add_animal(self, animal):
self.animals.append(animal)
# Create objects
leo = Lion("Leo", "Lion")
marty = Snake("Marty", "Python")
bob = Zookeeper("Bob")
snakes_enclosure = Enclosure(123, [marty])
bob.feed_animal(leo)
snakes_enclosure.add_animal(leo)
这证明了具有封装,继承,多态性和组成的建模域实体。改进了代码重用,耦合减少并维护抽象。
Python装饰师
装饰器动态更改功能,方法或类的功能,而无需直接修改代码。它们本质上包裹原始对象并根据需要修改其行为。
装饰器以 @符号开头,并放置在定义上。例如:
@timer
def run_long_job(args):
# Function body
这里@Timer是一种装饰器,可测量Run_long_job需要多长时间执行。
让我们看看如何构建此计时器装饰器:
import time
def timer(func):
# Inner wrapper function
def inner(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"Execution took {end-start} seconds")
return result
# Return inner function
return inner
@timer
def long_running_job(n):
print("Running long job...")
time.sleep(n)
return "Done!"
long_running_job(5)
# Prints execution time
装饰时,long_running_job行为会随着计时器功能扩展而无需修改代码。
其他一些示例将案例用于python装饰器:
- 记录函数参数和结果
- 执行功能之前检查权限或角色
- 缓存返回值以避免重新计算
- 费率限制功能调用
- 用于追踪或概要分析的仪器代码
- 验证输入数据类型
装饰器增压python具有元编程功能和表现力。它们被广泛使用在瓶,django等框架中。了解装饰器解锁了强大的功能。
Python中的并发
并发是指通过并行化或异步编程同时执行多个任务。 Python支持各种并发模型,以提高程序效率和速度。
一些方法包括:
- 线程
线程允许在同一解释器过程中并行执行代码。操作系统计划跨内核执行。
对于IO结合的任务,线程可以改善否则将花费等待的空闲时间的利用率。线程模块支持产卵和同步线程:
from threading import Thread
def io_bound_worker():
# Perform IO intensive work
threads = [Thread(target=io_bound_worker) for _ in range(8)]
for thread in threads:
thread.start()
# Main thread continues executing
多处理
对于CPU结合的任务,Python的多处理模块在多个过程中分发工作。每个CPU核心运行一个单独的Python解释器,绕过GIL限制。
过程的开销高于线程,但可以在多个CPU中实现真正的并行性:
from multiprocessing import Process
def cpu_bound_worker(data):
# Perform heavy computations
if __name__ == "__main__":
inputs = [large_dataset] * 8
processes = []
for input_data in inputs:
p = Process(target=cpu_bound_worker, args=(input_data,))
processes.append(p)
p.start()
# Rest of main process code executes in parallel
异步
该模块提供了使用异步/等待语法编写异步代码的基础架构。它非常适合涉及网络I/O和并发的任务:
import asyncio
async def fetch_data(url):
# Async HTTP request
response = await aiohttp.request(url)
return response
async def main():
urls = [url1, url2, url3]
tasks = []
for url in urls:
tasks.append(fetch_data(url))
results = await asyncio.gather(*tasks)
asyncio.run(main())
Asyncio通过有效处理数千个并发连接来帮助构建高性能的网络应用程序。
conturrent.futures
此高级模块摘要线程和过程池,用于异步执行可可:
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
futures = [executor.submit(cpu_bound_fn, arg) for arg in args]
results = [f.result() for f in futures]
未来对象提供了一个干净的接口,以等待和检索结果。该模块处理引擎盖下的合并和并发。
这些方法使Python开发人员能够通过并行性加速程序,使用多个内核并处理数千个并发连接。
用元素元编程
当Python中的类启用了多个对象的创建时,Metaclasses允许您自定义如何在元级别构造和修改类本身。
metaclasses拦截了类创建并在最终确定类之前修改类别。例如,在注册表中自动注册模型,应用Mixins,与ORMS进行接口等。
要使用元素,定义基本类型和覆盖 new 和 init 方法:
class RegistryMeta(type):
registry = {}
def __new__(cls, name, bases, attrs):
# Modify attrs
attrs['id'] = len(RegistryMeta.registry)
# Build class as normal
klass = type.__new__(cls, name, bases, attrs)
# Register class
RegistryMeta.registry[klass.id] = klass
return klass
def __init__(self, name, bases, attrs):
print(f"Initializing {name} class")
super().__init__(name, bases, attrs)
Any class inheriting this metaclass will be intercepted and registered:
class Base(metaclass=RegistryMeta):
pass
class Person(Base):
pass
print(RegistryMeta.registry)
# {0: <class '__main__.Base'>, 1: <class '__main__.Person'>}
元素为Python的班级施工过程打开了强大的元编程功能和自定义挂钩。
动态属性访问
与静态键入的语言不同,Python使对象能够在运行时动态添加属性,超出了 Init 或类中其他位置的明确定义的属性。
。例如:
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
p = Point(2, 3)
p.z = 5 # New attribute created dynamically
print(p.z)
# Outputs 5
在某些情况下,这种动态行为可能很有用:
- 将缓存作为属性
- 懒惰地创建属性
- 代理或委托类,将属性访问访问
- 动态混合物,将功能添加到类的功能
但是,它也可能使代码更难理解和跟踪,因为属性未事先明确定义。
python支持插槽魔术方法限制这种行为。它告诉python只是允许在此列出的属性并为其他任何事物提出属性:
class Point:
__slots__ = ['x', 'y']
p = Point(2, 3)
p.z = 5 # AttributeError!
so 插槽防止了动态属性的惊喜行为。
描述符协议
此高级协议提供了属性和方法在Python中如何工作的基本机制。
描述符基本上控制对象上的属性访问。它们被实现为包含 get 的类, set 和 delete 方法。
例如,@property装饰器通过描述符来工作:
class Property:
def __init__(self, fget):
self.fget = fget
def __get__(self, obj, owner):
return self.fget(obj)
class Point:
def __init__(self, x):
self.x = x
@Property
def y(self):
return self.x * 2
p = Point(10)
print(p.y) # Calls getter internally
在这里,属性描述符类实现 get 以访问属性时调用基础y方法。
描述符的其他一些示例:
- @classmethod和@staticmethod定义不同的方法类型
- @memoized到缓存方法返回值
- __ slots__限制属性
- ORM框架将DB行映射到Python对象
描述符协议是一种关键要素,它可以启用Python的大部分魔术,例如@property,类方法,静态方法等。掌握描述符可以解锁更深的功能。
上下文经理
当带有语句提供简单的文件清理逻辑时,Python启用了通过上下文管理者为任何对象实现相同的模式。
例如,获取和发布锁定或数据库连接:
class Resource:
def __enter__(self):
print("Acquiring resource")
def __exit__(self, exc_type, exc_val, exc_tb):
print("Releasing resource")
with Resource() as resource:
# Use resource
这可以通过退出方法确保可靠的清理。上下文经理还可以在清理过程中抑制异常:
class Resource:
# ...
def __exit__(self, exc_type, exc_val, exc_tb):
print("Handling exception")
# suppress exception by returning True
return True
上下文Lib模块提供了@ContextManager之类的实用程序来简化创建上下文管理器。
一些现实世界中的示例包括:
- 文件打开
- 锁定/释放
- 数据库连接
- 临时目录处理
- 记录重定向到缓冲区
上下文经理提供了一种强大的方法来处理Python的资源。
单元测试
编写测试对于验证代码质量并确保随着代码库的增长而正确行为至关重要。 Python配备了用于创作和运行单元测试的内置联合框架。
关键组件是测试用例类,单个测试方法,断言和测试跑者:
import unittest
class UserTestCase(unittest.TestCase):
# Setup run before each test method
def setUp(self):
self.user = User("John", "Doe")
def test_full_name(self):
self.assertEqual(self.user.full_name(), "John Doe")
def test_initials(self):
self.assertEqual(self.user.initials(), "J.D")
@unittest.expectedFailure
def test_send_email(self):
self.user.send_email("test@example.com")
if __name__ == "__main__":
unittest.main() # Run all tests
这允许将相关测试组织到可重复使用的测试用例中。灯具,断言,模拟和测试跑步者等功能。
其他一些Python测试工具包括用于简化体验的Pytest和用于隔离代码依赖项的模拟。
从长远来看,彻底的测试可改善代码质量并减少错误。测试使开发人员能够快速重构和迭代。
发电机和迭代器
生成器允许暂停和恢复执行,以通过懒惰地单独产生一系列值。这对于:
很有用- 处理大型数据集而不将所有内容加载到内存中
- 实施流和有效管道
- 避免渴望分配资源,直到需要
在python中,使用产量而不是返回来定义发电机:
def num_sequence(n):
for i in range(n):
yield i
seq = num_sequence(3)
print(next(seq)) # 0
print(next(seq)) # 1
调用时,生成器返回支持迭代协议的生成器对象。懒惰迭代启用有效的流式流:
def read_log_file(file):
for line in open(file):
yield process(line)
for event in read_log_file("logs.txt"):
print(event)
发电机允许优雅地实现Python迭代器。诸如Django Orm之类的流行库将其广泛用于懒惰查询。
异步编程
python 3.5使用asyncio引入异步/等待语法,以本性支持异步代码:
import asyncio
async def fetch(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.text()
async def main():
urls = ["url1", "url2", "url3"]
tasks = []
for url in urls:
tasks.append(fetch(url))
results = await asyncio.gather(*tasks)
print(results)
asyncio.run(main())
Asyncio提供了一个事件循环,以有效地协调并发任务和异步I/O。它非常适合高度并行网络程序。
Python键入
类型提示允许添加静态类型以函数参数并返回静态分析的值:
from typing import List
def sum_numbers(nums: List[int]) -> int:
return sum(nums)
此元数据可实现更好的错误捕获,IDE自动完成和文档。该代码仍然像往常一样动态运行。
流行的第三方工具(例如Mypy利用这些类型的提示)为Python提供可选的静态型检查。键入将静态语言的一些好处带到python。
Python包装
Python代码通常组织成模块或软件包。 Python包装索引(PYPI)包含数千个具有功能超出标准库的功能的开源包。
构建Python代码的一些最佳实践供其他代码:
- 使用SRC和测试文件夹的设置项目结构
- 写setup.py脚本以安装PIP
- 包括依赖关系的要求。txt
- 遵循版本的语义版本
- 上传包到PYPI进行公共共享
诗歌,flit和pipenv的工具,依赖和包装。共享可重复使用的软件包启用Python中的集体代码。
结论
这是我们现代Python高级指南的结论。我们涵盖了重要技术,例如:
- 面向对象的编程原理
- 用元素和装饰器的元编程
- 通过并发提高绩效
- 与上下文经理的强大资源处理
- 单元测试和维护代码质量
- 效率的懒惰序列
- 异步I/O处理
- 静态类型提示
- Python包装生态系统
这些功能可以在Python中开发大型,可靠的应用程序,库和框架。
关键始终是通过文档,书籍,开源代码,会议和尝试想法来继续学习。 Python有一个了不起的社区。p>
希望您喜欢阅读本指南,并有动力开始您的Python编程旅程。
如果您发现这篇文章令人兴奋,请在Learnhub Blog上找到更多令人兴奋的帖子;我们编写从Cloud computing到Frontend Dev,Cybersecurity,AI和Blockchain的所有技术。