Reputation: 894
I'm scratching my head over how to conditionally unpack variables from a class depending on the number of variables you are unpacking into e.g. I get a different set of variables unpacked depending on the number I set on the left hand side of the assignment.
For example, lets consider a class that has both x, y, z and latitude & longitude positions:
class LatLonOrXYZ:
def __init__(self, x, y, z, lat, lon):
self.x, self.y, self.z = x, y, z
self.lat, self.lon = lat, lon
def __iter__(self):
# not sure...
return iter([self.x, self.y, self.z, self.lat, self.lon])
Now I want to achieve something like the following:
pos = LatLonOrXYZ(x=0, y=1, z=2, lat=3, lon=4)
x, y, z = *pos # 0, 1, 2
lat, lon = *pos # 3, 4
Are there any deep python magics that could accomplish this sort of thing or am I better off just writing a couple of methods that feel so unnecessary?
As ever, any help, insights or advice would be greatly received :-)
Upvotes: 0
Views: 234
Reputation: 1714
This is completely doable, but may not be the best application, in your example, of an iterable.
Basically, create a list
from your iterable, as in list([*pos])
, then slice it as desired like list([*pos])[0:3]
.
Here's your example code with this in operation:
class LatLonOrXYZ:
def __init__(self, x, y, z, lat, lon):
self.x, self.y, self.z = x, y, z
self.lat, self.lon = lat, lon
def __iter__(self):
# not sure...
return iter([self.x, self.y, self.z, self.lat, self.lon])
pos = LatLonOrXYZ(x=0, y=1, z=2, lat=3, lon=4)
x, y, z = list([*pos])[0:3]
lat, lon = list([*pos])[3:5]
print(x, y, z)
print(lat, lon)
Output:
0 1 2
3 4
As a side note, in your example code, you are calling your actual class object rather than your pos
instance. It's important to understand the difference.
Rather than:
pos = LatLonOrXYZ(x=0, y=1, z=2, lat=3, lon=4)
x, y, z = *LatLonOrXYZ # 0, 1, 2
lat, lon = *LatLonOrXYZ # 3, 4
What you want to do is:
pos = LatLonOrXYZ(x=0, y=1, z=2, lat=3, lon=4)
x, y, z = *pos # 0, 1, 2
lat, lon = *pos # 3, 4
The first line creates an object based on the class definition that is an instance
, or an object using the structure and behavior of the class
that you'll be using as a position in your code.
Consider the following:
pos_1 = LatLonOrXYZ(x=0, y=1, z=2, lat=3, lon=4)
pos_2 = LatLonOrXYZ(x=4, y=3, z=2, lat=1, lon=0)
These are two different objects with their own characteristics, both structured as the LatLonOrXYZ
class
has laid out. Separate buildings based on the same blueprint.
This is a really basic description meant to just point out the gist of the thing. You can read more about python classes
, here in technical form:
Or, as an example of the decent explainers, but by far not the only excellent, accessible discussion regarding this stuff for which you should google lots :) , here:
OOP in Python - at Real Python
Upvotes: 1