kj wrote:
In <7figv3f2m3p0...@mid.uni-berlin.de> "Diez B. Roggisch" <de...@nospam.web.de> 
writes:

Classes are not scopes.

This looks to me like a major wart, on two counts.

First, one of the goals of OO is encapsulation, not only at the
level of instances, but also at the level of classes.  Your comment
suggests that Python does not fully support class-level encapsulation.

Second, my example shows that Python puts some peculiar restrictions
on recursion.  Recursion!  One of the central concepts in the theory
of functions!  This is shown most clearly by the following elaboration
of my original example:

class Demo(object):
    def fact_rec(n):
        if n < 2:
            return 1
        else:
            return n * fact_rec(n - 1)

Why not fix the call? The correct way to call a method is with either the class name or an instance object, depending on whether it's a instance method or not. By default, a method is unbound, and its first argument is by convention called self. If you want to recurse, then add self in the appropriate places.

As you have it, neither of the methods can be called outside the class:

class Demo(object):
   def fact_rec(n):
       if n < 2:
           return 1
       else:
           return n * fact_rec(n - 1)
    ....

obj = Demo()
print obj.fact_rec(5)

gives error:

Traceback (most recent call last):
 File "M:\Programming\Python\sources\dummy\stuff2.py", line 20, in <module>
   print obj.fact_rec(5)
TypeError: fact_rec() takes exactly 1 argument (2 given)

To fix it, you need to either change the signature (add in 'self' argument before the n argument) or do some form of decorator to the function. If I assume you never intended this method to use 'self' (ie. it's a static method), then declare it so. And call it accordingly.


class Demo(object):
   @staticmethod
   def fact(n):
       if n < 2:
           return 1
       else:
           return n * Demo.fact(n - 1)


print Demo.fact(6)

On the other hand, if I assume you're just giving a simple example of what's really intended to be a normal method (called with an instance, that it uses), then you'd change it this way.

class Demo2(object):
   def fact(self, n):
       if n<2:
           return 1
       else:
           return n * self.fact(n-1)

obj = Demo2()
print obj.fact(5)

Now the only real restriction, as opposed to all these red-herrings, is that the class may not be used before it's complete. That only comes to play when class attributes (non-instance "variables") are defined in terms of class methods. So if you have such attributes to define, move them outside of the class, perhaps immediately after it.


class Demo(object):
   @staticmethod
   def fact(n):
       if n < 2:
           return 1
       else:
           return n * Demo.fact(n - 1)
Demo._classvar = Demo.fact(5)

    def fact_iter(n):
        ret = 1
        for i in range(1, n + 1):
            ret *= i
        return ret

    classvar1 = fact_iter(5)
    classvar2 = fact_rec(5)

This code won't compile as shown,
Sure it will compile. It just won't run. You get the error after compiling the function when *calling* it from the classvar* line. But at that time the class is not defined, and not everything is ready for use.

You can probably work around this by replacing the staticmethod decorator with an equivalent function call:.

class Demo9(object):
   def fact(n):
       if n < 2:
           return 1
       else:
           return n * Demo.fact(n - 1)

   _classvar = fact(5)
   fact = staticmethod(fact)

print Demo9._classvar
xx = Demo9()
print xx.fact(6)
print Demo9.fact(8)
but it does compile if the last
line (the call to the recursive fact_rec) is commented out.  There
is no justification for discriminating against recursive functions
in this context.  Recursive functions should be OK wherever functions
are OK.  I can't think of any other language that allows recursion
but not anywhere.

Is there any good reason (from the point of view of Python's overall
design) for not fixing this?

kynn


--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to