我有一个带有非常通用的Initialisator的类,可以接受args
和kwargs
的任意组合。我想实现另一种构建实例的方法,该方法将使用3个列表:一个用于args
,两个用于kwargs
(Key
和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__
和__init__
之类的特殊方法外,该类实例应该已经存在,并非如此。代码:
__new__
产生:
#!/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()
编辑:
感谢@kindall,可以通过在备用构造函数上方添加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'
来解决问题。但是现在的问题是:我该如何区分备用构造函数和备用初始化函数?
答案 0 :(得分:0)
如果您可以控制类代码,则只需执行以下操作:
class A:
def __init__(self, args, keys, values):
self.args = args
self.kwargs = dict(zip(keys, values))
def __repr__(self):
return repr(self.args) + repr(self.kwargs)
您可以按照显示的方式使用:
>>> genlist = [1, 2, 3]
>>> genkeys = ["spam", "eggs"]
>>> genvals = ["foo", "bar"]
>>> a = A(genlist, genkeys, genvals)
>>> print(a)
[1, 2, 3]{'spam': 'foo', 'eggs': 'bar'}
除非有充分的理由不这样做,最好的办法可能是直接将键/值对直接作为关键字参数传递:
class A:
def __init__(self, *args, **kwargs):
pass
a = A(genlist, **dict(zip(genkeys, genvals)))
答案 1 :(得分:0)
已解决,感谢@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'}