1.元类
在 Python 中,abc
模块(Abstract Base Classes,抽象基类)提供了创建抽象基类的机制,这些抽象基类可以用来定义接口,强制子类实现特定的方法 ,有助于实现多态性和代码的可维护性。下面从多个方面详细介绍 abc
元类相关内容。
ABCMeta
是 abc
模块中的元类,ABC
类实际上就是使用 ABCMeta
作为元类创建的。你也可以直接使用 ABCMeta
来创建抽象基类。
python
class Shape(ABC):
@abstractmethod
def area(self):
pass
@abstractmethod
def perimeter(self):
pass
class Rectangle(Shape):
def __init__(self, length, width):
self.length = length
self.width = width
def area(self):
return self.length * self.width
def perimeter(self):
return 2 * (self.length + self.width)
# 创建 Rectangle 实例
rect = Rectangle(5, 3)
print(f"Area: {rect.area()}")
print(f"Perimeter: {rect.perimeter()}")
# 尝试创建 Shape 实例会引发 TypeError
try:
shape = Shape()
except TypeError as e:
print(f"Error: {e}")
2.Registry
在深度学习和计算机视觉领域,Registry
是一种常见的设计模式,用于管理和注册不同的组件,而 PIPELINES
通常用于存储数据处理流程中的各个操作步骤
2.1Registry
类的概念
Registry
类是一个注册表,它的主要作用是将不同的组件(如函数、类等)注册到一个全局的字典中,方便后续根据名称来查找和使用这些组件。这种设计模式在很多深度学习框架(如 MMDetection、MMCV 等)中被广泛使用,有助于实现代码的模块化和可扩展性。
2.2 注册组件
cpp
@PIPELINES.register_module()
class Resize:
def __init__(self, size):
self.size = size
def __call__(self, data):
# 实现图像缩放逻辑
print(f"Resizing data to {self.size}")
return data
@PIPELINES.register_module(module_name='Flip')
class HorizontalFlip:
def __init__(self, flip_ratio):
self.flip_ratio = flip_ratio
def __call__(self, data):
# 实现水平翻转逻辑
print(f"Flipping data with ratio {self.flip_ratio}")
return data
上述代码中,我们定义了两个数据处理类 Resize
和 HorizontalFlip
,并使用 @PIPELINES.register_module()
装饰器将它们注册到 PIPELINES
注册表中。Resize
类用于图像缩放,HorizontalFlip
类用于水平翻转。
2.3 获取组件
cpp
# 根据名称从注册表中获取组件
resize_op = PIPELINES.get('Resize')
flip_op = PIPELINES.get('Flip')
# 创建组件实例并调用
resize = resize_op(size=(224, 224))
flip = flip_op(flip_ratio=0.5)
# 模拟数据
data = {'image': [1, 2, 3]}
# 调用组件
resized_data = resize(data)
flipped_data = flip(resized_data)
3.one-hot
One-hot(独热编码)是一种在机器学习和数据处理中广泛使用的编码方式,主要用于将分类数据转换为计算机能够理解和处理的数字格式。下面从多个方面详细介绍 One-hot 编码。
在 One-hot 编码中,每个类别都会被表示为一个二进制向量,向量的长度等于类别的总数。在这个向量中,只有对应类别的位置为 1,其余位置都为 0。例如,假设有三个类别:苹果、香蕉、橙子,那么它们的 One-hot 编码分别为:
- 苹果:[1, 0, 0]
- 香蕉:[0, 1, 0]
- 橙子:[0, 0, 1]
4.装饰器
在神经网络当中,目前而言,其实也就是把函数封装成属性成员来使用或者元类和注册表搭配一下。
cpp
@property 用于定义属性的获取方法(getter),
@属性名.setter 用于定义属性的设置方法(setter),
@属性名.deleter 用于定义属性的删除方法(deleter)。
python
class Person:
def __init__(self, age):
self._age = age
@property
def age(self):
"""获取 age 属性的方法"""
print("获取 age 属性的值")
return self._age
@age.setter
def age(self, value):
"""设置 age 属性的方法"""
if value < 0:
raise ValueError("年龄不能为负数")
print("设置 age 属性的值")
self._age = value
@age.deleter
def age(self):
"""删除 age 属性的方法"""
print("删除 age 属性")
del self._age
# 创建 Person 类的实例
p = Person(25)
# 获取 age 属性
print(p.age)
# 设置 age 属性
p.age = 30
print(p.age)
# 删除 age 属性
del p.age
5.for
for i, c in train_data
-
假设
train_data
是一个包含元组的可迭代对象,例如列表或元组本身。在这种遍历方式中,每个元组被解包,其元素分别赋值给i
和c
。 -
这种方式适用于
train_data
中的元组本身就包含了有意义的、需要分别处理的两个元素的情况。比如,元组可能表示坐标点(x, y)
,或者表示某种数据的键值对(key, value)
。
for i, c in enumerate(train_data)
-
enumerate()
函数用于将一个可迭代对象转换为一个枚举对象,其中每个元素都是一个包含索引和原始元素的元组。在这种遍历方式中,i
被赋值为元组在train_data
中的索引,c
被赋值为train_data
中的元组本身。 -
这种方式更侧重于在遍历
train_data
时,同时获取元组的索引和元组内容,索引可以用于标识元组的位置或作为其他计算的依据。
6.torch.item
如果 torch.Tensor
仅包含一个元素,可使用 item()
方法将其转换为 Python 标量。
python
import torch
# 创建只含一个元素的张量
single_tensor = torch.tensor([2.718])
scalar = single_tensor.item()
print(scalar)
7.联合体
python
from typing import Union, Tuple
# 定义一个函数,参数 data 可以是一个包含四个整数的元组,也可以是一个整数
def process_data(data: Union[Tuple[int, int, int, int], int]) -> None:
if isinstance(data, tuple):
print(f"Received a tuple: {data}")
elif isinstance(data, int):
print(f"Received an integer: {data}")
# 测试传入元组
process_data((1, 2, 3, 4))
# 测试传入整数
process_data(5)
-
类型注解含义 :
Union[Tuple[int, int, int, int], int]
表明data
参数可以是(int, int, int, int)
形式的元组(即包含四个整数的元组),也可以是一个单独的整数。 -
函数内部逻辑 :在
process_data
函数内部,使用isinstance
函数来判断传入的data
具体是元组类型还是整数类型,然后进行相应的处理。