python 类可以使用类似于可迭代列表的赋值解包吗?

wfveoks0  于 2023-03-16  发布在  Python
关注(0)|答案(4)|浏览(118)

我有一个列表myList = [[1, 2], [3, 4], [5, 6]],可以使用赋值解包来得到list_instance0, list_instance1, list_instance2 = myList
如果我有课:

class myClass():
    def __init__(self, a: int, b: int):
        self.a = a
        self.b = b
    
    def printAB(self):
        return self.a, self.b

现在,如果我想分配list_instance[i],我可以做:

classInstance0=myClass(*list_instance0)
classInstance1=myClass(*list_instance1)
classInstance2=myClass(*list_instance2)

如果我去尝试

subClass0, subClass1, subClass2 = myClass(*list_instance0, *list_instance1, *list_instance2)
# error "myClass" is not iterable: __iter__ method not defined

因此,我想知道是否有一种方法可以以更动态的方式将classInstance[i]list_instance[i]一起分配给myClass,而不必单独分配每一个?

whitzsjs

whitzsjs1#

您只需要在列表上MapMyClass

from itertools import starmap

subClass0, subClass1, subClass2 = starmap(myClass, myList)

starmap确保每个子列表的 contents 作为单独的参数传递给myClass,而不是子列表本身作为单个参数传递。
或者你可以使用列表解析来更明确一点:

subClass0, subClass1, subClass2 = [myClass(*x) for x in myList]
bpsygsoo

bpsygsoo2#

这是一个有趣的问题。老实说,我根本不相信有一种方法可以自动地将子列表分解成一个类示例。
下面的代码,我不知道它在Python中是否有效:

MyClass(*subList0), MyClass(*subList1), MyClass(*subList2) = myList

我建议定义一个helper类方法from_list,在给定列表my_list的情况下,自动创建类对象的可迭代对象:

@classmethod
def from_list(cls, super_list: list[list[int]]) -> Iterable[MyClass]:
    for sub_list in super_list:
        yield cls(*sub_list)

完整的用法如下,当类示例被print艾德时,使用dataclasses模块以获得更好的输出:

from __future__ import annotations

from dataclasses import dataclass
from typing import Iterable

@dataclass
class MyClass:
    a: int
    b: int

    def printAB(self):
        return self.a, self.b

    @classmethod
    def from_list(cls, super_list: list[list[int]]) -> Iterable[MyClass]:
        for sub_list in super_list:
            try:
                yield cls(*sub_list)
            except TypeError:
                raise ValueError(f'value `{sub_list}` @ index={super_list.index(sub_list)}: '
                                 f'expected 2 elements, got {len(sub_list)}') from None

my_list = [[1, 2], [3, 4], [5, 6]]

# alternatively:
#   for sc in MyClass.from_list(my_list):
#       print(sc)

subClass0, subClass1, subClass2 = MyClass.from_list(my_list)

print(subClass0)
print(subClass1)
print(subClass2)

输出:

MyClass(a=1, b=2)
MyClass(a=3, b=4)
MyClass(a=5, b=6)
bihw5rsg

bihw5rsg3#

我想你误解了继承。你调用sublcass的项不是myClass的 subclasses。它们是myClass的 instances。所以简短的回答是no。为myClass调用构造函数返回单个对象。也就是说,myClass的一个示例。所以它不能被赋值给3个对象或一个可迭代对象,因为它返回单个对象。

46scxncf

46scxncf4#

myClass构造函数的一次调用返回三个myClass示例是没有意义的(从技术上讲,您可以通过对__new__执行一些奇怪的操作来实现这一点,但请不要这样做)。我认为,您需要的是某种工厂函数,它接受一系列init参数并为您提供一系列示例,因为你可以按照你想要的方式去解构它。例如:

def my_class_factory(*init_args):
    return [myClass(*args) for args in init_args]

subClass0, subClass1, subClass2 = my_class_factory(subList0, subList1, subList2)  # works
subClass0, subClass1, subClass2 = my_class_factory(*myList)  # also works!

注意,你调用的变量subClass * 不是子类 *,它们是myClass的 * 示例 *。

相关问题