Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Iterate through __slots__
#1
I have a class that uses slots (not the class shown below). The class has a generator that iterates through the attributes and returns those of a certain type.
class AClass:
    __slots__ = ('a', 'b', 'c')

    def __init__(self, a, b, c):
        super().__init__()
        self.a = a
        self.b = b
        self.c = c

    def numbers(self):
        for attr in self.__slots__:
            value = getattr(self, attr)
            if type(value) in (int, float):
                yield value

class BClass:
    def __init__(self, a, b, c):
        super().__init__()
        self.a = a
        self.b = b
        self.c = c

    def numbers(self):
        for value in self.__dict__.values():
            if type(value) in (int, float):
                yield value

class CClass(AClass):
    __slots__ = ('d', 'e')

    def __init__(self, a, b, c, d, e):
        super().__init__(a, b, c)
        self.d = d
        self.e = e

a = AClass('Word', 123, ('a','tuple'))
b = BClass('Word', 123, ('a','tuple'))
c = CClass('Word', 123, ('a','tuple'), 5.2, [1, 2, 3])

for number in a.numbers(): print('a contains', number)
for number in b.numbers(): print('b contains', number)
for number in c.numbers(): print('c contains', number)
I like the way BClass.numbers skips the step of using the key to get the value. All I care about are the values. But I cannot figure out how to do this with slots. I again get the feeling that there's something I am missing?

I know I should only ask one question at a time, but this is so closely related..

I have a class (CClass above) that inherits from my base class (AClass). When I search for numbers it unsurprisingly only finds the numbers in the slots added by CClass. I would like to find the numbers from the AClass slots too.

I did play around with using the mro. That works but is ugly. I tried using dir(), but that searches all the attributes up to class object. I tried having numbers call super(), but that didn't work and wasn't what I wanted anyway. I would like CClass to execute numbers using his superclass's slots (call same method wit supers' class data), not call the superclass's method with my slots.
Reply
#2
Mro is the way to go. Use
def all_slots(ob):
    if not hasattr(ob, 'mro'):
        ob = type(ob)
    for cls in reversed(ob.mro()):
        yield from cls.__dict__.get('__slots__', ())
and replace for attr in self.__slots__ with for attr in all_slots(self)

Edit: bugfix: changed getattr to __dict__.get to avoid repetition in case subclasses don't have slots.
Reply
#3
It took a bit of searching to find anything about "yield from". This is a reoccurring problem for me. I have an idea what I am looking for but have trouble finding answers. I would much rather figure this stuff out by myself instead of asking questions here.

Anyone have recommendation on where to search or how to search for information about the Python language? Python suffers from a glut of information sources, most of them repeating the same topics over and over.
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020