hussain sagar
hussain sagar

Reputation: 61

Not iterable object in python

I am trying to write a function that returns the variables contained in a class of type Rule. I need to iterate through it and get all variables and store them in a set.

class Rule:
    # head is a function
    # body is a *list* of functions
    def __init__(self, head, body):
        self.head = head
        self.body = body
    def __str__(self):
        return str(self.head) + ' :- ' + str(self.body)
    def __eq__(self, other):
        if not isinstance(other, Rule):
            return NotImplemented
        return self.head == other.head and self.body == other.body
    def __hash__(self):
        return hash(self.head) + hash(self.body)


class RuleBody:
    def __init__(self, terms):
        assert isinstance(terms, list)
        self.terms = terms
    def separator(self):
        return ','
    def __str__(self):
        return '(' + (self.separator() + ' ').join(
            list(map(str, self.terms))) + ')'
    def __eq__(self, other):
        if not isinstance(other, RuleBody):
            return NotImplemented
        return self.terms == other.terms
    def __hash__(self):
        return hash(self.terms)

My function is the following:

def variables_of_clause (self, c : Rule) -> set :
        returnSet = set()
        l = getattr(c, 'body')
        for o in l:
            returnSet.add(o)

Testing function

# The variables in a Prolog rule p (X, Y, a) :- q (a, b, a) is [X; Y]
def test_variables_of_clause (self):
        c = Rule (Function ("p", [Variable("X"), Variable("Y"), Atom("a")]),
                    RuleBody ([Function ("q", [Atom("a"), Atom("b"), Atom("a")])]))
        #assert
        (self.variables_of_clause(c) == set([Variable("X"), Variable("Y")]))

I keep getting an error that says: TypeError: 'RuleBody' is not iterable.

Upvotes: 0

Views: 858

Answers (1)

Djaouad
Djaouad

Reputation: 22794

RuleBody.terms is a list, not RuleBody, you can iterate over RuleBody.terms instead, however, you can make your RuleBody class iterable (by basically making it return RuleBody.terms's elements), using the __iter__ method:

class RuleBody:
    ... # everything
    ...
    def __iter__(self):
        return iter(self.terms)

Upvotes: 2

Related Questions