16
votes

Would it be possible to use a variable as a function name in python? For example:

list = [one, two, three]
for item in list:
    def item():
         some_stuff()
6
So you want a bunch of functions that all do the same thing? - Jeffrey Swan
It's clearly an XY problem, please show us WHAT is a problem you are trying to solve, not HOW you think you want to solve it. - Łukasz Rogalski
Using list as a variable name is a bad idea too... - Hugh Bothwell
Whatever you are doing, the way you are thinking is wrong! May be you should learn about generators. - ssapkota

6 Answers

21
votes

The trick is to use globals():

globals()['use_variable_as_function_name']()

will be equivalent to

use_variable_as_function_name()

found at: George Sakkis https://bytes.com/topic/python/answers/792283-calling-variable-function-name


The following is a useful application of the above questioning I needed right now (that's why I came here): apply special functions to URLs depending on their nature:

l = ['condition1', 'condition2', 'condition3']

I used to write

if 'condition1.' in href:
    return do_something_condition1()
if 'condition2.' in href:
    return do_something_condition2()
if 'condition3.' in href:
    return do_something_condition3()

and so on - my list has 19 members by now and keeps growing.

While investigating the subject and developing, the function code had been quite naturally part of the main function making it soon horrible to read, so relocating the working code into functions was a great relief already.

This clumsy code above can be substituted by:

for e in l:              # this is my condition list
    if e + '.' in href:  # this is the mechanism to choose the right function
        return globals()['do_something_' + e]()

This way the main code stays simple and legible no matter how long the list of conditions may grow.

Those functions corresponding to the condition labels have to be declared conventionally, of course, depending on the nature of the type of the URL in question:

def do_something_condition1(href):
    # special code 1
    print('========1=======' + href)

def do_something_condition2(href):
    # special code 2
    print('========2=======' + href)

def do_something_condition3(href):
    # special code 3
    print('========3=======' + href)

Test:

>>> href = 'https://google.com'
>>> for e in l:
...     globals()['do_something_' + e](href)
...
========1=======https://google.com
========2=======https://google.com
========3=======https://google.com

Or, to model it closer to the above scenario:

success = '________processed successfully___________ ' 

def do_something_google(href):
    # special code 1
    print('========we do google-specific stuff=======')
    return success + href 

def do_something_bing(href):
    # special code 2
    print('========we do bing-specific stuff=======')
    return success + href 

def do_something_wikipedia(href):
    # special code 3
    print('========we do wikipedia-specific stuff=======')
    return success + href 

Test:

l = ['google', 'bing', 'wikipedia']

href = 'https://google.com'

def test(href):
    for e in l:
        if e + '.' in href:
            return globals()['do_something_' + e](href)

>>> test(href)
========we do google-specific stuff=======
'________processed successfully___________ https://google.com'

Result:

Further elaboration on the problem now just amounts to augment the condition list one by one and write the corresponding functions depending on the argument. The above mechanism will pick the right one thereafter.

11
votes

You can't define a function using a variable but you can rebind the function to the variable name. Here is an example to add them to the module's global namespace.

one = 'one'
two = 'two'
three = 'three'
l = [one, two, three]
def some_stuff():
    print("i am sure some stuff")
for item in l:
    def _f():
        some_stuff()
    globals()[item] = _f
    del _f

one()
two()
three()
10
votes

Functions in Python are objects that have a name referencing them, so you can pass them around, store in lists and dictionaries (common use when creating jump-tables).

I.e. this works:

   def one():
        print "1"

    def two():
        print "2"

    def three():
        print "3"

    l = [one, two, three]

    for item in l:
        item()

Will print:

1
2
3

Don't use list as variable name, because this way you redefine buildin.

def is the statement that is also executed, unlike function defenitions in compiled languages. So when you call def item(): you don't define function for one, two, three, but redefine item name.

In general it is not quite clear what you're trying to do, but it doesn't look like a good idea. May be explain what you try to accomplish, or rethink the way you want to do it.

5
votes

Here is a workaround wrapped in a class. It uses a dictionary for the mapping:

class function_class:
    def __init__(self,fCase):
        fDic = {'A':self.A,         # mapping: string --> variable = function name
                'B':self.B,
                'C':self.C}
        self.fActive = fDic[fCase]
    def A(self): print('here runs function A')
    def B(self): print('here runs function B')
    def C(self): print('here runs function C')
    def run_function(self):
        self.fActive()

#---- main ----------        
fList = ['A','B','C']              # list with the function names as strings
for f in fList:                    # run through the list
    g = function_class(f)
    g.run_function()

The output is:

here runs function A
here runs function B
here runs function C
2
votes

You can do this:

from types import FunctionType
from copy import copy

def copy_function(fn):
    return FunctionType(copy(fn.func_code), copy(fn.func_globals), name=item,
                        argdefs=copy(fn.func_defaults),
                        closure=copy(fn.func_closure))

list = ['one', 'two', 'three']

for item in list:
    def _fn():
        print(item)
    globals()[item] = copy_function(_fn)
list = map(eval, list)
1
votes

The short answer is no. When you declare a variable, you have bound a name to an object. The same is true when you declare a function. You can try it out for yourself in a python console and see what happens:

>name=1
>name
1
>def name(x): print(x+1)

>name
function name at 0x000001CE8B8122F0