简体   繁体   中英

Unpacking tuple to autorun a function with parameters of unknown length in python 2

Using a tuple I would like to autorun a function passing the rest of the tuple as parameters. It's easier to understand what i'm trying to do if i show you what i have so far:

def Function1(var1,var2,post=False):
    if post: print "Function One "+str(var1)+str(var2)
    return "FN1"

def Function2(var1,var2,var3,var4,post=False):
    if post: print "Function Two "+str(var1)+str(var2)+str(var3)+str(var4)
    return "FN2"


pattern = ( ('Function1',1,2) , ('Function2',1,2,3,4) )
IDs = []

#the next line is the line i can't get working, i[0] is successfully calling
#but i can't get the tuple to pass (var,var,True)
#instead it passes to the function as ((var,var),True)
for i in pattern: IDs += eval(i[0])(i[1:],True)

print IDs

I want my output to be:

'''
Function One 12
Function Two 1234
["FN1","FN2"]
'''

You don't mention how it isn't working, but this should do it for you:

for i in pattern: 
    IDs += eval(i[0])(*i[1:], post=True)

Note that there are better ways than eval to find a function from a string. If you don't have total control over those lists of tuples, then you are asking for trouble.

You shouldn't be so quick to preclude other ideas. You don't seem to have much Python knowledge yet, so other ideas might be really good. For example, instead of:

if post: print "Function Two "+str(var1)+str(var2)+str(var3)+str(var4)

why not the more readable:

if post: 
    print "Function Two %s %s %s %s" % (var1, var2, var3, var4)

You need three things:

  • The magic star operator to turn the list slice into separate arguments.
  • Making post a named argument so it doesn't conflict with the magic star.
  • Append instead of += to separate the returned strings properly.

So:

for i in pattern: 
    IDs.append( eval(i[0])(*i[1:],post=True) )

print IDs

Mandatory eval() Lecture: Experienced Python programmers consider eval() to be a dangerous last resort. You should look up functions by name in the local module's dictionary instead:

for i in pattern:
    # look up i[0] in the symbol dictionary of the current module
    fun = sys.modules[__name__].__dict__[ i[0] ]
    IDs.append( fun(*i[1:],post=True) )

It's even cleaner and easier if you can restrict the functions to be executed by name to methods within a class object; you need only reference yourObject.__dict__[ functionName ] .

Using a lookup table (easier and more controlled than the local namespace even) instead of eval and appending to the list properly might look like this:

def Function1(var1,var2,post=False):
    if post:
        print "Function One "+str(var1)+str(var2)
    return "FN1"

def Function2(var1,var2,var3,var4,post=False):
    if post:
        print "Function Two "+str(var1)+str(var2)+str(var3)+str(var4)
    return "FN2"

allowableFunctions = {
    'Function1': Function1,
    'Function2': Function2,
}    

pattern = ( ('Function1',1,2) , ('Function2',1,2,3,4) )
IDs = []

for i in pattern:
    IDs.append(allowableFunctions[i[0]](*i[1:], post=True))

print IDs

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM