【问题标题】:Static typing for `__slots__` in pythonpython中`__slots__`的静态类型
【发布时间】:2021-03-28 04:21:13
【问题描述】:

我知道 python 使用了鸭子类型,但我想知道是否可以对类变量强制执行类型验证,尤其是 __slots__

例如-

class Student:
def __init__(self, name):
    self.name = name

class Class:
    __slots__ = ('class_representative',
                 'var_2',
                 'var_3',
                 '...',  # Assume many more variables below
                )

    def __init__(self, *args, **kwargs):
        self.class_representative = kwargs.get('cr')
        self.var_2 = kwargs.get('v2')
        self.var_3 = kwargs.get('v3')
        ... # Assume many more variables below

在上面的示例中,我如何确保每当任何对象被分配给class_representative 变量时,它的类型应该始终为Student

是否可能出现以下情况?

class Class:
    __slots__ = ('class_representative': Student,
                 'var_2',
                 'var_3',
                 '...',  # Assume many more variables below
                )

【问题讨论】:

  • 您必须自己编写代码来强制执行...不确定__slots__ 的相关性是什么
  • 您是在询问静态类型检查以确保属性仅获取 Student 值,还是运行时检查?
  • @Blckknght 我想防止在程序执行的任何时候将除Student 之外的任何其他类型分配给class_representative 变量。
  • @aaryan:这并没有真正回答我的问题。静态类型检查发生在您运行程序之前,并试图证明您从未使用错误类型调用函数。运行时检查发生在程序运行时。它们的实现方式完全不同,所以你真的需要选择你想要的并做那件事。 __slots__ 与类型检查(任何一种)无关。它的目的是通过避免在每个实例中都需要 __dict__ 来帮助您为要创建大量对象的对象节省内存。
  • @Blckknght 很抱歉之前没有正确理解您的问题。是的,我想在这里进行静态类型检查。 Silvio Mayolo 在下面回答了一种方法,但它不适用于 *args/**kwargs 语法。有关详细信息,请参阅我的评论。

标签: python slots


【解决方案1】:

当您说“静态类型”时,我假设您指的是PEP 484。在这种情况下,__slots__ 完全没有区别,我们会像以往对 Python 类所做的那样注释实例变量的类型。

class Class:
    __slots__ = ('class_representative',)
    class_representative: Student

    def __init__(self, student: Student) -> None:
        self.class_representative = student

顺便说一句,如果您要在 Python 中进行静态类型检查(我强烈推荐它;这是一个设计精良的系统),在您的构造函数中获取和转发 *args**kwargs 是一个很好的方法来失去任何静态可验证性。获取您需要的参数,尽可能明确地提供类型,然后转发您必须提供的内容。

【讨论】:

  • 在某些地方,我有很多参数要传递给构造函数。如果我按照您建议的方式编写论据,它看起来会非常难看。因此我使用**kwargs,但随后我失去了静态可验证性。所以我想知道是否有办法以某种方式在__slots__ 中指定它们。
  • @aaryan:我不确定**kwargs 是否按照您的想法行事。在您的示例代码中,您的 __init__ 方法与根本没有方法相同。如果你不实现__init__,你将继承object.__init__,它不接受self以外的任何参数并且什么都不做。您的代码接受任意参数,但将它们传递给object.__init__,如果有任何参数(任何类型),它将引发异常。您班级中的任何内容都不会根据argskwargs 中的任何参数设置class_representative,所以我不确定您要输入什么检查。
  • @Blckknght 我已经改进了有问题的示例,以便更容易理解问题。
  • 我仍然同意@Blckknght。如果您想将实例变量class_representative 设置为参数cr,那么只需使用一个名为cr 的参数并使用它。 **kwargs 用于当您想要接受所有关键字参数作为字典时。这完全没有意义并且如果你知道期望什么参数的话,你会花费静态验证。
  • 另外,值得指出的是,只是为了确保没有误解。 __slots__ 主要是一种使班级规模更小的效率技巧。对于 Python 中的类来说,这绝不是必需的。因此,除非在极端瓶颈情况下使用此类(并且您已经对其进行了基准测试并发现了证据),否则__slots__ 可能为时过早。特别是,它在类中不是必需的,绝大多数 Python 类从不指定它
猜你喜欢
  • 1970-01-01
  • 2015-06-29
  • 2021-05-07
  • 2010-11-19
  • 2017-11-13
  • 2013-08-24
  • 2011-08-26
  • 2012-05-10
  • 2018-02-02
相关资源
最近更新 更多