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 funimport 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#
實際上eval和exec是沒必要用到的.
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 |