本文目录导读:

在Python中自定义校验规则有多种方式,我来给你介绍几种常见的实现方法:
使用装饰器实现校验
def validate_positive(func):
def wrapper(value, *args, **kwargs):
if value <= 0:
raise ValueError(f"值 {value} 必须为正数")
return func(value, *args, **kwargs)
return wrapper
def validate_range(min_val, max_val):
def decorator(func):
def wrapper(value, *args, **kwargs):
if not (min_val <= value <= max_val):
raise ValueError(f"值 {value} 必须在 [{min_val}, {max_val}] 范围内")
return func(value, *args, **kwargs)
return wrapper
return decorator
@validate_positive
@validate_range(1, 100)
def process_age(age):
return f"年龄:{age}"
# 测试
try:
print(process_age(25)) # 正常
print(process_age(-5)) # 会报错
except ValueError as e:
print(f"错误:{e}")
基于类的校验器
class Validator:
def __init__(self):
self.rules = []
def add_rule(self, check_func, error_msg="校验失败"):
self.rules.append((check_func, error_msg))
def validate(self, value):
for check_func, error_msg in self.rules:
if not check_func(value):
raise ValueError(error_msg)
return True
# 创建校验器实例
email_validator = Validator()
email_validator.add_rule(lambda x: '@' in x, "必须包含@符号")
email_validator.add_rule(lambda x: len(x) > 5, "长度必须大于5")
email_validator.add_rule(lambda x: x.endswith('.com'), "必须以.com结尾")
# 使用校验器
def register_user(email):
email_validator.validate(email)
return f"用户注册成功:{email}"
# 测试
try:
print(register_user("test@example.com")) # 正常
print(register_user("invalid")) # 会报错
except ValueError as e:
print(f"错误:{e}")
使用数据类(dataclass)实现
from dataclasses import dataclass
from typing import Callable, List
@dataclass
class FieldValidator:
name: str
rules: List[Callable]
def validate(self, value):
for rule in self.rules:
rule(value)
class UserData:
def __init__(self):
self.validators = {
'username': FieldValidator('用户名', [
lambda x: len(x) >= 3 or self._raise_error("用户名至少3个字符"),
lambda x: x.isalnum() or self._raise_error("用户名只能包含字母和数字")
]),
'password': FieldValidator('密码', [
lambda x: len(x) >= 8 or self._raise_error("密码至少8位"),
lambda x: any(c.isupper() for c in x) or self._raise_error("密码需要包含大写字母"),
lambda x: any(c.isdigit() for c in x) or self._raise_error("密码需要包含数字")
])
}
def _raise_error(self, msg):
raise ValueError(msg)
def validate_user(self, username, password):
self.validators['username'].validate(username)
self.validators['password'].validate(password)
print("验证通过!")
# 使用示例
user = UserData()
try:
user.validate_user("test", "Hello123") # 正常
user.validate_user("ab", "弱密码") # 会报错
except ValueError as e:
print(f"验证错误:{e}")
链式调用校验器
class ValidatorChain:
def __init__(self):
self._checks = []
def add_rule(self, check_func, error_msg="校验失败"):
self._checks.append((check_func, error_msg))
return self # 返回self实现链式调用
def not_empty(self, error_msg="不能为空"):
return self.add_rule(lambda x: x is not None and x != "", error_msg)
def min_length(self, length, error_msg=None):
default_msg = f"长度不能小于{length}"
return self.add_rule(lambda x: len(str(x)) >= length, error_msg or default_msg)
def max_length(self, length, error_msg=None):
default_msg = f"长度不能大于{length}"
return self.add_rule(lambda x: len(str(x)) <= length, error_msg or default_msg)
def is_email(self, error_msg="不是有效的邮箱格式"):
import re
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
return self.add_rule(lambda x: re.match(pattern, x) is not None, error_msg)
def validate(self, value):
for check_func, error_msg in self._checks:
if not check_func(value):
raise ValueError(error_msg)
return True
# 使用示例
password_validator = ValidatorChain()
password_validator.not_empty("密码不能为空") \
.min_length(8, "密码至少8位") \
.max_length(20, "密码最多20位")
# 测试
try:
password_validator.validate("Hello@123")
print("密码验证通过")
password_validator.validate("short")
except ValueError as e:
print(f"验证失败:{e}")
使用pydantic(最推荐的方式)
# 需要先安装: pip install pydantic
from pydantic import BaseModel, validator, Field
from typing import Optional
class UserModel(BaseModel):
username: str = Field(..., min_length=3, max_length=50)
email: str
age: int = Field(..., ge=0, le=150)
password: str
@validator('email')
def validate_email(cls, v):
if '@' not in v:
raise ValueError('无效的邮箱格式')
return v
@validator('password')
def validate_password(cls, v):
if len(v) < 8:
raise ValueError('密码至少8位')
if not any(c.isupper() for c in v):
raise ValueError('密码需要包含大写字母')
if not any(c.isdigit() for c in v):
raise ValueError('密码需要包含数字')
return v
@validator('username')
def validate_username(cls, v):
if not v.isalnum():
raise ValueError('用户名只能包含字母和数字')
return v
# 使用示例
try:
user = UserModel(
username="张三",
email="zhangsan@example.com",
age=25,
password="Hello1234"
)
print(f"创建用户成功:{user.username}")
except Exception as e:
print(f"创建用户失败:{e}")
实际应用示例:表单验证器
class FormValidator:
"""表单验证器"""
def __init__(self):
self._fields = {}
self._errors = {}
def add_field(self, name, validators=None, required=True):
"""添加验证字段"""
self._fields[name] = {
'validators': validators or [],
'required': required
}
def validate(self, data):
"""验证所有字段"""
self._errors.clear()
for field_name, config in self._fields.items():
value = data.get(field_name)
# 检查必填字段
if config['required'] and (value is None or value == ''):
self._errors[field_name] = f"{field_name} 是必填字段"
continue
# 跳过空值非必填字段
if not config['required'] and (value is None or value == ''):
continue
# 执行校验规则
for validator in config['validators']:
try:
validator(value)
except ValueError as e:
self._errors[field_name] = str(e)
break
return len(self._errors) == 0
def get_errors(self):
"""获取错误信息"""
return self._errors
# 使用示例
def validate_age(age):
"""自定义年龄验证"""
if not isinstance(age, int) or age < 0 or age > 150:
raise ValueError("年龄必须在0-150之间")
def validate_phone(phone):
"""自定义电话号码验证"""
import re
if not re.match(r'^1[3-9]\d{9}$', phone):
raise ValueError("无效的手机号码格式")
# 创建表单验证器
form = FormValidator()
form.add_field('name', [lambda x: len(x) >= 2 or (_ for _ in ()).throw(ValueError("姓名至少2个字符"))])
form.add_field('age', [validate_age])
form.add_field('phone', [validate_phone])
form.add_field('email', [
lambda x: '@' in x or (_ for _ in ()).throw(ValueError("邮箱需要包含@")),
lambda x: '.' in x or (_ for _ in ()).throw(ValueError("邮箱需要包含. "))
])
# 测试验证
test_data = {
'name': '张三',
'age': 25,
'phone': '13800138000',
'email': 'test@example.com'
}
if form.validate(test_data):
print("所有字段验证通过!")
else:
print("验证失败:", form.get_errors())
推荐使用方式:
- 简单场景:使用装饰器或函数
- 复杂业务:使用类实现,支持链式调用
- 专业项目:使用
pydantic或marshmallow等成熟的库 - 框架集成:使用框架自带的验证机制(如Django Forms、Flask-WTF)
选择哪种方式取决于你的具体需求和项目复杂度。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播