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

   日期:2020-08-04     浏览:91    评论:0    
核心提示:闲来没事,分享一个工作上遇到的糗事。先把问题抛出来,假设现在需要定义一个函数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],l_{c

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

先把问题抛出来,假设现在需要定义一个函数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下来[汗]

 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服