標籤:

python如何才能批量生成函數呢?函數名分別等於一個list里的每個元素~?

比如:

lista = ["funca","funcb","funcc"]

想讀取這個lista里的每一個元素,批量分別生成名為funca,funcb,funcc的函數,

函數名必須是funca,funcb,funcc,因為函數內容是根據這個名稱來傳參執行。

比如他們的內容都是:

print sys._getframe().f_code.co_name

實際情況下這個list很長很長,所以不想一個個def這些函數。

求批量生成指定名稱函數的方法,求解惑_(:з」∠)_

手機打字可能排版不好望包涵~3q


import sys

lista = ["funca","funcb","funcc"]

FUNC_TEMPLATE = "def {func}(): print sys._getframe().f_code.co_name"

for fn in lista:
exec(FUNC_TEMPLATE.format(func=fn))

local_vars = dict(locals().items())

funcs = [local_vars[f] for f in lista]

Hacky -&> 測試就好,不建議check-in進生產環境

實際中考慮用閉包或者包裝成一個類更好,實現__call__方法即可。


def func(a=1):
print a

func2 = types.FunctionType(func.func_code, globals(), "func2", (2,))
func2()

types - Python code objects

但是上面的方法沒辦法改變位元組碼對象的內容,所以要再往上追溯,找到位元組碼對象的生成函數,根據位元組碼的內容自己生成位元組碼對象。實用性不高,Just for fun

import sys
import types

def func():
print sys._getframe().f_code.co_name

code_obj = func.func_code

def make_func(func_name):
co_argcount = code_obj.co_argcount
co_code = code_obj.co_code
co_consts = code_obj.co_consts
co_filename = code_obj.co_filename
co_flags = code_obj.co_flags
co_lnotab = code_obj.co_lnotab
co_name = func_name # 函數名在這裡設置
co_names = code_obj.co_names
co_nlocals = code_obj.co_nlocals
co_stacksize= code_obj.co_stacksize
co_varnames = code_obj.co_varnames
co_firstlineno = code_obj.co_firstlineno

mycode_obj = types.CodeType(co_argcount,
co_nlocals,
co_stacksize,
co_flags,
co_code,
co_consts,
co_names,
co_varnames,
co_filename,
co_name,
co_firstlineno,
co_lnotab)
x = types.FunctionType(mycode_obj, globals(), func_name, ())
return x

lista = ["funca","funcb","funcc"]
for l in lista:
x = make_func(l)
x()


上面的回答都是「運行時動態生成函數」。如果題主的那個函數名列表不是動態的,而是事先約定好的,只是偷個懶,那麼我建議直接生成相應的 def 為源代碼文件,省掉有點黑的 exec。


不建議運行時去 hack . 就醬紫.

提供另一個思路: 寫成配置文件格式, 然後利用 "反射" 來實現, 不知是否可行? 從沒遇到過這麼奇怪的問題呀~~逃


謝邀,python里動態構造函數可以使用閉包

lista = ["funca","funcb","funcc"]

def make_func(val):
def func(name):
print("hello %s from %s" % (name, val))
return func

funcs = map(make_func, lista)
map(lambda f: f("world!"), funcs)

這樣生成的函數名沒有導出到命名空間里,需要自己導出一下

另外如果有 print sys._getframe().f_code.co_name 結果必須是給定函數名這樣的需求的話,那就只能用eval、exec 這樣動態生成代碼的方法了


謝邀,前面Twisted Python已經提到了實現類的__call__方法。其實函數在python里也是對象的一種形式。寫一個類實現的簡單版本。

class FuncGen(object):
def __init__(self,name):
self.name = name
def __call__(self):
print "hello, i am %s" %self.name

lista = ["funca","funcb","funcc"]

dictf = {}
for a in lista:
dictf.update({a: FuncGen(a)})

for a in lista:
dictf[a]()


Lfuncs = ["funca","funcb","funcc"]

Sbody ="print (sys._getframe().f_code.co_name)"

Lfuncs_content=["def {0}():
{1}
".format(Sfunc,Sbody) for Sfunc in Lfuncs]

print("
".join(Lfuncs_content))


用反射的方法應該是正解,類似這樣定義一個類

class FunctionTemplate(object):
def __init__(self):
self.__dict__={}
def __getattr__(self,attr):
def p(*args):
print "Function name: %s, No. of args: %d"%(attr,len(args))
return
self.__dict__[attr]=p
return p

假設函數名列表是

fnames=["func1","func2","func3"]

生成一個實例,然後初始化一下

x=FunctionTemplate()
_=[getattr(x,i) for i in fnames]

這樣就可通過訪問x的對應屬性來訪問你想要的函數了,比如

x.func1(1,2)
Function name: func1, No. of args: 2


工業里不是沒有這種做法,而且很多時候anonymous function可以避免name clashing。

用一個簡單的Factory模式即可。

class _Functor(object):
"""
A functor is a named function with its own state.

:NOTE: you should use and only use FunctorFactory to create functor objects.
"""
def __init__(self, name):
self._name = name

def __call__(self, *args, **kwargs):
"""
:NOTE: to be implemented

:param args:
:param kwargs:
:return:
"""
pass

class FunctorFactory(object):
"""
Produces functor objects;

:NOTE: Inserts the functor objects in the global dictionary so that the name of the functors become available even
though they are not explicitly defined.
"""
def create(self, name):
globals()[name] = _Functor(name)

# examples
if __name__ == "__main__":
factory = FunctorFactory()
for name in ("funca", "funcb", "funcc"):
factory.create(name)
print funca()
print funcb()
print funcc()


#!/usr/bin/env python
# -*- coding: utf-8 -*-

def main():
items = ["a","b","c","d"]

for item in items:
generate_function_with(item)
globals()[item]()

def generate_function_with(func_name):
"""generate functions that prints its function name"""
print "Creating {func_name}".format(func_name=func_name)
def func_body():
print func_name
globals()[func_name] = func_body
func_body.__name__ = func_name

if __name__ == "__main__":
main()

# Ref: https://docs.python.org/2/library/functions.html#

實際上evalexec是沒必要用到的.


class GenFunc:
func_set = set([])
def __init__(self, list_func):
self.func_set = set(list_func)

def method_missing(self, attr, *args, **kwargs):
print attr

def __getattr__(self, attr):
if not (attr in self.func_set):
raise Exception("no such method")
def callable(*args, **kwargs):
return self.method_missing(attr, *args, **kwargs)
return callable

test = GenFunc(["funca", "funcb", "funcc"])
test.funca()
test.funcb()
test.funcc()
test.funcd()

這樣可以嗎?


推薦閱讀:

為什麼要學習Python?
如果每天堅持用12個小時學習一門編程語言,一年下來,編程能力會達到什麼程度?
做網路工程師還是做大數據,請求大佬指路?
哪些技術讓你有一種 「Orz, 還有這種操作」 ?
學 Python 發現學一門編程語言很難,有哪些學好編程的方法或技巧?

TAG:Python |