Is there a shorthand initializer in Python?
我没有找到一个简短的构造函数调用的引用,它会初始化调用者选择的变量。 我在寻找
1 2 3 4 5 | class AClass: def __init__(self): pass instance = AClass(var1=3, var2=5) |
而不是写更重
1 2 3 4 | class AClass: def __init__(self, var1, var2): self.var1 = var1 self.var2 = var2 |
或者更重
1 2 3 | instance = AClass() instance.var1 = 3 instance.var2 = 5 |
我错过了什么吗?
您可以直接更新对象的
1 2 3 4 5 | class AClass: def __init__(self, **kwargs): self.__dict__.update(kwargs) c = AClass(var1=1, var2='a') |
这是一个很好的问题,对我来说也是一个难题。
在现代Python世界中,有三个(优秀的)速记初始化器(这个术语很聪明,我采用它),这取决于你的需求。没有任何需要使用
命名空间对象
如果您希望为实例分配任意值(即不由类强制执行),则应使用名为namespace的特定数据结构。命名空间对象是可通过点表示法访问的对象,您可以基本上为其分配所需的对象。
您可以从argparse导入Namespace类(这里介绍:如何创建Python命名空间(argparse.parse_args值)?)。从Python 3.3开始。标准类型包中提供了SimpleNamespace类。
1 2 | from types import SimpleNamespace instance = SimpleNamespace(var1=var1, var2=var2) |
你也可以写:
1 2 3 | instance = SimpleNamespace() instance.var1 = var1 instance.var2 = var2 |
让我们说它是"快速而肮脏的方式",它可以在许多情况下起作用。一般来说,甚至没有必要申报你的课程。
如果您希望实例仍然具有一些方法和属性,您仍然可以执行以下操作:
1 2 3 | class AClass(Namespace): def mymethod(self, ...): pass |
然后:
1 | instance = AClass(var1=var1, var2=var2, etc.) |
这为您提供了最大的灵活性
命名为元组
另一方面,如果您希望类强制执行这些属性,那么您还有另一个更可靠的选项。
命名元组生成不可变实例,它们一劳永逸地初始化。将它们视为普通元组,但每个项目也可以用点符号访问。这个类namedtuple是Python标准发行版的一部分。这是你如何生成你的类:
1 2 | from collections import namedtuple AClass = namedtuple("AClass","var1 var2") |
注意定义有多酷和短,而不是
并创建一个对象:
1 | instance = AClass(var1, var2) |
要么
1 | instance = AClass(var1=var1, var2=var2) |
命名清单
但是,如果您希望该实例是可变的,即允许您更新实例的属性,该怎么办?答案是命名列表(也称为RecordClass)。从概念上讲,它就像一个普通的列表,其中的项目也可以用点表示法访问。
有各种实现。我个人使用恰当命名的命名列表。
语法相同:
1 2 | from namedlist import namedlist AClass = namedlist("AClass","var1 var2") |
并创建一个对象:
1 | instance = AClass(var1, var2) |
要么:
1 | instance = AClass(var1=var1, var2=var2) |
然后你可以修改它们:
1 | instance.var1 = var3 |
但是您无法添加未定义的属性。
1 2 3 | >>> instance.var4 = var4 File"<stdin>", line 1, in <module> AttributeError: 'instance' object has no attribute 'var4' |
用法
这是我的两位:
命名空间对象是为了获得最大的灵活性,甚至不需要声明一个类;存在不正常行为的风险(但Python是同意成人的语言)。如果您只有一个实例和/或您知道自己在做什么,那将是最佳选择。
namedtuple类生成器非常适合生成函数返回的对象(请参阅Raymond Hettinger讲座中的简要说明)。返回的元组不是返回用户需要在文档中查找的平淡元组,而是不言自明(dir或help会执行此操作)。并且它无论如何都与元组使用兼容(例如
namedlist类生成器在很多情况下都很有用,包括当你需要从函数返回多个值时,需要在稍后阶段进行修改(你仍然可以解压它们:
如果您使用它们,这可能会显着减少编写类和处理实例所花费的时间!
您可以使用对象属性的字典表示,并使用给定构造函数的关键字参数更新其元素:
1 2 3 4 5 6 | class AClass: def __init__(self, **kwargs): self.__dict__.update(**kwargs) instance = AClass(var1=3, var2=5) print(instance.var1, instance.var2) # prints 3 5 |
但是,考虑到这个问题的风格,请考虑这个问题及其答案。 除非你知道自己在做什么,否则最好一个一个地明确设置参数。 对于你和其他人来说,这将更容易理解 - 明确比隐含更好。 如果以
尝试
1 2 3 | class AClass: def __init__(self, **vars): self.var1 = vars.get('var1') |