-1

This simple loop works just fine:

>>> def loop (i):
        i+=i
        if 0<i<20:
            print i
            loop(i)


>>> loop (1)
2
4
8
16

But this one doesn't work and it exits the loop unexpectedly:

>>> from functools import partial
>>> def loop (i):
        i+=i
        if 0<i<20:
            print i
            partial(loop,i)


>>> loop(1)
2
>>> 

What's the problem? Is there a solution to make it work somehow?

That was just a simple function... My real question is:

Q: How to write a function which is able to loop over itself, each time with only a number of it's arguments? Should I look somewhere else (other than partial) ?

Dusk
  • 1,729
  • 10
  • 17

4 Answers4

4

partial creates a callable, so..

def loop (i):
        i+=i
        if 0<i<20:
            print i
            partial(loop,i)()
thkang
  • 11,215
  • 14
  • 67
  • 83
1

The problem is that you are incrementing i in the function. Dont increment i and pass i-1 in the loop function:-

>>> def loop(i):
...     if i>0 and i<20:
...             print i
...             loop(i-1)

Using this method, when you run your function, here is the output:-

>>> loop(1)
1
>>> loop(2)
2
1
>>> loop(3)
3
2
1
>>> loop(4)
4
3
2
1
>>> loop(20)
>>> loop(19)
19
18
17
16
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
>>> 
GodMan
  • 2,561
  • 2
  • 24
  • 40
1

Not sure what you are trying to achieve but partial does not actually run the function only constructs and returns the function with the arguments you've given 'fixed'

You need something like this to get the same result as in your first example:

>>> from functools import partial
>>> def loop (i):
        i+=i
        if 0<i<20:
            print i
            partial(loop,i)()
Kamil Szot
  • 17,436
  • 6
  • 62
  • 65
1

partial gives you back a function with some of its arguments already set - it doesn't actually call that function yet. You need to call the partial object to do that:

>>> def foo(a, b):
        print(a, b)
>>> bar = partial(foo, 5)
>>> bar
functools.partial(<function foo at 0x01E1A348>, 5)
>>> bar()
Traceback (most recent call last):
  File "<pyshell#6>", line 1, in <module>
    bar()
TypeError: foo() takes exactly 2 arguments (1 given)
>>> bar(4)
5 4

As you can see, partial here binds one argument to the function foo - it takes a function and some arguments, and gives back a function of that many less arguments than the original. You can make it work in your case by calling the partial immediately with partial(loop, i)(), but this is exactly the same as just calling loop(i). This implies that it is the wrong tool for you to use here - partial is mainly useful for the case that you want to pass a callable into another function (or just set it early to use later in your code) and set some (or all) of it's arguments at the time you make the decision to use that function, rather than at the time it is ultimately called.

lvc
  • 34,233
  • 10
  • 73
  • 98
  • Yes. I just used the simple loop function as an example to clarify my question. I didn't want to confuse people with an alien function. Thanks. – Dusk Apr 17 '13 at 07:27