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

时间:2018-01-16 15:47:54

标签: python

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

class AClass:
    def __init__(self):
        pass

instance = AClass(var1=3, var2=5)

而不是写较重的

class AClass:
    def __init__(self, var1, var2):
        self.var1 = var1
        self.var2 = var2

或更重的

instance = AClass()
instance.var1 = 3
instance.var2 = 5

我错过了什么吗?

4 个答案:

答案 0 :(得分:5)

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

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

c = AClass(var1=1, var2='a')

答案 1 :(得分:4)

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

在现代Python世界中,有三个(优秀)速记初始化器这个术语很聪明,我采用它),根据您的需要。 无需使用__init__方法进行任何步法(这是您首先想要避免的)。

命名空间对象

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

您可以从argparse导入Namespace类(这里介绍:How do I create a Python namespace (argparse.parse_args value)?)。从Python 3.3开始。标准类型包中提供了SimpleNamespace类。

from types import SimpleNamespace
instance = SimpleNamespace(var1=var1, var2=var2)

你也可以写:

instance = SimpleNamespace()
instance.var1 = var1
instance.var2 = var2

让我们说它是“快速而肮脏的方式”,它可以在许多情况下起作用。一般来说,甚至没有必要申报你的班级。

如果您希望实例仍然有一些方法和属性,您仍然可以这样做:

class AClass(Namespace):
    def mymethod(self, ...):
        pass

然后:

instance = AClass(var1=var1, var2=var2, etc.)

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

命名元组

另一方面,如果您希望课程强制这些属性,那么您还有另一个更可靠的选项。

命名的元组生成不可变实例,这些实例一次性初始化。将它们视为普通元组,但每个项目也可以用点符号访问。这个类namedtuple是Python标准发行版的一部分。这就是你如何生成你的课程:

from collections import namedtuple
AClass = namedtuple("AClass", "var1 var2")

请注意定义有多酷和短,而不需要__init__方法。之后你可以完成课程。

创建一个对象:

instance = AClass(var1, var2)

instance = AClass(var1=var1, var2=var2)

命名列表

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

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

语法相同:

from namedlist import namedlist
AClass = namedlist("AClass", "var1 var2")

创建一个对象:

instance = AClass(var1, var2)

或:

instance = AClass(var1=var1, var2=var2)

然后你可以修改它们:

instance.var1 = var3

但您无法添加未定义的属性。

>>> instance.var4 = var4
  File "<stdin>", line 1, in <module>
AttributeError: 'instance' object has no attribute 'var4'

<强>用法

这是我的两位:

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

  2. namedtuple 类生成器非常适合生成函数返回的对象(请参阅Raymond Hettinger讲座中的brief explanation)。返回的元组不是返回用户需要在文档中查找的平淡元组,而是不言自明(dir或help会执行此操作)。并且它无论如何都与元组使用兼容(例如k,v, z = my_func())。而且它是不可变的,它有自己的优势。

  3. namedlist 类生成器在各种情况下都很有用,包括当你需要从函数返回多个值时,需要在稍后阶段进行修改(和你一样)仍然可以打开它们:k, v, z = instance)。如果您需要具有强制属性的适当类的可变对象,那么这可能是首选解决方案。

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

答案 2 :(得分:1)

您可以使用对象属性的字典表示,并使用给予构造函数的关键字参数更新其元素:

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

instance = AClass(var1=3, var2=5)
print(instance.var1, instance.var2) # prints 3 5

但是,考虑一下这种风格,考虑this question及其答案。除非你知道自己在做什么,否则最好一个一个地明确设置参数。对于你和其他人来说,这将更容易理解 - 明确比隐含更好。如果您使用__dict__.update方式,请正确记录。

答案 3 :(得分:-2)

尝试

class AClass:
    def __init__(self, **vars):
        self.var1 = vars.get('var1')