python - 我的类构造函数的“接口”应该是我的类的一部分吗?(如何?)
问题描述
我有一个带有非常通用的初始化器的类,它接受args
和的任意组合kwargs
。我想实现另一种构建实例的方法,它将使用 3 个列表:一个 forargs
和两个 for kwargs
( Key
and values
,两者的长度相同)。显然,我不能用我的常规__init()__
方法做到这一点,因为传递 3 个列表是一个完全有效的案例。
class MyVeryGenericClass:
__init__(self, *args, **kwargs):
pass #Do something really nice with args and kwargs, any case is valid.
出于这个原因,我想,我将不得不使用另一个函数来环绕我的__init__
函数,如下所示:
def mvgc_wrapper(lll, keys, vals):
if len(keys) != len(vals):
raise ValueError("keys and vals must have the same length.")
return MyVeryGenericClass(*lll, **dict(zip(keys, vals)))
问题是:我的包装函数是否应该是我的类的方法,出于什么原因,如果是这样,那么如何?
- 一方面,除了像
__new__
and这样的特殊方法外__init__
,类实例应该已经存在,但事实并非如此。 - 另一方面,让我的包装器成为我的类的一部分以使其成为整体会更合乎逻辑。
- 否则,我是否应该以与 a 相同的方式定义它
__new__
,使用 cls 参数而不是 self. 我试图让它像这样写,但它似乎不起作用。
代码:
#!/usr/bin/python3
# coding: UTF-8
import traceback
class MyVeryGenericClass:
def __init__(self, *args, **kwargs):
self.args = args
self.kwargs = kwargs
def __repr__(self):
return repr(self.args)+repr(self.kwargs)
def wrapper(cls, lll, keys, vals):
if len(keys) != len(vals):
raise ValueError("keys and vals must have the same length.")
return MyVeryGenericClass(*lll, **dict(zip(keys, vals)))
def wrapper2(cls, lll, keys, vals):
if len(keys) != len(vals):
raise ValueError("keys and vals must have the same length.")
return cls(*lll, **dict(zip(keys, vals)))
def wrapper3(cls, lll, keys, vals):
if len(keys) != len(vals):
raise ValueError("keys and vals must have the same length.")
return cls.MyVeryGenericClass(*lll, **dict(zip(keys, vals)))
genlist = [1, 2, 3]
genkeys = ["spam", "eggs"]
genvals = ["foo", "bar"]
try:
cmd="instance1 = MyVeryGenericClass(genlist, genkeys, genvals)"
print(">", cmd)
exec(cmd)
print("instance1 = {}".format(repr(instance1)))
except TypeError: traceback.print_exc()
print()
try:
cmd="instance2 = instance1.wrapper(genlist, genkeys, genvals)"
print(">", cmd)
exec(cmd)
print("instance2 = {}".format(repr(instance2)))
except TypeError: traceback.print_exc()
print()
try:
cmd="failed_instance = MyVeryGenericClass.wrapper(genlist, genkeys, genvals)"
print(">", cmd)
exec(cmd)
print("failed_instance = {}".format(repr(failed_instance)))
except TypeError: traceback.print_exc()
print()
try:
cmd="failed_instance = MyVeryGenericClass.wrapper2(genlist, genkeys, genvals)"
print(">", cmd)
exec(cmd)
print("failed_instance = {}".format(repr(failed_instance)))
except TypeError: traceback.print_exc()
print()
try:
cmd="failed_instance = MyVeryGenericClass.wrapper3(genlist, genkeys, genvals)"
print(">", cmd)
exec(cmd)
print("failed_instance = {}".format(repr(failed_instance)))
except TypeError: traceback.print_exc()
产生:
RESTART: /media/raid/ArcFolder/Mes documents/Mes Textes/Mes programmes/python/init_wrapper.py
> instance1 = MyVeryGenericClass(genlist, genkeys, genvals)
instance1 = ([1, 2, 3], ['spam', 'eggs'], ['foo', 'bar']){}
> instance2 = instance1.wrapper(genlist, genkeys, genvals)
instance2 = (1, 2, 3){'eggs': 'bar', 'spam': 'foo'}
> failed_instance = MyVeryGenericClass.wrapper(genlist, genkeys, genvals)
Traceback (most recent call last):
File "/media/raid/ArcFolder/Mes documents/Mes Textes/Mes programmes/python/init_wrapper.py", line 51, in <module>
exec(cmd)
File "<string>", line 1, in <module>
TypeError: wrapper() missing 1 required positional argument: 'vals'
> failed_instance = MyVeryGenericClass.wrapper2(genlist, genkeys, genvals)
Traceback (most recent call last):
File "/media/raid/ArcFolder/Mes documents/Mes Textes/Mes programmes/python/init_wrapper.py", line 58, in <module>
exec(cmd)
File "<string>", line 1, in <module>
TypeError: wrapper2() missing 1 required positional argument: 'vals'
> failed_instance = MyVeryGenericClass.wrapper3(genlist, genkeys, genvals)
Traceback (most recent call last):
File "/media/raid/ArcFolder/Mes documents/Mes Textes/Mes programmes/python/init_wrapper.py", line 65, in <module>
exec(cmd)
File "<string>", line 1, in <module>
TypeError: wrapper3() missing 1 required positional argument: 'vals'
编辑:感谢@kindall,通过#classmethod
在替代构造函数上方添加解决方案。但现在的问题是:如何区分备用构造函数和备用初始化器?
解决方案
解决了,感谢@kindall。我需要在@classmethod
我的备用初始化程序上方添加:
#!/usr/bin/python3
# coding: UTF-8
import traceback
class MyVeryGenericClass:
def __init__(self, *args, **kwargs):
self.args = args
self.kwargs = kwargs
def __repr__(self):
return repr(self.args)+repr(self.kwargs)
@classmethod
def wrapper(cls, lll, keys, vals):
if len(keys) != len(vals):
raise ValueError("keys and vals must have the same length.")
return MyVeryGenericClass(*lll, **dict(zip(keys, vals)))
@classmethod
def wrapper2(cls, lll, keys, vals):
if len(keys) != len(vals):
raise ValueError("keys and vals must have the same length.")
return cls(*lll, **dict(zip(keys, vals)))
genlist = [1, 2, 3]
genkeys = ["spam", "eggs"]
genvals = ["foo", "bar"]
try:
cmd="instance1 = MyVeryGenericClass(genlist, genkeys, genvals)"
print(">", cmd)
exec(cmd)
print("instance1 = {}".format(repr(instance1)))
except TypeError: traceback.print_exc()
print()
try:
cmd="instance2 = instance1.wrapper(genlist, genkeys, genvals)"
print(">", cmd)
exec(cmd)
print("instance2 = {}".format(repr(instance2)))
except TypeError: traceback.print_exc()
print()
try:
cmd="failed_instance = MyVeryGenericClass.wrapper(genlist, genkeys, genvals)"
print(">", cmd)
exec(cmd)
print("failed_instance = {}".format(repr(failed_instance)))
except TypeError: traceback.print_exc()
print()
try:
cmd="failed_instance = MyVeryGenericClass.wrapper2(genlist, genkeys, genvals)"
print(">", cmd)
exec(cmd)
print("failed_instance = {}".format(repr(failed_instance)))
except TypeError: traceback.print_exc()
生产:
RESTART: /media/raid/ArcFolder/Mes documents/Mes Textes/Mes programmes/python/init_wrapper.py
> instance1 = MyVeryGenericClass(genlist, genkeys, genvals)
instance1 = ([1, 2, 3], ['spam', 'eggs'], ['foo', 'bar']){}
> instance2 = instance1.wrapper(genlist, genkeys, genvals)
instance2 = (1, 2, 3){'spam': 'foo', 'eggs': 'bar'}
> instance3 = MyVeryGenericClass.wrapper(genlist, genkeys, genvals)
instance3 = (1, 2, 3){'spam': 'foo', 'eggs': 'bar'}
> instance4 = MyVeryGenericClass.wrapper2(genlist, genkeys, genvals)
instance4 = (1, 2, 3){'spam': 'foo', 'eggs': 'bar'}
推荐阅读
- c# - OntriggerEnter 未调用 playerController
- javascript - 如何从字符串制作 HTML 元素,然后在 React 中选择一个元素?
- css - 如何在 React 中隐藏包装的组件
- cassandra - 无法强制转换为格式化日期 - Cassandra 时间戳类型
- laravel - laravel 数据库种子数据透视表
- java - 处理3中二维数组的变化值
- ios - 在 UIViewControllerTransitioning 如何在转换进行时点击视图内的按钮?
- javascript - 从索引视图中的部分视图重新渲染索引视图?
- java - 如何通过 Android HAL 创建环回摄像头?
- javascript - Javascript绑定函数实现