开发者

Dynamicly define the function name and function body with variables in python

I have below functions

def foo_001(para):
    tmp = para + 2
    return tmp

def foo_002(para):
    tmp = para * 2
    return tmp

def foo_003(para):
    tmp = para / 2
    return tmp

def foo_004(para):
    tmp = para - 2
    return tmp

those functions only have different in function names while the algorithm line e.g. "tmp = para - 2", besides that, the rest part are all same.

So, may I know if I can doing something like this:

def $fooname (para):         # $ is borrowed try to say fooname is a variable
    $alog                    # $algo is also variable
    return tmp

lst = [
      ['tmp = para + 2', "foo_001"],
      ['tmp = para * 2', "foo_002"],
      ['tmp = para / 2', "foo_003"],
      ['tmp = para - 2', "foo_004"],
      ]

In runtime, I can use lst[0][0] assign to $algo and using lst[0][1] assign to $fooname in somehow and I can invok开发者_如何学Goe the function via the lst[0][x] inside of the lst?


More specific for my problem here

file foo.py

def foo_001(para): tmp = para + 2 return tmp
def foo_002(para): tmp = para * 2 return tmp
def foo_003(para): tmp = para / 2 return tmp
...
def foo_100(para): tmp = #complex algo, return tmp

main.py

from foo import *
fun_name = ["foo_001","foo_002","foo_002" ... "foo_100"]

src = 1
rzt = [] 
for i in fun_name:
    rzt.extent(eval(i)(src)) 

Here are my questions:

  1. Can I get the fun_name list in runtime? I want to save them in a text file.
  2. I found there's a common part in function definition which is tmp = #algo. Can I extract them out form those definitions while can I define the functions in runtime? I want something like this:

file foo.py

def foo_factory(): 
    # in somehow
    return adict      #function_name/function pair 

template = [
["foo_001","tmp = para + 2"],
["foo_002","tmp = para * 2"],
["foo_002","tmp = para * 2"],
...
["foo_100","tmp = #complex algo"]

main.py

from foo import *
dic = foo_factory(template)
fun_name = dic.keys()
src = 1
rzt = [] 
for i in fun_name:
    rzt.extent(eval(i)(src)) 
        #or
    rzt.extent(dic(i)())


How are you going to call these functions if you don't know their name at "creating time"?

Wouldn't it be a better approach to hold an array of functions (closures) parametrized as you see fit?

I.e. (not tested, but should work):

def make_foo_func(op):
  def func(para):
    tmp = op(para, 2) 
    return tmp
  return func

And then:

import operator
foo_001 = make_foo_func(operator.add)
foo_oo2 = make_foo_func(operator.mul)
...


You're thinking in terms of string manipulation and named functions where you should think in terms of higher-order unnamed functions. They make this a breeze, without exploiting any dynamicness ;) (In fact, the Haskell equivalent would be considerably shorter and cleaner.)

Example:

import operator as op

def algo_factory(f):
    def algo(para):
        return f(para, 2)
    #maybe, for nicer debugging output: algo.__name__ = "..."
    return algo

algorithms = [
    mkAlgo(op.add),
    mkAlgo(op.mul),
    mkAlgo(op.truediv),
    mkAlgo(op.sub),
    #...
]

Also, depending on what you are doing, you might want algorithms to be a dict.


I think what you really want to do is save the functions themselves in a list and retrieve the function you want from the list.

foo_container = [foo_001,foo_002,foo_003,foo_004]

Then from there, the call:

foo_container[0](3)

would be the same as:

foo_001(3)


There are a lot of tools for manipulating functions at a high level in Python. However, from what you have written I don't understand what you're trying to do, so I can't say how to do it. So here is some rambling about things that you might find useful.

  • Don't write boilerplate code. The moment you find yourself writing the same thing that you wrote a couple of lines above, think to yourself: "how can I abstract this away?". Note that the answer might be "don't, it's easiest this way", but it also might be "aha! I can make a function factory!".

  • How on earth is making a function called foo_02 that performs division useful? I mean, clearly you're trying to simplify a more complicated problem (you are, right?) but you've removed all of the details that are useful. Think about the overall architecture of your code to work out why you need these functions.

  • Use operator a lot. It has functions for +, -, *, / and all that jazz. For instance:

    import operator as op
    operator.add(1,2) == 1 + 2
    
  • Use functools a lot. In particular, partial is your friend here:

    >>> from functools import partial
    >>> import operator as op
    >>> double = partial(op.mul, 2)
    >>> double(2)
    4
    >>> double(20)
    40
    


The typical answer to dynamical creation of functions are lambda forms:

>>> def make_incrementor(n):
...     return lambda x: x + n
...
>>> f = make_incrementor(42)
>>> f(0)
42
>>> f(1)
43

Probably you should use function pointers instead of lists with function names as strings. Also classes might be a concept to clean up your code, but your description is to vague to provide a more detailed answere.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜