【日常】轻松一刻:python传参还能这么写

闲来没事,分享一个工作上遇到的糗事。

先把问题抛出来,假设现在需要定义一个函数myFunction(f,lst),其中参数f是一个函数,lst是一个列表,要求myFunction的运行结果是参数为的函数f依次接受lst中每一项为参数的运行结果,即myFunction(f,lst) = f(lst[0],lst[1], … ,lst[n]),假设lst中有n+1个元素。

其实这个问题很容易,只是如果没有接触过这个知识点就很难想到该怎么写。因为lst的长度是未知的,并不能用显式表达出f(lst[0],lst[1], … ,lst[n])

举个例子,如何编写myFunction函数使得下面的脚本能够正常运行?

def f(a,b=1,c=2,d=3):
print("a: {}".format(a))
print("b: {}".format(b))
print("c: {}".format(c))
print("d: {}".format(d))

def myFunction(f,lst):
""" Edit Start """
""" Edit End """
pass

lst1 = [1]
lst2 = [1,3]
lst3 = [1,3,5]
lst4 = [1,3,5,7]

myFunction(f,lst1)
myFunction(f,lst2)
myFunction(f,lst3)
myFunction(f,lst4)

笔者遇到这个问题时先去复习了一下动态参数的函数写法?

def f1(a,*args,**kwargs):
print(a)
print(args)
print(kwargs)

f1(1,2,3,4,b=1,c=2)

# 输出
"""
1
(2, 3, 4)
{'b': 1, 'c': 2}
"""

复习完之后发现好像没有什么用处,并不能解决这个问题,然后就写了一个又臭又长的myFunction函数?

def f(a,b=1,c=2,d=3):
print("a: {}".format(a))
print("b: {}".format(b))
print("c: {}".format(c))
print("d: {}".format(d))

def myFunction(f,lst):
""" Edit Start """
if len(lst)==1: f(lst[0])
elif len(lst)==2: f(lst[0],lst[1])
elif len(lst)==3: f(lst[0],lst[1],lst[2])
elif len(lst)==4: f(lst[0],lst[1],lst[2],lst[3])
else: assert False
""" Edit End """
pass

lst1 = [1]
lst2 = [1,3]
lst3 = [1,3,5]
lst4 = [1,3,5,7]

myFunction(f,lst1)
myFunction(f,lst2)
myFunction(f,lst3)
myFunction(f,lst4)

写完之后笔者想想不行呀,万一以后f的参数列表超过4个怎么办,要是参数列表有几百上千那不得改得累死,一顿操作后笔者想出了一个绝妙的写法?

def f(a,b=1,c=2,d=3):
print("a: {}".format(a))
print("b: {}".format(b))
print("c: {}".format(c))
print("d: {}".format(d))

def myFunction(f,lst):
""" Edit Start """
string = "f("
for i in range(len(lst)):
string += "lst[{}],".format(i)
string += ")"
eval(string)
""" Edit End """
pass

lst1 = [1]
lst2 = [1,3]
lst3 = [1,3,5]
lst4 = [1,3,5,7]

myFunction(f,lst1)
myFunction(f,lst2)
myFunction(f,lst3)
myFunction(f,lst4)

笔者想到可以用eval函数完美解决这个问题,eval函数可以将一段字符串当成代码直接运行,lst有多长不知道怎么办?直接把整个表达式用字符串表达出来就好了呗。

写完这个笔者还专门测试了一下发现这样的写法是不成立的?

eval("f(lst[0],lst[1],lst[2],lst3)")      # 可行
f(eval("lst[0],lst[1],lst[2],lst[3]")) # 不可行

然后就心满意足的push了代码。

写完之后笔者忽然想起在多进程multiprocess库的使用中似乎有相似的情形,创建进程时只要把函数和参数列表传入Process就可以直接运行函数了?

import multiprocessing
def do(n) :
#获取当前线程的名字
name = multiprocessing.current_process().name
print(name,'starting')
print("worker ",n)

if __name__ == '__main__' :
numList = []
for i in range(5):
p = multiprocessing.Process(target=do, args=(i,))
numList.append(p)
p.start()
p.join()
print("Process end.")

诶,那么multiprocess包里究竟是怎么写这个类似myFunction的函数的呢?是不是跟笔者写得一样妙?

出于好奇去查看了multiprocess的源码(python3.6/Lib/multiprocessing/process.py BaseProcess类节选?)

class BaseProcess(object):
'''
Process objects represent activity that is run in a separate process

The class is analogous to `threading.Thread`
'''
def _Popen(self):
raise NotImplementedError

def __init__(self, group=None, target=None, name=None, args=(), kwargs={},
*, daemon=None):
assert group is None, 'group argument must be None for now'
count = next(_process_counter)
self._identity = _current_process._identity + (count,)
self._config = _current_process._config.copy()
self._parent_pid = os.getpid()
self._popen = None
self._target = target
self._args = tuple(args)
self._kwargs = dict(kwargs)
self._name = name or type(self).__name__ + '-' + \
':'.join(str(i) for i in self._identity)
if daemon is not None:
self.daemon = daemon
_dangling.add(self)

def run(self):
'''
Method to be run in sub-process; can be overridden in sub-class
'''
if self._target:
self._target(*self._args, **self._kwargs)

看到run函数里的写法笔者猛得一惊,赶紧测试了一下?

def f(a,b=1,c=2,d=3):
print("a: {}".format(a))
print("b: {}".format(b))
print("c: {}".format(c))
print("d: {}".format(d))

def myFunction(f,lst):
""" Edit Start """
f(*lst)
""" Edit End """
pass

lst1 = [1]
lst2 = [1,3]
lst3 = [1,3,5]
lst4 = [1,3,5,7]

myFunction(f,lst1)
myFunction(f,lst2)
myFunction(f,lst3)
myFunction(f,lst4)

所以其实直接在lst前加个*号就可以了。

实在是丢人现眼的写法,趁还没有人看到赶紧pull下来[汗]

原创:https://www.panoramacn.com
源码网提供WordPress源码,帝国CMS源码discuz源码,微信小程序,小说源码,杰奇源码,thinkphp源码,ecshop模板源码,微擎模板源码,dede源码,织梦源码等。

专业搭建小说网站,小说程序,杰奇系列,微信小说系列,app系列小说

【日常】轻松一刻:python传参还能这么写

免责声明,若由于商用引起版权纠纷,一切责任均由使用者承担。

您必须遵守我们的协议,如果您下载了该资源行为将被视为对《免责声明》全部内容的认可-> 联系客服 投诉资源
www.panoramacn.com资源全部来自互联网收集,仅供用于学习和交流,请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除。 敬请谅解! 侵权删帖/违法举报/投稿等事物联系邮箱:2640602276@qq.com
未经允许不得转载:书荒源码源码网每日更新网站源码模板! » 【日常】轻松一刻:python传参还能这么写
关注我们小说电影免费看
关注我们,获取更多的全网素材资源,有趣有料!
120000+人已关注
分享到:
赞(0) 打赏

评论抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

您的打赏就是我分享的动力!

支付宝扫一扫打赏

微信扫一扫打赏