adikh
adikh

Reputation: 306

"class name" object has no attribute "function name" in Recursive Function

I am trying to implement a recursive function, in which my base condition is working fine, another condition is also working properly. But when I jump to the recursive condition it gives me error that,"class name" object has no attribute "function name" .

My class:

class NGram(object):
    def __init__(self):
        self.n = None
        self.ngramprobability = None
        self.uniquegrams = [
            ["sample", "this"],
            ["is", "a"],
            ["this", "is"],
            ["sample"],
            ["this"],
            ["a"],
            ["is"],
            ["a", "sample"],
        ]

        self.out = [
            [
                ["sample", 0.16666666666666666],
                ["this", 0.3333333333333333],
                ["a", 0.16666666666666666],
                ["is", 0.3333333333333333],
            ],
            [
                ["sample", "this", 1.0],
                ["is", "a", 0.5],
                ["this", "is", 1.0],
                ["a", "sample", 1.0],
            ],
        ]

    def get_prob(self, words):

        if len(words) == 1:
            probability = [j[-1] for i in self.out for j in i if j[:-1] == words][0]
            return probability  # condition works fine

        elif words in self.uniquegrams:
            probability = [j[-1] for i in self.out for j in i if j[:-1] == words][0]
            return probability  # condition works fine
        else:
            return self.get_prob(self, words[1:]) * 0.4

My script that is raising errors:

# train bi_gram
bi_gram = NGram()

c = bi_gram.get_prob(["this", "sample"])
print(c)

Where I am making mistake?

Upvotes: 0

Views: 476

Answers (2)

bruno desthuilliers
bruno desthuilliers

Reputation: 77912

Here are two examples (you'll notice that I removed everything that's irrelevant and only kept what's necessary to reproduce the issues) :

1/ forgetting to use self. to reference the method:

class NGram(object):
    def get_prob(self, words):
        if len(words) == 1:
            return 1        
        else: 
            return get_prob(words[1:]) * 0.4

ng = NGram()
print(ng.get_prob(["foo"]))
print(ng.get_prob(["foo", "bar"]))

which constantly raises a NameError on the second call:

1
Traceback (most recent call last):
  File "probs.py", line 10, in <module>
    print(ng.get_prob(["foo", "bar"]))
  File "probs.py", line 6, in get_prob
    return get_prob(words[1:]) * 0.4
NameError: global name 'get_prob' is not defined

2/ using self. to reference the method but incorrectly passing self as argument:

class NGram(object):
    def get_prob(self, words):
        if len(words) == 1:
            return 1        
        else: 
            return self.get_prob(self, words[1:]) * 0.4

ng = NGram()
print(ng.get_prob(["foo"]))
print(ng.get_prob(["foo", "bar"]))

which constantly raises a TypeError on the second call:

1
Traceback (most recent call last):
  File "probs.py", line 10, in <module>
    print(ng.get_prob(["foo", "bar"]))
  File "probs.py", line 6, in get_prob
    return self.get_prob(self, words[1:]) * 0.4
TypeError: get_prob() takes 2 positional arguments but 3 were given

And to address your issue - which you wouldn't have if you had done the tutorial -, the correct way is:

 class NGram(object):
    def get_prob(self, words):
        if len(words) == 1:
            return 1        
        else: 
            return self.get_prob(words[1:]) * 0.4

ng = NGram()
print(ng.get_prob(["foo"]))
print(ng.get_prob(["foo", "bar"]))

which works as expected:

1
0.4

Upvotes: 2

Syed Rafay
Syed Rafay

Reputation: 1500

Short answer: replace your code at line #22 from

return self.get_prob(self, words[1:]) * 0.4

to

return self.get_prob(words[1:]) * 0.4

You are not supposed to give self as an argument when calling any function of a class (it's only included in the definition).

Long answer: Check @Bruno's answer

Upvotes: 1

Related Questions