- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
在 Python 3.7 中有这些新的“数据类”容器,它们基本上类似于可变命名元组。假设我制作了一个代表一个人的数据类。我可以通过 __post_init__()
函数添加输入验证,如下所示:
@dataclass
class Person:
name: str
age: float
def __post_init__(self):
if type(self.name) is not str:
raise TypeError("Field 'name' must be of type 'str'.")
self.age = float(self.age)
if self.age < 0:
raise ValueError("Field 'age' cannot be negative.")
这将使良好的输入通过:
someone = Person(name="John Doe", age=30)
print(someone)
Person(name='John Doe', age=30.0)
虽然所有这些错误的输入都会引发错误:
someone = Person(name=["John Doe"], age=30)
someone = Person(name="John Doe", age="thirty")
someone = Person(name="John Doe", age=-30)
但是,由于数据类是可变的,我可以这样做:
someone = Person(name="John Doe", age=30)
someone.age = -30
print(someone)
Person(name='John Doe', age=-30)
从而绕过输入验证。
那么,确保数据类的字段在 初始化后不会突变为不良内容的最佳方法是什么?
最佳答案
数据类是一种提供默认初始化以接受属性作为参数的机制,以及一个很好的表示,以及一些诸如 __post_init__
钩子(Hook)之类的细节。
幸运的是,它们不会与 Python 中的任何其他属性访问机制混淆 - 您仍然可以将无数据类属性创建为 property
描述符,或者如果需要,也可以创建自定义描述符类。这样,任何属性访问都将自动通过您的 getter 和 setter 函数。
使用默认的 property
内置的唯一缺点是你必须以“旧方式”使用它,而不是使用装饰器语法 - 这允许你为你的创建注释属性。
因此,“描述符”是在 Python 中分配给类属性的特殊对象,任何对该属性的访问都会调用描述符 __get__
、__set__
或 __del__
方法。内置的 property
可以方便地构建一个描述符,传递 1 到 3 个函数,这些函数将被这些方法调用。
因此,在没有自定义描述符的情况下,您可以:
@dataclass
class MyClass:
def setname(self, value):
if not isinstance(value, str):
raise TypeError(...)
self.__dict__["name"] = value
def getname(self):
return self.__dict__.get("name")
name: str = property(getname, setname)
# optionally, you can delete the getter and setter from the class body:
del setname, getname
通过使用这种方法,您必须将每个属性的访问权限编写为两个方法/函数,但不再需要编写您的__post_init__
:每个属性都会自行验证。
另请注意,此示例采用了将属性通常存储在实例的 __dict__
中的小常用方法。在网络上的示例中,实践是使用正常的属性访问,但在名称前加上 _
。这将使这些属性污染您最终实例上的 dir
,并且私有(private)属性将不 protected 。
另一种方法是编写您自己的描述符类,并让它检查您要保护的属性的实例和其他属性。这可以根据您的需要进行复杂化,最终以您自己的框架结束。因此,对于将检查属性类型并接受验证器列表的描述符类,您将需要:
def positive_validator(name, value):
if value <= 0:
raise ValueError(f"values for {name!r} have to be positive")
class MyAttr:
def __init__(self, type, validators=()):
self.type = type
self.validators = validators
def __set_name__(self, owner, name):
self.name = name
def __get__(self, instance, owner):
if not instance: return self
return instance.__dict__[self.name]
def __delete__(self, instance):
del instance.__dict__[self.name]
def __set__(self, instance, value):
if not isinstance(value, self.type):
raise TypeError(f"{self.name!r} values must be of type {self.type!r}")
for validator in self.validators:
validator(self.name, value)
instance.__dict__[self.name] = value
#And now
@dataclass
class Person:
name: str = MyAttr(str)
age: float = MyAttr((int, float), [positive_validator,])
就是这样——创建你自己的描述符类需要更多的 Python 知识,但上面给出的代码应该很好用,即使在生产中——欢迎你使用它。
请注意,您可以轻松地为每个属性添加许多其他检查和转换 -并且 __set_name__
本身的代码可以更改为内省(introspection) owner
类中的 __annotations__
以自动记录类型 - 这样类型MyAttr
类本身不需要参数。但正如我之前所说:您可以根据需要将其复杂化。
关于python - 改变数据类时验证输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54488765/
在 JSF2 应用程序中遇到验证属性的问题时,有两种主要方法。 使用 Annotation 在 ManagedBean 上定义验证 @ManagedBean public class MyBean {
我想实现一个不常见的功能,我认为 jquery 验证插件将是最好的方法(如果您在没有插件的情况下建议和回答,我们也会欢迎)。我想在用户在输入字段中输入正确的单词后立即隐藏表单。我试过这个: $("
我有几个下拉菜单(类名为month_dropdown),并且下拉菜单的数量不是恒定的。我怎样才能为它们实现 NotEqual 验证。我正在使用 jQuery 验证插件。 这就是我写的 - jQuery
我设法制作了这个网址验证代码并且它起作用了。但我面临着一个问题。我认为 stackoverflow 是获得解决方案的最佳场所。 function url_followers(){ var url=do
我目前正在使用后端服务,该服务允许用户在客户端应用程序上使用 Google Games 库登录。 用户可以通过他们的 gplay ID 向我们发送信息,以便登录或恢复旧帐户。用户向我们发送以下内容,包
我正在尝试验证输入以查看它是否是有效的 IP 地址(可能是部分地址)。 可接受的输入:172、172.112、172.112.113、172.112.113.114 Not Acceptable 输入
我从 Mongoose 验证中得到这条消息: 'Validator failed for path phone with value ``' 这不应该发生,因为不需要电话。 这是我的模型架构: var
我一直在尝试使用Python-LDAP (版本 2.4.19)在 MacOS X 10.9.5 和 Python 2.7.9 下 我想在调用 .start_tls_s() 后验证与给定 LDAP 服务
我正在处理一个仅与 IE6 兼容的旧 javascript 项目(抱歉...),我想仅在 VS 2017 中禁用此项目的 ESLint/CSLint/Javascript 验证/CSS 验证。 我知道
我正在寻找一种方法来验证 Spring 命令 bean 中的 java.lang.Double 字段的最大值和最小值(一个值必须位于给定的值范围之间),例如, public final class W
我正在尝试在 springfuse(JavaEE 6 + Spring Framework (针对 Jetty、Tomcat、JBoss 等)) 和 maven 的帮助下构建我的 webapps 工作
我试图在我们的项目中使用 scalaz 验证,但遇到了以下情况: def rate(username: String, params: Map[String, String]): Validation
我有一个像这样的 Yaml 文件 name: hhh_aaa_bbb arguments: - !argument name: inputsss des
我有一个表单,人们可以单击并向表单添加字段,并且我需要让它在单击时验证这些字段中的值。 假设我单击它两次并获取 2 个独立的字段集,我需要旋转 % 以确保它在保存时等于 100。 我已放入此函数以使其
在我的页面中有一个选项可以创建新的日期字段输入框。用户可以根据需要创建尽可能多的“截止日期”和“起始日期”框。就像, 日期_to1 || date_from1 日期到2 ||日期_from2 date
我有一个像这样的 Yaml 文件 name: hhh_aaa_bbb arguments: - !argument name: inputsss des
有没有办法在动态字段上使用 jquery 验证表单。 我想将其设置为必填字段 我正在使用 Jsp 动态创建表单字段。 喜欢 等等...... 我想使用必需的表单字段验证此表单字段。 最佳答
嗨,任何人都可以通过提供 JavaScript 代码来帮助我验证用户名文本框不应包含数字,它只能包含一个字符。 最佳答案 使用正则表达式: (\d)+ 如果找到匹配项,则字符串中就有一个数字。 关于J
我有两个输入字段holidayDate和Description(id=tags) $(document).ready(function() {
我遇到了这个问题,这些验证从电子邮件验证部分开始就停止工作。 我只是不明白为什么即使经过几天的观察,只是想知道是否有人可以在这里指出我的错误? Javascript部分: function valid
我是一名优秀的程序员,十分优秀!