首页 > 解决方案 > 我的类构造函数的“接口”应该是我的类的一部分吗?(如何?)

问题描述

我有一个带有非常通用的初始化器的类,它接受args和的任意组合kwargs。我想实现另一种构建实例的方法,它将使用 3 个列表:一个 forargs和两个 for kwargs( Keyand 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)))

问题是:我的包装函数是否应该是我的类的方法,出于什么原因,如果是这样,那么如何?

代码:

#!/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在替代构造函数上方添加解决方案。但现在的问题是:如何区分备用构造函数和备用初始化器?

标签: pythonpython-3.xclassconstructor

解决方案


解决了,感谢@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'}

推荐阅读