我的班级构造函数的《接口》应该成为我班级的一部分吗? (如何?)

时间:2019-03-29 00:43:27

标签: python python-3.x class constructor

我有一个带有非常通用的Initialisator的类,可以接受argskwargs的任意组合。我想实现另一种构建实例的方法,该方法将使用3个列表:一个用于args,两个用于kwargsKeyvalues,它们的长度相同) 。显然,我无法使用常规的__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__之类的特殊方法外,该类实例应该已经存在,并非如此。
  • 另一方面,让我的包装器成为类的一部分以使其整体成为更合理。
  • 否则,是否应该以{{1​​}}的相同方式定义它,并使用cls参数代替self。我试图像这样编写它,但似乎不起作用。

代码:

__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' 来解决问题。但是现在的问题是:我该如何区分备用构造函数和备用初始化函数?

2 个答案:

答案 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'}