Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Pythonic-如何使用多个参数初始化构造函数并进行验证_Python_Design Patterns - Fatal编程技术网

Pythonic-如何使用多个参数初始化构造函数并进行验证

Pythonic-如何使用多个参数初始化构造函数并进行验证,python,design-patterns,Python,Design Patterns,我是一个python noob,我正试图以“python式”的方式解决我的问题。我有一个类,它的\uuuu init\uuu方法包含6个参数。我需要验证每个参数,如果任何参数未能验证,则抛出/引发异常 这条路对吗 class DefinitionRunner: def __init__(self, canvasSize, flightId, domain, definitionPath, harPath): self.canvasSize = canvasSize

我是一个python noob,我正试图以“python式”的方式解决我的问题。我有一个类,它的
\uuuu init\uuu
方法包含6个参数。我需要验证每个参数,如果任何参数未能验证,则抛出/引发异常

这条路对吗

class DefinitionRunner:
    def __init__(self, canvasSize, flightId, domain, definitionPath, harPath):
        self.canvasSize = canvasSize
        self.flightId   = flightId
        self.domain     = domain
        self.harPath    = harPath
        self.definitionPath = definitionPath

        ... bunch of validation checks...
        ... if fails, raise ValueError ...

从广义上讲,这看起来像是你做这件事的方式。虽然严格地说,您也可以在分配之前而不是之后进行验证,尤其是在分配可能会占用大量时间或资源的情况下。另外,样式约定要求不要像您这样对齐赋值块。

我会像您那样做。除了验证性的东西。我将在setter方法中进行验证,并使用它来设置属性。

如果希望变量可以独立于
\uuuu init\uuuu
进行设置,则可以使用在单独的方法中实现验证

但是,它们只适用于新样式的类,因此需要将类定义为
class DefinitionRunner(object)

那么比如说,

    @property
    def canvasSize(self):
        return self._canvasSize

    @canvasSize.setter
    def canvasSize(self, value):
        # some validation here
        self._canvasSize = value

你可以这样做。为每种类型的输入创建一个验证器。创建一个助手函数以运行验证:

def validate_and_assign(obj, items_d, validators):
    #validate all entries
    for key, validator in validators.items():
        if not validator[key](items_d[key]):
            raise ValueError("Validation for %s failed" % (key,))

    #set all entries
    for key, val in items_d.items():
        setattr(obj, key, val)
您可以这样使用:

class DefinitionRunner:
    validators = {
        'canvasSize': canvasSize_validator,
        'flightId': flightId_validator,
        'domain': domain_validator,
        'definitionPath': definitionPath_validator,
        'harPath': harPath_validator,
    }

    def __init__(self, canvasSize, flightId, domain, definitionPath, harPath):
        validate_and_assign(self, {
            'canvasSize': canvasSize,
            'flightId': flightId,
            'domain': domain,
            'definitionPath': definitionPath,
            'harPath': harPath,
        }, DefinitionRunner.validators) 

当然,如果数据类型相同,验证程序可能是相同的函数。

我不确定这是否完全是“Pythonic”,但我定义了一个名为require\u type的函数装饰程序。(老实说,我想我是在网上找到的。)

然后,要使用它:

class SomeObject(object):

    @require_type("prop1", str)
    @require_type("prop2", numpy.complex128)
    def __init__(self, prop1, prop2):
        pass

这个看起来不错。您认为这可能不是一个好方法,有什么特别的原因吗?您正在进行哪些类型的验证?很多时候,这并不是完全必要的…验证是非常基本的,只是确保设置了一些特定的值,并且所有变量都不是空的。。。值是必需的。@NPE-我不确定是否缺少处理此问题的python特定功能。通常在执行类似操作时,您会编写大量的锅炉板代码。然而,其优点是,在初始化类实例之后,您仍然可以安全地知道用户无法将属性重置为不正常的属性。您可以通过重写
\uuuuuuu setattr\uuuuuu
在很大程度上避免样板文件,但您要么最终将该方法膨胀,或是授权给其他方法。不过,你至少可以不用那样写一堆setter。您还可以围绕
property
编写自己的decorator,它自动生成一个getter,只需要一个setter。谢谢。我现在没有选择这个,因为这不是我决定要做的,但这是一个很好的答案,我将进一步研究。这个逻辑只在对象周围有意义,所以直接将它放在类中,或在混合中。然后您可以做一些很好的事情,比如提供一个
register
方法来向类添加新的验证器。或者,如果验证器很简单,只需完全放弃外部基础结构,直接在字典中以lambda的形式编写验证器,然后在
\uuuuu init\uuuuu
中赋值时对其进行迭代。是的,mixin可能是最好的选择,使用类方法注册验证器库-这是一种有趣的方法。我会考虑这个,谢谢。你也可以使用断言语句。我一直在使用PyCharm IDE,如果您断言变量是某种类型,PyCharm可以为您提供代码完成。例如,我有一个名为
Email
的类。如果我在函数中添加一行:
assert-isinstance(email,email)
,PyCharm将知道email类的代码完成选项。我最终选择了这一行,因为这是目前工作量最小的应用程序。然而,我喜欢杰科泽拉的回答,并且很可能在将来实现这一点。
class SomeObject(object):

    @require_type("prop1", str)
    @require_type("prop2", numpy.complex128)
    def __init__(self, prop1, prop2):
        pass