0

python newbie here.

I am working my way towards a recursive, memoized (on a formula of two variables) function but I'm currently a ways away.

So currently I think my main problem is that after I call the function, fun1 initially, and do some manipulation, I then want to pass an altered group of initial agruments to the function again. But when I do that the error says it receives just one argument - a tuple. Here is the error and the script at the bottom. Currently I am just trying to remove one argument at a time (p1tpn) until there is only one left, but the real case will be different.

fun1(2,4,6)

I was called with 3 arguments: (2, 4, 6)
with arg <class 'tuple'>
[arg] is type: <class 'list'>
list on arg [2, 4, 6] and is type: <class 'list'>
argList is: [2, 4, 6]

[[2, 4], [6]]

first arg is: 2
rest of arg is: [4, 6]
I was called with 1 arguments: ([4, 6],)
with arg <class 'tuple'>
[arg] is type: <class 'list'>
list on arg [[4, 6]] and is type: <class 'list'>
argList is: [[4, 6]]

[[[4, 6]]]

first arg is: [4, 6]
rest of arg is: []

So I see that near the completion of the first call, with rest of arg is [4, 6], upon entering the second "call/instantiation" it says this is 1 argument. I guess the other things could have been taken out (memoize) but one can see they are not being implemented yet.

def partition(collection):
    if len(collection) == 1:
        yield [ collection ]
        return

    first = collection[0]
    for smaller in partition(collection[1:]):
        # insert `first` in each of the subpartition's subsets
        for n, subset in enumerate(smaller):
            yield smaller[:n] + [[ first ] + subset]  + smaller[n+1:]
        # put `first` in its own subset 
        yield [ [ first ] ] + smaller

def memoize(f):
    memo = {}
    def helper(x):
        if x not in memo:
            memo[x] = f(x)
        return memo[x]
    return helper

fun1 = memoize(fun1)

def fun1(*arg):
    lArg = len(arg)
    firstNumber = arg[0]
    print("I was called with", len(arg), "arguments:", arg)
    print("with arg", type(arg))
    argList = list(arg)
    print("argList is:",argList)
    print("first arg is:", arg[0])
    p1tpn = argList[1:]
    print("rest of arg is:", p1tpn)
#
    if firstNumber == 1 : return 1
    else: fun1(p1tpn)

The partition function definition I got from Set partitions in Python

nate
  • 269
  • 2
  • 11

1 Answers1

1

The def fun1(*args) (note that this is the function definition) syntax packs any number of passed in arguments into a list. In your recursive call you are indeed passing in just a single argument, the list itself. You'll want to modify the recursive call to un pack the list of arguments for the function call fun1(*p1tpn)

Here's some more info on the semantics of the * and ** operators What does ** (double star/asterisk) and * (star/asterisk) do for parameters?

Also, as a side note you can use the built-in lru_cache for the memoization:

https://docs.python.org/3/library/functools.html#functools.lru_cache

Matti Lyra
  • 12,828
  • 8
  • 49
  • 67
  • Aahhh I didn't know what the operation was called... with "packing" I quickly found: https://stackoverflow.com/questions/12786102/unpacking-function-argument I will spend some time looking over your links. – nate Jan 20 '18 at 21:06
  • yeah, so the problem is that it does both "packing" and "unpacking" depending on where it's used, in function _calls_ it unpacks lists, but in function definitions it (kind of) _packs_ arguments into tuples – Matti Lyra Jan 20 '18 at 21:13