osdir.com


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Recursive method in class


Le 30/09/2019 ? 13:11, Anders M?rak Leffler a ?crit?:
> What do you mean by transformed? This is probably your understanding
> already, but a further consequence of when arguments are evaluated
> plus what you said about data attributes is that the fib(self, n - 1)
> call will follow the standard LEGB-lookup of whatever "fib" is, from
> the point of view of the function object. As far as I know, there is
> no transformation of these scopes - either when it comes to creating
> the class, or creating the instances. (self is just the instance,
> passed as an argument.)
> 
> Cf when you change a binding:
> 
>>>> def factorial(self, n):
> ...     if not n:
> ...             return 1
> ...     else:
> ...             return n * factorial(self, n - 1)
> ...
>>>> Dummy = type("DummyObject", (object, ), {"factorial" : factorial})
>>>> instance = Dummy()
>>>> def factorial(self, n):
> ...     print("Hello!")
> ...     return 999
> ...
>>>> instance.factorial(5)   # Where will the call go ("old" or "new" factorial?)? Where will possible recursive calls go (and why)?
> Hello!
> 4995
> 
> Oh, and as others have pointed out on this list - you/whoever runs the
> system sending the mail might want to change the return address.
> none at gmail.com is somewhat consistently classed as spam.
> 
> 
> 
> //Anders
> 
> PS. We could further complicate this by adding a call to
> self.factorial in the new function, but let's not go there. :)
> 

I understood your example, but it doesn't answer my initial question.
I try to rewrite my question:

The following code is working well and I don't really understand why

def factorial(self, n):
     if not n:
         return 1
     else:
         return n * factorial(self, n - 1)

Dummy = type("DummyObject", (object, ), {"factorial" : factorial})
instance = Dummy()
instance.factorial(3)

6  # correct

The problem is that "factorial" in line
"return n * factorial(self, n - 1)" should not have been found
because there is no factorial function defined in the current
scope.

if you use "class" keyword to define the class

class Dummy:

     def factorial(self, n):
         if not n:
             return 1
         else:
             return n * factorial(self, n - 1)

instance = Dummy()
instance.factorial(3)

It generate an error because "factorial" in line
"return n * factorial(self, n - 1)" is not found.

Traceback (most recent call last):
   File "<pyshell#42>", line 1, in <module>
     instance.factorial(3)
   File "<pyshell#40>", line 7, in factorial
     return n * factorial(self, n - 1)
NameError: name 'factorial' is not defined

This is OK to me

The correct way is to write:

class Dummy:

     def factorial(self, n):
         if not n:
             return 1
         else:
             return n * self.factorial(n - 1)

instance = Dummy()
instance.factorial(3)

6 # correct

So, to summarize, if you create a class with type(name, bases, dict_)
or with the "class" keyword, recursive methods can't be writen
in the same way. This is what puzzle me.