我正在尝试在Python中运行模拟。为此,我需要定义一些参数,并从中推导出其他参数。使用这些我然后调用几个作用于这些参数的函数并返回一定的结果。目前我的代码看起来像这样
common(ai, bi, ..., hi):
# calculations
return ao, bo, ..., fo
func1(ai, bi, ..., xi):
ao, bo, ..., fo = common(ai, bi, ..., hi)
# calculations specific to func1
return y
func1(ai, bi, ..., xi):
ao, bo, ..., fo = common(ai, bi, ..., hi)
# calculations specific to func2
return z
ai = 0
bi = 1
...
xi = 2
print(func1(ai, bi, ..., xi))
print(func2(ai, bi, ..., xi))
我使用...
缩写参数列表等,并在# calculations
部分中执行计算。
我更愿意使用func1(di=2)
调用函数,并为所有其他函数设置默认值。然而,这意味着使用命名参数,在这种情况下,我必须指定两次默认值(在func1
和func2
中)。我不认为**kwargs
会在这里工作,因为这需要明确传递默认值。
我一直在尝试将字典传递给函数并在传递之前设置非标准参数。这使得函数调用更难以理解,所以我觉得应该有一种更简单的方法来做到这一点。
由于函数只包含相对较长的方程式,因此我不想在变量名称中添加字符,就像将它们存储在字典中并从那里调用它们时所需要的那样。这使得读取方程式变得更加困难。
我的问题是,是否有一种pythonic方法可以解决这个问题。
答案 0 :(得分:1)
你有两种方法具有相同类型的参数和返回值,唯一的区别是函数内部的进程,即它们共享相同的接口和功能。
您需要一种简单的方法来定义函数,而无需编写默认参数或多次传入字典。
使用装饰器或类继承会很好。
Decorator使您可以定义返回func1
或func2
等函数的工厂方法。该接口仅使用decorator中的默认参数定义一次,返回的函数在过程方法或核心方法上有所不同。
Class继承的工作方式类似,但通过方法继承,它更灵活,更通用。
答案 1 :(得分:0)
您可以创建一个类来保存其属性中的变量:
class SimClass(object):
def __init__(self, **kw):
self.ao = kw.get('aa', VA_DEFAULT)
self.bo = kw.get('bb', VB_DEFAULT)
# ...
self.zo = kw.get('zz', VZ_DEFAULT)
def common(self, ai, bi, ..., hi):
# calculations set self.ao, self.bo, ..., self.fo
return
def func1(self, ai, bi, ..., xi):
self.common(ai, bi, ..., hi)
# calculations specific to func1 using self.ao, self.bo, ..., self.fo
return y
def func1(self, ai, bi, ..., xi):
common(ai, bi, ..., hi)
# calculations specific to func2 using self.ao, self.bo, ..., self.fo
return z
ai = 0
bi = 1
...
xi = 2
sim = SimClass(bb='BB', cc='CC')
print(sim.func1(ai, bi, ..., xi))
print(sim.func2(ai, bi, ..., xi))
答案 2 :(得分:0)
编程中的函数参数不必像数学中那样完全使用。你可能有一个等式:
z = sqrt((x2 - x1)^2 + (y2 - y1)^2)
,
仅当变量具有短名称时才易于阅读。你想保留它是可以理解的。但编程语言可能不会那样工作,他们使用自己的语法和工具。
编程中重构的一个重要原则是减少函数中传递的参数的数量。最简单的方法是将所有传递的参数封装在一个对象中,并在函数之间仅传递该对象:
import math
class Line:
def __init__(self, x1, x2, y1, y2):
self.x1 = x1
self.x2 = x2
self.y1 = y1
self.y2 = y2
def getLineLength(line):
return math.sqrt((line.x2 - line.x1)**2 + (line.y2 - line.y1)**2)
line = Line(3, 5, -2, 7)
print(getLineLength(line))
当然,您必须使用对象名称,原始等式变得不那么可读。而Python代码并不一定非常像数学公式。但相反,您现在可以在代码的其他部分重新使用新类Line
。
如果函数足够复杂以查看它的作用,可以进一步重构:
def getLineLength(line):
dx = line.x2 - line.x1
dy = line.y2 - line.y1
return math.sqrt(dx**2 + dy**2)
此函数可能会在Line
类中移动:
class Line:
...
def getLength(self):
dx = self.x2 - self.x1
dy = self.y2 - self.y1
return math.sqrt(dx**2 + dy**2)
line = Line(3, 5, -2, 7)
print(line.getLength())
......甚至进一步重构:
import math
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __sub__(self, other):
return Point(other.x - self.x, other.y - self.y)
class Line:
def __init__(self, x1, x2, y1, y2):
self.start = Point(x1, y1)
self.end = Point(x2, y2)
def getLength(self):
d = self.start - self.end
return math.sqrt(d.x**2 + d.y**2)
line = Line(3, 5, -2, 7)
print(line.getLength())
新课程Point
可以在其他地方重复使用。
因此,可以保持代码清洁,简单和可重用。随着脚本的发展,可重用性变得非常重要。