我是python的新手,想知道经验丰富的编码人员如何解决以下问题。
我有一个名为foo
的方法,带有多个参数。我需要在另一个方法bar
中调用该方法。有没有一种方法(避免使用类属性),可以避免将“ foo”方法的相同参数传递给“ bar”方法?
class Class:
def __init__(self, attr1):
self.attr1 = attr1
def foo(self, arg1, arg2, arg3):
return arg1*arg2*arg3
def bar(self, arg1,arg2, arg3, arg4):
return arg4*self.foo(arg1, arg2, arg3)
我也必须从其他类中调用bar
方法,我想知道是否有一种优雅的解决方案可以使用更少的参数。
答案 0 :(得分:1)
在不使用类属性/全局变量的情况下,我认为您只需要传递参数即可。但是,您可以编写
class Class:
def __init__(self, attr1):
self.attr1 = attr1
def foo(self, *args):
# Your logic here/if this is the usage use reduce
return args[0]*args[1]*args[2]
def bar(self, *args):
return args[3]*self.foo(*args[:3])
如您所见,此代码牺牲了代码的可读性。 PEP8(https://www.python.org/dev/peps/pep-0008/)进行澄清。
或者您也可以这样做:
class Class:
def __init__(self, attr1):
self.attr1 = attr1
def foo(self, arg1, arg2, arg3):
# Your logic here/if this is the usage use reduce
return arg1*arg2*arg3
def bar(self, *args):
return args[3]*self.foo(*args[:3])
*
运算符在此遍历给定的数组,并将其元素提供给被调用的函数。
答案 1 :(得分:0)
我在这里要做什么实际上取决于您的功能的实际目的。没有办法避免这样传递参数,但是有办法在适当的条件下使代码更短,更清晰。
我将首先确定foo
是否适用于任意输入。如果参数确实是不同的并且具有不同的目的,那么我将保持原样并接受参数列表将很长。另一方面,如果某些参数不是真正不同的并且可以视为序列,则可以使用splat表示法将其明确。关键不是修改输入而是重写foo
本身以处理任意输入:
from operator import mul
from functools import reduce
def foo(*args):
return reduce(mul, args)
当然,某些参数本身可能是不同的且很重要,在这种情况下,您可以混合使用:
def foo(arg1, arg2, *args):
return arg2 * (arg1 + reduce(mul, args))
现在,您可以决定如何处理bar
。结果将取决于您对foo
所做的操作以及bar
本身的总体目的。
如果bar
的唯一主要依存关系是foo
,则它可以直接接受foo
的参数。我强烈建议您将非foo
参数(在您的示例中为arg4
)移到参数列表的前面。即使您决定foo
需要多个独立的命名参数,您仍然可以执行以下操作:
def bar(arg4, *args, **kwargs):
return arg4 * foo(*args, **kwargs)
请记住要非常清楚地记录下来。确保在“所有其余参数都直接传递到foo
”这一行中有一条注释。
一个更复杂的情况可能是bar
要么委托许多复杂的函数,要么本身就拥有大量参数。在这种情况下,我会将foo
的参数列表放入位置和关键字参数的两个单独的变量中。这在matplotlib中很常见,在其中注释对象之类的东西需要具有文本属性,箭头属性,不同的变换等:
def bar(arg4, foo_args=None, foo_kwargs=None):
if foo_args is None:
foo_args = ()
if foo_kwargs is None:
foo_kwargs = {}
return arg4 * foo(*foo_args, **foo_kwargs)
我们必须做foo_kwargs=None
的原因是默认参数是持久且可访问的。如果要在函数外部修改该参数,则默认情况下将使用非空字典来调用foo
。将默认参数设置为空容器是一个新手常犯的错误,只是意识到一旦函数运行,它们就不会为空。我们使用None
之类的不变标记值来解决此问题,该值使我们知道何时从头开始创建一个新的空容器。请注意,foo_args=None
并非绝对必要,因为空元组将始终保持为空。我只是觉得如图所示会更加一致。
我已经用函数符号编写了所有示例,但是如果可以的话,这些思想可以完全转移到方法中。