在对象中实现打包/解包

Har*_*Har 1 python python-2.7

我有一个只包含属性的类,我想打包/解包来处理它.我collections.abc应该实现什么才能获得这种行为?

class Item(object):

    def __init__(self, name, age, gender)
        self.name = name
        self.age = age
        self.gender = gender

a, b, c = Item("Henry", 90, "male")
Run Code Online (Sandbox Code Playgroud)

我想避免使用namedtuple.

Kei*_*ith 25

解压 Python 3.7+ 数据类的更好选择如下:

from dataclasses import astuple, dataclass

@dataclass 
class Item:
    name: str
    age: int
    gender: str

    def __iter__(self):
        return iter(astuple(self))

a, b, c = Item("Henry", 90, "male")
Run Code Online (Sandbox Code Playgroud)

  • 不幸的是,“dataclasses.astuple()”会进行深度解包,这对于嵌套结构来说通常是不受欢迎的——(请参阅/sf/answers/3626186301/)。 (5认同)
  • 更简单、更快的浅层解包 `def __iter__(self): return iter(self.__dict__.values())` (3认同)
  • 如果数据类定义为使用槽(3.10 中添加的功能),则 self.__dict__.values() 可能不起作用。 (2认同)

jon*_*rpe 7

你可以解压缩任何Iterable.这意味着您需要实现该__iter__方法,并返回一个迭代器.在您的情况下,这可能只是:

def __iter__(self):
    return iter((self.name, self.age, self.gender))
Run Code Online (Sandbox Code Playgroud)

或者你可以把你的类的Iterator,然后__iter__return self和你需要实现__next__; 这是更多的工作,可能不值得努力.

有关更多信息,请参阅Python的迭代器,迭代和迭代协议究竟是什么?


根据我上面链接的问题,您还可以使用以下方法实现迭代__getitem__:

def __getitem__(self, index):
    return (self.name, self.age, self.gender)[index]
Run Code Online (Sandbox Code Playgroud)


JBe*_*rdo 5

另一种选择是命名元组

Item = collections.namedtuple('Item', ['name', 'age', 'gender']) 
Run Code Online (Sandbox Code Playgroud)

所以这是开箱即用的:

a, b, c = Item("Henry", 90, "male")
Run Code Online (Sandbox Code Playgroud)

如果您使用的是 Python 3.7+,您还可以利用更强大的数据类。但是您需要明确调用astuple

@dataclasses.dataclass
class Item(object):
    name: str
    age: int
    gender: str

a, b, c = dataclasses.astuple(Item("Henry", 90, "male"))
Run Code Online (Sandbox Code Playgroud)

  • 这个问题的字面意思是“我想避免使用命名元组”。 (2认同)