当前位置: 首页 > news >正文

python类元编程示例-使用类型注解来检查转换属性值的类框架

用三种方式实现使用类型注解来检查转换属性值的类框架

1 __init_subclass__方式

1.1 代码实现

from collections.abc import Callable  # <1>
from typing import Any, NoReturn, get_type_hints
from typing import Dict, Typeclass Field:def __init__(self, name: str, constructor: Callable) -> None:  # <2>if not callable(constructor) or constructor is type(None):  # <3>raise TypeError(f'{name!r} type hint must be callable')self.name = nameself.constructor = constructordef __set__(self, instance: Any, value: Any) -> None:if value is ...:  # <4>value = self.constructor()else:try:value = self.constructor(value)  # <5>except (TypeError, ValueError) as e:  # <6>type_name = self.constructor.__name__msg = f'{value!r} is not compatible with {self.name}:{type_name}'raise TypeError(msg) from einstance.__dict__[self.name] = value  # <7>class Checked:@classmethoddef _fields(cls) -> Dict[str, type]:  # <1>return get_type_hints(cls)def __init_subclass__(subclass) -> None:  # <2>super().__init_subclass__()           # <3>for name, constructor in subclass._fields().items():   # <4>setattr(subclass, name, Field(name, constructor))  # <5>def __init__(self, **kwargs: Any) -> None:for name in self._fields():             # <6>value = kwargs.pop(name, ...)       # <7>setattr(self, name, value)          # <8>if kwargs:                              # <9>self.__flag_unknown_attrs(*kwargs)  # <10>def __setattr__(self, name: str, value: Any) -> None:  # <1>if name in self._fields():              # <2>cls = self.__class__descriptor = getattr(cls, name)descriptor.__set__(self, value)     # <3>else:                                   # <4>self.__flag_unknown_attrs(name)def __flag_unknown_attrs(self, *names: str) -> NoReturn:  # <5>plural = 's' if len(names) > 1 else ''extra = ', '.join(f'{name!r}' for name in names)cls_name = repr(self.__class__.__name__)raise AttributeError(f'{cls_name} object has no attribute{plural} {extra}')def _asdict(self) -> Dict[str, Any]:  # <6>return {name: getattr(self, name)for name, attr in self.__class__.__dict__.items()if isinstance(attr, Field)}def __repr__(self) -> str:  # <7>kwargs = ', '.join(f'{key}={value!r}' for key, value in self._asdict().items())return f'{self.__class__.__name__}({kwargs})'
#!/usr/bin/env python3from checkedlib import Checkedclass Movie(Checked):title: stryear: intbox_office: floatif __name__ == '__main__':movie = Movie(title='The Godfather', year=1972, box_office=137)print(movie.title)print(movie)try:# remove the "type: ignore" comment to see Mypy errormovie.year = 'MCMLXXII'  # type: ignoreexcept TypeError as e:print(e)try:blockbuster = Movie(title='Avatar', year=2009, box_office='billions')except TypeError as e:print(e)

checked_demo.py执行结果

The Godfather
Movie(title='The Godfather', year=1972, box_office=137.0)
'MCMLXXII' is not compatible with year:int
'billions' is not compatible with box_office:float

A Checked subclass definition requires that keyword arguments are
used to create an instance, and provides a nice __repr__::

>>> class Movie(Checked):  # <1>
...     title: str  # <2>
...     year: int
...     box_office: float
...
>>> movie = Movie(title='The Godfather', year=1972, box_office=137)  # <3>
>>> movie.title
'The Godfather'
>>> movie  # <4>
Movie(title='The Godfather', year=1972, box_office=137.0)

The type of arguments is runtime checked during instantiation and when an attribute is set::

>>> blockbuster = Movie(title='Avatar', year=2009, box_office='billions')
Traceback (most recent call last):...
TypeError: 'billions' is not compatible with box_office:float
>>> movie.year = 'MCMLXXII'
Traceback (most recent call last):...
TypeError: 'MCMLXXII' is not compatible with year:int

Attributes not passed as arguments to the constructor are initialized with default values::

>>> Movie(title='Life of Brian')
Movie(title='Life of Brian', year=0, box_office=0.0)

Providing extra arguments to the constructor is not allowed::

>>> blockbuster = Movie(title='Avatar', year=2009, box_office=2000,
...                     director='James Cameron')
Traceback (most recent call last):...
AttributeError: 'Movie' object has no attribute 'director'

Creating new attributes at runtime is restricted as well::

>>> movie.director = 'Francis Ford Coppola'
Traceback (most recent call last):...
AttributeError: 'Movie' object has no attribute 'director'

The _asdict instance method creates a dict from the attributes
of a Movie object::

>>> movie._asdict()
{'title': 'The Godfather', 'year': 1972, 'box_office': 137.0}

2 代码解释

在这个例子中,__init_subclass____init__ 的调用顺序和作用域不同,它们各自处理类和实例级别的逻辑。

调用顺序

  • __init_subclass__ 是在子类定义时自动调用的。这发生在任何实例被创建之前,仅在类定义期间触发一次。因此,当定义一个继承了 Checked 类的新类时,__init_subclass__ 将被调用来为这个新类设置 Field 描述符。
  • __init__ 是在创建类的一个实例时调用的。每次通过类(例如 Checked 的子类)创建一个新对象时,都会调用 __init__ 方法。

不同的作用

  • __init_subclass__Checked 类中用来自动为每个子类基于类型注解创建并设置 Field 实例。这些 Field 实例被设置为类属性,用来管理对应的实例属性。

  • __init__ 的作用是初始化具体的实例。尽管 __init_subclass__ 已经设置了 Field 描述符,但是描述符需要在实例化时对具体的属性值进行管理和转换。__init__ 中的 setattr(self, name, value) 调用是用来初始化这些实例属性的值,并且触发 Field 描述符的 __set__ 方法,该方法负责使用提供的构造函数验证和转换这些值。尽管 __init_subclass__ 已经把注解自动创建并分配为 Field 实例,但这些 Field 实例实际上是作为类属性存在的。它们不直接持有数据,而是定义了如何通过其 __set____get__ 方法处理数据。当你在 __init__ 方法中使用 setattr 时,实际上是触发了这些 Field 描述符的 __set__ 方法,它们负责根据构造函数规则来验证和转换赋予实例属性的值。这样,每个实例都可以持有独立的、已经经过验证和转换的数据。

  • __init_subclass__ 设置了如何管理和验证属性(即通过 Field 描述符),但并未处理具体的属性值。

  • __init__ 负责实际设置这些属性的初始值,并触发描述符来处理验证和转换的逻辑。

在调用 __init_subclass__ 之后类的结构会发生一些变化

在这个例子中,使用了 __init_subclass__ 方法和 Checked 类的框架,当 Movie 类被定义继承自 Checked 类时,__init_subclass__ 会自动被调用。这是在类级别发生的,即在任何 Movie 实例被创建之前。

Movie 类定义完成并触发 __init_subclass__ 方法时,这里发生的主要变化如下:

  1. 自动属性创建

    • 对于 Movie 类中定义的每个类型注解(title: str, year: int, box_office: float),__init_subclass__ 会从这些注解中获取信息,并为每个属性创建一个 Field 实例。
  2. Field 实例作为类属性

    • 这些 Field 实例不直接存储任何数据,而是作为描述符存在。描述符主要负责拦截对这些属性的访问和修改操作。
    • 对于每个属性,Field 描述符会设置如何创建(调用相应的类型构造器,如 str(), int(), float()),验证和存储其值。

__init_subclass__ 方法中的核心操作包括:

  • 遍历从 get_type_hints 获取到的类型注解。
  • 为每个属性(如 title, year, box_office)创建一个 Field 描述符,并将其作为类属性设置到 Movie 类上。

这样设置后的 Movie 类的结构将包含以下元素:

  • title 属性关联到一个 Field 描述符,该描述符使用 str 作为构造函数。
  • year 属性关联到一个 Field 描述符,该描述符使用 int 作为构造函数。
  • box_office 属性关联到一个 Field 描述符,该描述符使用 float 作为构造函数。

类的行为

当创建 Movie 的实例并尝试设置这些属性时:

  • 访问或修改这些属性将触发对应的 Field 描述符的 __set____get__ 方法。
  • 如果尝试设置的值类型不正确,Field__set__ 方法将尝试转换值到声明的类型(如将字符串转换为整数)。如果转换失败,将抛出 TypeError

2 类装饰器方式

2.1 代码实现

from collections.abc import Callable  # <1>
from typing import Any, NoReturn, get_type_hints
from typing import Dict, Type
class Field:def __init__(self, name: str, constructor: Callable) -> None:  # <2>if not callable(constructor) or constructor is type(None):raise TypeError(f'{name!r} type hint must be callable')self.name = nameself.constructor = constructordef __set__(self, instance: Any, value: Any) -> None:  # <3>if value is ...:  # <4>value = self.constructor()else:try:value = self.constructor(value)  # <5>except (TypeError, ValueError) as e:type_name = self.constructor.__name__msg = (f'{value!r} is not compatible with {self.name}:{type_name}')raise TypeError(msg) from einstance.__dict__[self.name] = value  # <6># tag::CHECKED_DECORATOR[]
def checked(cls: type) -> type:  # <1>for name, constructor in _fields(cls).items():    # <2>setattr(cls, name, Field(name, constructor))  # <3>cls._fields = classmethod(_fields)  # type: ignore  # <4>instance_methods = (  # <5>__init__,__repr__,__setattr__,_asdict,__flag_unknown_attrs,)for method in instance_methods:  # <6>setattr(cls, method.__name__, method)return cls  # <7>def _fields(cls: type) -> Dict[str, type]:return get_type_hints(cls)def __init__(self: Any, **kwargs: Any) -> None:for name in self._fields():value = kwargs.pop(name, ...)setattr(self, name, value)if kwargs:self.__flag_unknown_attrs(*kwargs)def __setattr__(self: Any, name: str, value: Any) -> None:if name in self._fields():cls = self.__class__descriptor = getattr(cls, name)descriptor.__set__(self, value)else:self.__flag_unknown_attrs(name)def __flag_unknown_attrs(self: Any, *names: str) -> NoReturn:plural = 's' if len(names) > 1 else ''extra = ', '.join(f'{name!r}' for name in names)cls_name = repr(self.__class__.__name__)raise AttributeError(f'{cls_name} has no attribute{plural} {extra}')def _asdict(self: Any) -> Dict[str, Any]:return {name: getattr(self, name)for name, attr in self.__class__.__dict__.items()if isinstance(attr, Field)}def __repr__(self: Any) -> str:kwargs = ', '.join(f'{key}={value!r}' for key, value in self._asdict().items())return f'{self.__class__.__name__}({kwargs})'

2.2 代码解释

这段代码实现了一个装饰器 checked,它为 Python 类添加强类型检查和自动属性管理的功能。该装饰器使用了 Python 的描述符协议和类型注解来自动验证和初始化类属性。下面逐部分解析代码的功能和工作方式:

Field 类

  • 目的Field 类用作属性描述符,主要负责设置和检索类实例的属性值,并确保值符合指定的类型。
  • 构造方法 (__init__): 接收一个属性名和一个构造函数(类型)。如果构造函数不是可调用的或者是 None 类型,则抛出 TypeError
  • 设置方法 (__set__): 负责接收和处理对属性的赋值操作。如果值是 ...(省略符号),则使用构造函数(无参数)创建默认值。如果提供了值,则尝试使用构造函数将值转换为适当的类型。如果转换失败,会抛出 TypeError
  • 当从实例访问这个属性(如 instance.title)时,由于缺少 get 方法,Python 的解释器会直接从实例的 dict 字典中查找该属性的值,而不是调用描述符的 get 方法。描述符的 set 方法直接操作了托管实例的 dict 字典,将值存储在由 self.name 指定的键下。这意味着,尽管 Field 对象被设置为类的属性,它并没有拦截获取属性值的操作,而是允许直接从实例的字典中获取这些值。

checked 装饰器

  • 功能:通过自动应用类型注解和属性管理,使类成为"检查型"类。
  • 实现
    • 自动属性管理:遍历类的类型注解,并为每个注解创建一个 Field 描述符,负责管理相应的属性。
    • 添加方法:将一系列方法(如 __init__, __repr__, __setattr__, _asdict, __flag_unknown_attrs)添加到被装饰的类中,以支持初始化、属性设置、字典转换和错误管理等功能。

实现的方法

  • _fields:返回一个字典,包含类的所有类型注解。用于在类中创建 Field 描述符。
  • __init__:负责初始化新创建的实例。从 kwargs 中提取每个字段的值,如果未提供,则使用省略符号触发默认构造。
  • __setattr__:当尝试设置属性时,首先检查该属性是否由 Field 描述符管理。如果是,则使用描述符的 __set__ 方法来设置值,否则抛出属性错误。
  • __flag_unknown_attrs:在尝试设置未知属性或当 __init__ 方法中存在额外的 kwargs 时被调用,抛出 AttributeError
  • _asdict:返回一个字典,包含由 Field 描述符管理的所有属性及其值。
  • __repr__:生成类实例的字符串表示,展示所有通过 Field 管理的属性和它们的值。

使用 checked 装饰器处理子类后类的结构会发生的变化

属性管理
checked 装饰器会遍历子类中通过类型注解定义的属性,并为每个属性创建并分配一个 Field 描述符实例。这些 Field 描述符被设置为类属性,用于管理相应的实例属性。这意味着:

对于每个定义的属性,都会有一个 Field 实例与之关联,负责接收和处理对该属性的所有访问和修改请求。
这些 Field 描述符将确保属性值在设置时被正确地转换和验证,按照定义的类型进行。

方法增强
checked 装饰器还会将几个关键的方法添加到子类中:

init:用于正确地初始化新对象的实例属性,接受关键字参数,每个参数对应一个属性。如果属性未在初始化时提供,将使用其类型的默认构造函数来生成值。
setattr:重写此方法以确保对属性的设置通过 Field 描述符进行,从而利用 Field 的类型检查和转换功能。
repr:提供了一种格式化的方式来描述类实例,显示所有通过 Field 管理的属性和它们的值。
_asdict:允许将对象的属性转换成字典形式,便于查看和使用。
__flag_unknown_attrs:当尝试访问或设置不存在的属性时,此方法将被调用,抛出 AttributeError。

3 元类方式

3.1 代码实现

from collections.abc import Callable
from typing import Any, NoReturn, get_type_hints
from typing import Dict, Typeclass Field:def __init__(self, name: str, constructor: Callable) -> None:if not callable(constructor) or constructor is type(None):raise TypeError(f'{name!r} type hint must be callable')self.name = nameself.storage_name = '_' + name  # <1>self.constructor = constructordef __get__(self, instance, owner=None):if instance is None:  # <2>return selfreturn getattr(instance, self.storage_name)  # <3>def __set__(self, instance: Any, value: Any) -> None:if value is ...:value = self.constructor()else:try:value = self.constructor(value)except (TypeError, ValueError) as e:type_name = self.constructor.__name__msg = f'{value!r} is not compatible with {self.name}:{type_name}'raise TypeError(msg) from esetattr(instance, self.storage_name, value)  # <4>class CheckedMeta(type):def __new__(meta_cls, cls_name, bases, cls_dict):  # <1>if '__slots__' not in cls_dict:  # <2>slots = []type_hints = cls_dict.get('__annotations__', {})  # <3>for name, constructor in type_hints.items():   # <4>field = Field(name, constructor)  # <5>cls_dict[name] = field  # <6>slots.append(field.storage_name)  # <7>cls_dict['__slots__'] = slots  # <8>return super().__new__(meta_cls, cls_name, bases, cls_dict)  # <9>class Checked(metaclass=CheckedMeta):__slots__ = ()  # skip CheckedMeta.__new__ processing@classmethoddef _fields(cls) -> Dict[str, type]:return get_type_hints(cls)def __init__(self, **kwargs: Any) -> None:for name in self._fields():value = kwargs.pop(name, ...)setattr(self, name, value)if kwargs:self.__flag_unknown_attrs(*kwargs)def __flag_unknown_attrs(self, *names: str) -> NoReturn:plural = 's' if len(names) > 1 else ''extra = ', '.join(f'{name!r}' for name in names)cls_name = repr(self.__class__.__name__)raise AttributeError(f'{cls_name} object has no attribute{plural} {extra}')def _asdict(self) -> Dict[str, Any]:return {name: getattr(self, name)for name, attr in self.__class__.__dict__.items()if isinstance(attr, Field)}def __repr__(self) -> str:kwargs = ', '.join(f'{key}={value!r}' for key, value in self._asdict().items())return f'{self.__class__.__name__}({kwargs})'

3.2 代码解释

这段代码定义了一个复杂的类装饰和类元编程机制,通过自定义描述符 Field 和元类 CheckedMeta 来自动化处理类属性的类型检查和初始化。这种机制可以用来创建严格类型化的数据结构,确保对象属性在设置时自动进行类型转换和验证。

Field 类

Field 用作属性描述符,负责管理属性的访问和设置。

  • 初始化: 接收一个属性名称和一个构造函数。如果构造函数不是可调用的,则抛出异常。此外,它生成一个内部使用的存储属性名 (storage_name),这通常是私有属性名。
  • __get__ 方法: 用于获取属性值。如果 instanceNone(通常在直接通过类访问属性时发生),返回描述符自身;否则从实例字典中返回相应的值。
  • __set__ 方法: 设置属性值。如果值为特殊标记 ...,使用无参数的构造函数创建默认值;否则尝试使用构造函数转换提供的值。如果转换失败,抛出 TypeError

CheckedMeta 元类

CheckedMeta 是一个元类,用于在创建类时自动处理属性的类型注解。

  • __new__ 方法: 在创建类对象时被调用。
    • 检查是否已定义 __slots__,用于优化内存使用。
    • 从类定义中获取类型注解,并为每个注解创建一个 Field 描述符,将其添加到类字典中。
    • 为每个 Field 描述符生成的 storage_name 创建一个对应的槽。
    • 最后,使用修改后的类字典调用基类的 __new__ 方法创建类。

Checked 类

作为使用 CheckedMeta 元类的示例,这个类提供了以下功能:

  • 初始化: 使用关键字参数初始化类的实例。通过 _fields 方法获取所有字段,并尝试从 kwargs 中提取对应的值进行设置。
  • 属性设置 (__setattr__): 拦截所有属性赋值操作,确保通过 Field 描述符处理。
  • 错误处理: 当尝试访问或设置未知属性时,__flag_unknown_attrs 方法会抛出 AttributeError
  • 字典转换 (_asdict): 提供一种将对象属性转换为字典的方法,便于外部访问和操作。
  • 字符串表示 (__repr__): 生成对象的友好字符串表示,展示其所有属性和值。

使用 CheckedMeta 作为元类的子类结构

属性描述符 (Field 实例):

title 关联到一个 Field 实例,此实例用 str 作为构造函数进行类型检查和转换。
year 关联到一个 Field 实例,此实例用 int 作为构造函数进行类型检查和转换。
box_office 关联到一个 Field 实例,此实例用 float 作为构造函数进行类型检查和转换。

槽 (slots):

slots 包含 [‘_title’, ‘_year’, ‘_box_office’],这些是实际存储属性值的内部属性名,避免了使用实例字典。

方法:

类继承自 Checked,因此拥有 initsetattr、_asdict、repr 和 __flag_unknown_attrs 等方法,这些方法提供了初始化、属性设置、错误处理、对象转字典和字符串表示的功能。

类属性与实例属性不能同名的原因

使用 __slots__ 在 Python 类中定义哪些属性名将作为实例属性存储,通常是为了节省内存和提高属性访问速度。当使用 __slots__ 时,Python 不再为每个实例创建一个 __dict__ 字典,而是为这些属性在内存中分配固定位置。

当使用描述符(如 Field 类实例)作为类属性,同时使用 __slots__ 指定实例属性时,需要注意的是:

  1. 名称冲突:如果一个实例属性与一个类属性(描述符)同名,那么在访问这个属性时,描述符的逻辑将被触发,而不是直接访问实例属性。这是因为类属性(描述符)的访问级别比实例属性更高。

  2. 描述符协议:描述符协议定义了如何通过描述符对象来控制属性的访问。在你的 Field 描述符的实现中,__get____set__ 方法被用来管理访问和设置属性的行为。当你尝试访问一个属性,Python 首先检查该属性是否是一个描述符(即是否有 __get____set__ 方法),如果是,则调用这些方法。

  3. 存储位置Field 描述符使用 storage_name (例如 '_title')来在实例中存储数据,而不是直接使用 title。这是为了避免直接访问和修改这些属性,从而绕过描述符逻辑。

如何确保描述符的 __get__ 正确执行

为了确保 Field 描述符的 __get__ 方法能够正确执行,你应该这样访问属性:

  • 当通过实例访问属性时(例如 movie_instance.title),将调用 Field__get__ 方法,从实例中的 '_title' 位置取出值。
  • 当直接通过类访问属性时(例如 Movie.title),__get__ 方法中的 instance is None 分支将被执行,这通常返回描述符自身或其他与类相关的信息。

4 元类的调用顺序

元类在 Python 中用于创建类,它们本身是类的类。

元类的关键方法

  1. __prepare__:

    • 调用时机: 在类体被执行前调用。
    • 功能: 返回一个映射对象,用于在类定义时存储类属性和方法的定义。通常返回的是一个字典,但可以覆盖为其他类型的映射对象。
    • 参数: 接受将要创建的类的名称和它的基类。
    • 返回值: 用于类体执行的命名空间。
  2. __new__:

    • 调用时机: 在类的实例(即类对象本身)被创建时调用。
    • 功能: 负责实际创建类对象。它可以修改类的定义,添加、修改或删除属性,或者根据需要完全改变类的创建过程。
    • 参数: 元类、类名、基类元组、类字典(由 __prepare__ 返回的映射对象),还可以接收额外的关键字参数(如果在类定义中提供)。
    • 返回值: 返回一个新的类对象。
  3. __init__:

    • 调用时机: 在类对象创建后被调用,用于初始化新创建的类对象。
    • 功能: 初始化新创建的类对象。与 __new__ 不同,__init__ 不返回任何值,它仅用于初始化操作。
    • 参数: 类对象、类名、基类元组、字典。
  4. __init_subclass__:

    • 调用时机: 这是一个类方法,当类被继承时自动调用。
    • 功能: 用于在创建子类时执行初始化或其他配置工作。
    • 参数: 子类和任何在子类定义时传递的关键字参数。
    • 返回值: 通常无返回值,用于设置子类或进行检查。

调用顺序示例

假设我们有一个元类 Meta 和使用这个元类的类 MyClass

class Meta(type):def __prepare__(name, bases, **kwargs):print("Meta.__prepare__ called")return super().__prepare__(name, bases, **kwargs)def __new__(cls, name, bases, namespace, **kwargs):print("Meta.__new__ called")return super().__new__(cls, name, bases, namespace, **kwargs)def __init__(cls, name, bases, namespace, **kwargs):print("Meta.__init__ called")super().__init__(name, bases, namespace, **kwargs)def __init_subclass__(cls, **kwargs):print("Meta.__init_subclass__ called")super().__init_subclass__(**kwargs)class MyClass(metaclass=Meta):passclass MySubClass(MyClass):pass
调用顺序为:
  1. Meta.__prepare__ 被调用来准备 MyClass 的命名空间。
  2. 类体 MyClass 执行。
  3. Meta.__new__ 被调用来创建 MyClass 类对象。
  4. Meta.__init__ 被调用来初始化 MyClass 类对象。
  5. Meta.__init_subclass__ 被调用(如果在 MyClass 中定义)。
  6. MySubClass 被定义时,上述步骤(1-4)重复执行,此外,MyClass.__init_subclass__ 也会被调用来处理子类的创建。

参考《流程的python》第24章

相关文章:

python类元编程示例-使用类型注解来检查转换属性值的类框架

用三种方式实现使用类型注解来检查转换属性值的类框架 1 __init_subclass__方式 1.1 代码实现 from collections.abc import Callable # <1> from typing import Any, NoReturn, get_type_hints from typing import Dict, Typeclass Field:def __init__(self, name: …...

Python3 笔记:字符串的 zfill() 和 rjust()

1、zfill() 方法返回指定长度的字符串&#xff0c;原字符串右对齐&#xff0c;前面填充0。 语法&#xff1a;str.zfill(width) width &#xff1a;指定字符串的长度。原字符串右对齐&#xff0c;前面填充0。 str1 2546 str2 2 print(str1.zfill(10)) # 运行结果&#xff1…...

SpringBoot项目启动提示端口号占用

Windows环境下&#xff0c;SpringBoot项目启动时报端口号占用&#xff1a; *************************** APPLICATION FAILED TO START ***************************Description:Web server failed to start. Port 8080 was already in use.Action:Identify and stop the proc…...

音视频开发23 FFmpeg 音频重采样

代码实现的功能 目的是 将&#xff1a; 一个采样率为 44100&#xff0c;采样通道为 2&#xff0c;格式为 AV_SAMPLE_FMT_DBL 的 in.pcm 数据 转换成 一个采样率为 48000&#xff0c;采样通道为 1&#xff0c;格式为 AV_SAMPLE_FMT_S16 的 out.pcm 数据 1.重采样 1.1 为什么要重…...

windows系统下安装fnm

由于最近做项目要切换多个node版本&#xff0c;查询了一下常用的有nvm和fnm这两种&#xff0c;对比了一下选择了fnm。 下载fnm 有两种方式&#xff0c;目前最新版本是1.37.0&#xff1a; 1.windows下打开powershell&#xff0c;执行以下命令下载fnm winget install Schniz.f…...

【Linux网络】传输层协议 - UDP

文章目录 一、传输层&#xff08;运输层&#xff09;运输层的特点复用和分用再谈端口号端口号范围划分认识知名端口号&#xff08;Well-Know Port Number&#xff09;两个问题① 一个进程是否可以绑定多个端口号&#xff1f;② 一个端口号是否可以被多个进程绑定&#xff1f; n…...

debugger(四):源代码

〇、前言 终于来到令人激动的源代码 level 了&#xff0c;这里将会有一些很有意思的算法&#xff0c;来实现源代码级别的调试&#xff0c;这将会非常有趣。 一、使用 libelfin 库 我们不可能直接去读取整个 .debug info 段来进行设置&#xff0c;这是没有必要的&#xff0c;…...

基于运动控制卡的圆柱坐标机械臂设计

1 方案简介 介绍一种基于运动控制卡制作一款scara圆柱坐标的机械臂设计方案&#xff0c;该方案控制器用运动控制卡制作一台三轴机械臂&#xff0c;用于自动抓取和放料操作。 2 组成部分 该机械臂的组成部分有研华运动控制卡&#xff0c;触摸屏&#xff0c;三轴圆柱坐标的平面运…...

MongoDBTemplate-基本文档查询

文章目录 流程概述步骤1&#xff1a;创建一个MongoDB的连接步骤2&#xff1a;创建一个查询对象Query步骤3&#xff1a;设置需要查询的字段步骤4&#xff1a;使用查询对象执行查询操作 流程概述 步骤描述步骤1创建一个MongoDB的连接步骤2创建一个查询对象Query步骤3设置需要查询…...

23种设计模式——创建型模式

设计模式 文章目录 设计模式创建型模式单例模式 [1-小明的购物车](https://kamacoder.com/problempage.php?pid1074)工厂模式 [2-积木工厂](https://kamacoder.com/problempage.php?pid1076)抽象⼯⼚模式 [3-家具工厂](https://kamacoder.com/problempage.php?pid1077)建造者…...

idm究竟有哪些优势

IDM&#xff08;Internet Download Manager&#xff09;是一款广受好评的下载管理工具&#xff0c;其主要优势包括&#xff1a; 高速下载&#xff1a;IDM支持最大32线程的下载&#xff0c;可以显著提升下载速度1。文件分类下载&#xff1a;IDM可以根据文件后缀进行分类&#x…...

如何学习Golang语言!

第一部分&#xff1a;Go语言概述 起源与设计哲学&#xff1a;Go语言由Robert Griesemer、Rob Pike和Ken Thompson三位Google工程师设计&#xff0c;旨在解决现代编程中的一些常见问题&#xff0c;如编译速度、运行效率和并发编程。主要特点&#xff1a;Go语言的语法简单、编译…...

Redis系列之淘汰策略介绍

Redis系列之淘汰策略介绍 文章目录 为什么需要Redis淘汰策略&#xff1f;Redis淘汰策略分类Redis数据淘汰流程源码验证淘汰流程Redis中的LRU算法Redis中的LFU算法 为什么需要Redis淘汰策略&#xff1f; 由于Redis内存是有大小的&#xff0c;当内存快满的时候&#xff0c;又没有…...

sql 调优

sql 调优 SQL调优是一个复杂的过程&#xff0c;涉及多个方面&#xff0c;包括查询优化、索引优化、表结构优化等。以下是一些基本的SQL调优策略&#xff1a; 使用索引&#xff1a;确保查询中涉及的列都有适当的索引。 查询优化&#xff1a;避免使用SELECT *&#xff0c;只选取…...

【UML用户指南】-13-对高级结构建模-包

目录 1、名称 2、元素 3、可见性 4、引入与引出 用包把建模元素安排成可作为一个组来处理的较大组块。可以控制这些元素的可见性&#xff0c;使一些元素在包外是可见的&#xff0c;而另一些元素要隐藏在包内。也可以用包表示系统体系结构的不同视图。 狗窝并不复杂&#x…...

前端面试题日常练-day63 【面试题】

题目 希望这些选择题能够帮助您进行前端面试的准备&#xff0c;答案在文末 1. TypeScript中&#xff0c;以下哪个关键字用于声明一个类的构造函数&#xff1f; a) constructor b) init c) create d) initialize 2. 在TypeScript中&#xff0c;以下哪个符号用于声明可选的函…...

GAN的入门理解

这一篇主要是关于生成对抗网络的模型笔记&#xff0c;有一些简单的证明和原理&#xff0c;是根据李宏毅老师的课程整理的&#xff0c;下面有链接。本篇文章主要就是梳理基础的概念和训练过程&#xff0c;如果有什么问题的话也可以指出的。 李宏毅老师的课程链接 1.概述 GAN是…...

43【PS 作图】颜色速途

1 通过PS让画面细节模糊&#xff0c;避免被过多的颜色干扰 2 分析画面的颜色 3 作图 参考网站&#xff1a; 色感不好要怎么提升呢&#xff1f;分享一下我是怎么练习色感的&#xff01;_哔哩哔哩_bilibili https://www.bilibili.com/video/BV1h1421Z76p/?spm_id_from333.1007.…...

定个小目标之刷LeetCode热题(13)

今天来看看这道题&#xff0c;介绍两种解法 第一种动态规划&#xff0c;代码如下 class Solution {public int maxSubArray(int[] nums) {int pre 0, maxAns nums[0];for (int x : nums) {// 计算当前最大前缀和pre Math.max(pre x, x);// 更新最大前缀和maxAns Math.ma…...

【AI大模型】Prompt Engineering

目录 什么是提示工程&#xff08;Prompt Engineering&#xff09; Prompt 调优 Prompt 的典型构成 「定义角色」为什么有效&#xff1f; 防止 Prompt 攻击 攻击方式 1&#xff1a;著名的「奶奶漏洞」 攻击方式 2&#xff1a;Prompt 注入 防范措施 1&#xff1a;Prompt 注…...

centos安装vscode的教程

centos安装vscode的教程 步骤一&#xff1a;打开vscode官网找到历史版本 历史版本链接 步骤二&#xff1a;找到文件下载的位置 在命令行中输入&#xff08;稍等片刻即可打开&#xff09;&#xff1a; /usr/share/code/bin/code关闭vscode后&#xff0c;可在应用程序----编程…...

面试题------>MySQL!!!

一、连接查询 ①&#xff1a;左连接left join &#xff08;小表在左&#xff0c;大表在右&#xff09; ②&#xff1a;右连接right join&#xff08;小表在右&#xff0c;大表在左&#xff09; 二、聚合函数 SQL 中提供的聚合函数可以用来统计、求和、求最值等等 COUNT&…...

英伟达:史上最牛一笔天使投资

200万美元的天使投资&#xff0c;让刚成立就面临倒闭风险的英伟达由危转安&#xff0c;并由此缔造了一个2.8万亿美元的市值神话。 这是全球风投史上浓墨重彩的一笔。 前不久&#xff0c;黄仁勋在母校斯坦福大学的演讲中&#xff0c;提到了人生中的第一笔融资——1993年&#x…...

PDF分页处理:技术与实践

引言 在数字化办公和学习中&#xff0c;PDF文件因其便携性和格式稳定性而广受欢迎。然而&#xff0c;处理大型PDF文件时&#xff0c;我们经常需要将其拆分成单独的页面&#xff0c;以便于管理和分享。本文将探讨如何使用Python编程语言和一些流行的库来实现PDF文件的分页处理。…...

数据可视化——pyecharts库绘图

目录 官方文档 使用说明&#xff1a; 点击基本图表 可以点击你想要的图表 安装&#xff1a; 一些例图&#xff1a; 柱状图&#xff1a; 效果&#xff1a; 折线图&#xff1a; 效果&#xff1a; 环形图&#xff1a; 效果&#xff1a; 南丁格尔图&#xff08;玫瑰图&am…...

Python的return和yield,哪个是你的菜?

目录 1、return基础介绍 &#x1f4da; 1.1 return用途&#xff1a;数据返回 1.2 return执行&#xff1a;函数终止 1.3 return深入&#xff1a;无返回值情况 2、yield核心概念 &#x1f347; 2.1 yield与迭代器 2.2 生成器函数构建 2.3 yield的暂停与续行特性 3、retur…...

持续总结中!2024年面试必问 20 道分布式、微服务面试题(七)

上一篇地址&#xff1a;持续总结中&#xff01;2024年面试必问 20 道分布式、微服务面试题&#xff08;六&#xff09;-CSDN博客 十三、请解释什么是服务网格&#xff08;Service Mesh&#xff09;&#xff1f; 服务网格&#xff08;Service Mesh&#xff09;是一种用于处理服…...

AJAX 跨域

这里写目录标题 同源策略JSONPJSONP 是怎么工作的JSONP 的使用原生JSONP实践CORS 同源策略 同源&#xff1a; 协议、域名、端口号 必须完全相同、 当然网页的URL和AJAX请求的目标资源的URL两者之间的协议、域名、端口号必须完全相同。 AJAX是默认遵循同源策略的&#xff0c;不…...

3 数据类型、运算符与表达式-3.1 C语言的数据类型和3.2 常量与变量

数据类型 基本类型 整型字符型实型(浮点型) 单精度型双精度型 枚举类型 构造类型 数组类型结构体类型共用体类型 指针类型空类型 #include <stdio.h> #include <string.h> #include <stdbool.h> // 包含布尔类型定义 // 常量和符号常量 #define PRICE 30//…...

NSSCTF-Web题目5

目录 [SWPUCTF 2021 新生赛]error 1、题目 2、知识点 3、思路 [LitCTF 2023]作业管理系统 1、题目 2、知识点 3、思路 [HUBUCTF 2022 新生赛]checkin 1、题目 2、知识点 3、思路 [SWPUCTF 2021 新生赛]error 1、题目 2、知识点 数据库注入、报错注入 3、思路 首先…...

不注册公司可以做网站吗/互联网推广是做什么的

何为虚拟DOM虚拟DOM就是普通的js对象&#xff0c;其可以用来描述DOM对象&#xff0c;但是由于不是真正的DOM对象&#xff0c;因此人们把它叫做虚拟DOM。为何出现虚拟DOM手动处理DOM在早期的js应用中&#xff0c;开发人员需要手动处理DOM&#xff0c;手动处理不仅代码繁琐&#…...

网站怎么做图片搜索/百度快速排名化

下面的文章讲解了如何为Cassandra设置登录密码&#xff1a;(操作的环境为Linux 下的 Cassandra , Windows 下面存在一些问题, 不知道怎么解决, cqlsh 不能登录) 0.修改配置文件 cassandra.yaml&#xff0c;把 authenticator: AllowAllAuthenticator改为authenticator: Passwor…...

达州城乡建设网站/广告

1、问题&#xff1a;这两天写的APP需要在一个页面中使用echarts图表&#xff0c;发现一个问题&#xff1a;在进入改页面初始化时&#xff0c;图表会缩小。但是把容器宽高设置为px就可以了&#xff0c;但是写的移动端需要适配必须rem。 2、问题根因&#xff1a;div还没有创建出来…...

上海市住房和城乡建设管理委员会门户网站/seo关键词优化提高网站排名

搬到姨家还没一段时间&#xff0c;跟姨睡一张床也还没多久&#xff0c;我就又要一个人睡一个房间了&#xff0c;陪伴我的又是除了电脑就是电视&#xff0c;我不喜欢这样&#xff0c;更多时候我希望晚上的自己是忙碌的&#xff0c;不希望自己有空闲时间&#xff0c;一直我都是喜…...

手机传奇网站/正规网络推广服务

之前我们知道&#xff0c;二分查找依赖数组的随机访问&#xff0c;所以只能用数组来实现。如果数据存储在链表中&#xff0c;就真的没法用二分查找了吗&#xff1f;而实际上&#xff0c;我们只需要对链表稍加改造&#xff0c;就可以实现类似“二分”的查找算法&#xff0c;这种…...

潍坊企业宣传片制作公司/杭州seo网站建设靠谱

Bootstrap Method:在统计学中&#xff0c;Bootstrap从原始数据中抽取子集&#xff0c;然后分别求取各个子集的统计特征&#xff0c;最终将统计特征合并。例如求取某国人民的平均身高&#xff0c;不可能测量每一个人的身高&#xff0c;但却可以在10个省市&#xff0c;分别招募10…...