Python中是否有速记初始化器?

PPC*_*PPC 4 python

我没有找到一个简短的构造函数调用的引用,它会初始化调用者选择的变量.我在寻找

class AClass:
    def __init__(self):
        pass

instance = AClass(var1=3, var2=5)
Run Code Online (Sandbox Code Playgroud)

而不是写更重

class AClass:
    def __init__(self, var1, var2):
        self.var1 = var1
        self.var2 = var2
Run Code Online (Sandbox Code Playgroud)

或者更重

instance = AClass()
instance.var1 = 3
instance.var2 = 5
Run Code Online (Sandbox Code Playgroud)

我错过了什么吗?

Pat*_*ugh 6

您可以__dict__直接更新对象的属性,这是存储属性的位置

class AClass:
    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)

c = AClass(var1=1, var2='a')
Run Code Online (Sandbox Code Playgroud)

  • 您付出的代价是您不再对构造函数参数进行错误检查。 (3认同)

fra*_*lau 5

这是一个很好的问题,对我来说也是一个难题。

在现代的Python世界中,根据您的需要,有三个(出色的)速记初始值设定项这个术语很巧妙,我正在采用)。没有一个__init__方法需要任何步法(这是您首先要避免的方法)。

命名空间对象

如果您希望为实例分配任意值(即不由类强制执行),则应使用称为namespace的特定数据结构。命名空间对象是可以使用点表示法访问的对象,基本上可以为其分配所需的对象。

您可以从argparse导入Namespace类(在此介绍:如何创建Python名称空间(argparse.parse_args值)?)。从Python 3.3开始。一个SimpleNamespace类是可从标准类型包。

from types import SimpleNamespace
instance = SimpleNamespace(var1=var1, var2=var2)
Run Code Online (Sandbox Code Playgroud)

您还可以编写:

instance = SimpleNamespace()
instance.var1 = var1
instance.var2 = var2
Run Code Online (Sandbox Code Playgroud)

假设它是“快速而肮脏的方式”,在许多情况下都可以使用。通常,甚至都不需要声明您的类。

如果您希望实例仍然具有一些方法和属性,则仍然可以执行以下操作:

class AClass(Namespace):
    def mymethod(self, ...):
        pass
Run Code Online (Sandbox Code Playgroud)

然后:

instance = AClass(var1=var1, var2=var2, etc.)
Run Code Online (Sandbox Code Playgroud)

这为您提供最大的灵活性。

命名元组

另一方面,如果您希望类强制实施这些属性,那么您将拥有另一个更可靠的选择。

一个命名的元组产生不可变的实例,这些实例被一劳永逸地初始化。可以将它们视为普通的元组,但每个项目也都可以使用点符号来访问。名为tuple的此类是Python标准发行版的一部分。这是您生成类的方式:

from collections import namedtuple
AClass = namedtuple("AClass", "var1 var2")
Run Code Online (Sandbox Code Playgroud)

注意定义是多么的酷和简短,而不是__init__方法的要求。您实际上可以在那之后完成课程。

并创建一个对象:

instance = AClass(var1, var2)
Run Code Online (Sandbox Code Playgroud)

要么

instance = AClass(var1=var1, var2=var2)
Run Code Online (Sandbox Code Playgroud)

命名清单

但是,如果您希望该实例是可变的,即允许您更新该实例的属性,该怎么办?答案是命名列表(也称为RecordClass)。从概念上讲,它就像一个普通列表,其中的项目也可以使用点符号来访问。

有各种实现。我个人使用了恰当命名的namedlist

语法是相同的:

from namedlist import namedlist
AClass = namedlist("AClass", "var1 var2")
Run Code Online (Sandbox Code Playgroud)

并创建一个对象:

instance = AClass(var1, var2)
Run Code Online (Sandbox Code Playgroud)

要么:

instance = AClass(var1=var1, var2=var2)
Run Code Online (Sandbox Code Playgroud)

然后您可以修改它们:

instance.var1 = var3
Run Code Online (Sandbox Code Playgroud)

但是您不能添加未定义的属性。

>>> instance.var4 = var4
  File "<stdin>", line 1, in <module>
AttributeError: 'instance' object has no attribute 'var4'
Run Code Online (Sandbox Code Playgroud)

用法

这是我的两位:

  1. 命名空间对象具有最大的灵活性,甚至不需要声明类。存在实例无法正常运行的风险(但是Python是成年人同意的语言)。如果您只有一个实例和/或您知道自己在做什么,那将是一种方法。

  2. namedtuple类生成器非常适合生成用于函数返回的对象(请参阅Raymond Hettinger的演讲中的简要说明)。而不是返回用户需要在文档中查找的平淡的元组,返回的元组是不言自明的(目录或帮助会做到这一点)。而且它仍然与元组用法兼容(例如k,v, z = my_func())。加上它是一成不变的,具有自己的优势。

  3. namedlist类生成器在很多情况下都非常有用,包括当您需要从函数返回多个值时,然后需要在以后的阶段对其进行修改(您仍然可以解压缩它们:)k, v, z = instance。如果您需要来自具有强制属性的适当类的可变对象,则可能是首选的解决方案。

如果使用得当,可能会大大减少编写类和处理实例所花费的时间!