前言
今天来看下下面代码画红框的三个地方。先看第16行,这块很简单,就是规范下包引入的范围。
all 是 Python 中的一个特殊变量,用于定义模块、类或包的公共接口。它在执行通配符导入(例如 from module import *)时只有 ApiModelWorker、ApiChatParams、ApiCompletionParams 和 ApiEmbeddingsParams 将被导入。未列在 all 中的任何内容都不会被导入。
这对于控制模块或包的公共接口非常有用。它可以通过只暴露必要的对象来防止命名空间污染。
下面的BaseModel,实际上是 pydantic库。今天我们来学习下这个库。
一、pydantic库是做什么的?
pydantic是一个Python库,用于数据验证和解析。它提供了一个简单而强大的方式来定义数据模型,然后可以使用这些模型来验证和解析数据。
它的主要功能包括:
-
声明式模型定义:使用类来定义数据模型,通过在类的属性上添加注解来指定数据类型和验证规则。
-
数据验证:可以对输入的数据进行验证,例如验证数据类型、长度、范围等。
-
数据解析:可以将输入的数据解析为定义好的模型对象,自动转换数据类型并应用指定的验证规则。
-
自动文档生成:可以根据模型定义自动生成API文档,包括数据类型、验证规则等信息。
-
数据序列化:可以将模型对象序列化为JSON字符串或其他格式,并支持自定义编码器。
总的来说,pydantic提供了一种简单、便捷、安全的方式来定义和处理数据模型,可以提高开发效率并减少错误。
二、通过实例来学习
1. @root_validator装饰器
我们在上面的例子中增加@root_validator(pre=True)
装饰器。下面是修改后的代码示例:
from pydantic import BaseModel, root_validator
class User(BaseModel):
name: str
age: int
@root_validator(pre=True)
def check_age(cls, values):
age = values.get('age')
if age < 0:
raise ValueError('年龄不能是负数')
return values
user_data = {
'name': 'Alice',
'age': -30
}
try:
user = User(**user_data)
except ValueError as e:
print(e)
这样,check_age
方法将在根校验之前执行,以确保年龄不是负数。
在 Python 中,** 是一个特殊的语法,用于将一个字典解包为关键字参数。
在上面的代码中,user = User(**user_data) 中的 **user_data 表示将 user_data 字典中的键值对作为关键字参数传递给 User 类的构造函数。
具体来说,User(**user_data) 会将 user_data 字典中的键作为参数名,值作为参数值传递给 User 类的构造函数。
例如,假设 user_data 字典的内容为 {‘name’: ‘John’, ‘age’: 25},那么 User(**user_data) 相当于 User(name=‘John’, age=25)。
这种用法可以使您更灵活地创建 User 实例,因为您可以使用一个字典来存储实例的属性值,并将其传递给构造函数。这在处理动态数据或从其他来源获取数据时非常有用。
请注意,**user_data 只适用于字典类型的参数。如果 user_data 不是一个字典,将会引发一个 TypeError 异常。
2. @validator 装饰器
我们也可以更精细的对每一个字段进行判断,并给出不同错误信息
from pydantic import BaseModel, validator
class User(BaseModel):
name: str
@validator('name')
def validate_name(cls, name):
if not isinstance(name, str):
raise ValueError('姓名必须是字符串')
if len(name) > 10:
raise ValueError('姓名长度不能超过10个字符')
return name
if __name__ == '__main__':
try:
user = User(name=12345678901) # 正确,name满足条件
except ValueError as e:
print(e)
结果可能和大家想的不一样,它不会“报姓名必须是字符串”,因为定义了 name: str
会自动转换,只有转换不了的时候,才会报错。
3. 自动文档生成
自动生成文档的方法可以用两句话实现
user_schema = User.schema()
print(user_schema)
示例如下
from pydantic import BaseModel, root_validator
class User(BaseModel):
name: str
age: int
@root_validator(pre=True)
def check_age(cls, values):
age = values.get('age')
if age < 0:
raise ValueError('年龄不能是负数')
return values
user_data = {
'name': 'Alice',
'age': -30
}
if __name__ == '__main__':
user_schema = User.schema()
print(user_schema)
try:
user = User(**user_data)
except ValueError as e:
print(e)
运行结果:
总结
回来看代码是不是就很简单了。唯一要说明的是 代码里 @root_validator(pre=True)和@root_validator(pre=False) 的区别
测试:
from pydantic import BaseModel, root_validator
class User(BaseModel):
name: str
age: int
@root_validator(pre=False)
def check_name(cls, values):
name = values.get('name')
if name is None or name == '':
raise ValueError('姓名不能为空')
return values
@root_validator(pre=False)
def check_age(cls, values):
age = values.get('age')
if age < 0:
raise ValueError('年龄不能是负数')
return values
user_data = {
'name': '',
'age': -30
}
if __name__ == '__main__':
user_schema = User.schema()
print(user_schema)
try:
user = User(**user_data)
except ValueError as e:
print(e)
看结果
from pydantic import BaseModel, root_validator
class User(BaseModel):
name: str
age: int
@root_validator(pre=True)
def check_name(cls, values):
name = values.get('name')
if name is None or name == '':
raise ValueError('姓名不能为空')
return values
@root_validator(pre=True)
def check_age(cls, values):
age = values.get('age')
if age < 0:
raise ValueError('年龄不能是负数')
return values
user_data = {
'name': '',
'age': -30
}
if __name__ == '__main__':
user_schema = User.schema()
print(user_schema)
try:
user = User(**user_data)
except ValueError as e:
print(e)