I have a class that only contains attributes and I would like packing/unpacking to work on it. What collections.abc
should I implement to get this behaviour?
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")
I would like to avoid using a namedtuple
.
Unpacking in Python refers to an operation that consists of assigning an iterable of values to a tuple (or list ) of variables in a single assignment statement. As a complement, the term packing can be used when we collect several values in a single variable using the iterable unpacking operator, * .
Understanding Python Sequence Unpacking Sequence unpacking in python allows you to take objects in a collection and store them in variables for later use. This is particularly useful when a function or method returns a sequence of objects.
Both * and ** are the operators that perform packing and unpacking in Python. The * operator (quite often associated with args) can be used with any iterable (such as a tuple, list and strings), whereas the ** operator, (quite often associated with kwargs) can only be used on dictionaries.
Above operation is called 'packing” as it pack all the arguments into one single variable that this method call receives into a tuple called args. We can use name other than args, but args is the most common and pythonic way of doing things.
You can unpack any Iterable
. This means you need to implement the __iter__
method, and return an iterator. In your case, this could simply be:
def __iter__(self):
return iter((self.name, self.age, self.gender))
Alternatively you could make your class an Iterator
, then __iter__
would return self
and you'd need to implement __next__
; this is more work, and probably not worth the effort.
For more information see What exactly are Python's iterator, iterable, and iteration protocols?
Per the question I linked above, you could also implement an iterable with __getitem__
:
def __getitem__(self, index):
return (self.name, self.age, self.gender)[index]
A better option for unpacking Python 3.7+ dataclasses is as follows:
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")
Another option would be a named tuple
Item = collections.namedtuple('Item', ['name', 'age', 'gender'])
So this works out of the box:
a, b, c = Item("Henry", 90, "male")
If you're on Python 3.7+, you could also take advantage of dataclasses which are more powerful. But you would need to explicitly call astuple
:
@dataclasses.dataclass
class Item(object):
name: str
age: int
gender: str
a, b, c = dataclasses.astuple(Item("Henry", 90, "male"))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With