blu*_*e13 8 python coding-style
我从用户那里获得了一些参数并将函数传递给函数(每个函数在不同的类中),直到它最终到达一个执行某些处理的函数,然后解决方案从链中返回.在链上,函数变得越来越抽象,合并来自较低函数的多次运行的结果.
*args
和**kwargs
?我认为*args
并且*kwargs
可以用于函数不明确使用参数的每个函数.但是,需要定义实际参数,top_level
以便用户知道函数期望的内容.
我认为应该定义它们,top_level
因为这是最终用户可能希望查看文档的那个.
同样,我认为它们应该被定义,top_level
因为这是最终用户与之交互的那个.
这是一个简单的例子,用于演示参数的传递,其中我没有展示函数如何变得越来越抽象或者它们如何与不同的类交互,因为我认为这是不必要的细节.
def top_level(a=1, b=1, c=1, d=1, e=1):
""" Compute sum of five numbers.
:param a: int, a
:param b: int, b
:param c: int, c
:param d: int, d
:param e: int, e
:return: int, sum
"""
return mid_level(a, b, c, d, e)
def mid_level(*args, **kwargs):
return bottom_level(*args, **kwargs)
def bottom_level(a, b, c, d, e):
return a + b + c + d + e
print top_level(1, 2, 3)
8
Run Code Online (Sandbox Code Playgroud)
是否有传递这样的参数的Python约定?
我不打算回答你的问题,因为这就像回答"用螺丝刀拧紧螺母的最佳方法是什么?".即我不相信你要求指导的工具(*args
和**kwargs
)旨在解决你想要解决的问题.
相反,我会回答这个问题:"如何将一些数据与一组函数相关联?",答案显然是使用类.
欢迎使用面向对象的编程.我想你会喜欢它!
这是我的意思的一个非常基本的例子,但很难从你的例子中确切地知道你想要什么,因为它很简单,但基本原则是将你的数据封装在一个类中,然后使用类的方法对它进行操作.
.calculate()
下面的方法),您不知道顶层是否需要或底层.__init__
方法..reduce(x, y)
下面的方法所做的那样.例:
class ReductionCalculator:
def __init__(self, *args):
self.args = args
def calculate(self):
start = self.args[0]
for arg in self.args[1:]:
start = self.reduce(start, arg)
return start
class Summer(ReductionCalculator):
def reduce(self, x, y):
return x + y
class Multiplier(ReductionCalculator):
def reduce(self, x, y):
return x * y
summer = Summer(1, 2, 4)
print('sum: %d' % (summer.calculate(),))
multiplier = Multiplier(1, 2, 4)
print('sum: %d' % (multiplier.calculate(),))
Run Code Online (Sandbox Code Playgroud)
这不是最常见的模式,但我在具有嵌套命令级别的命令行程序中看到过这种模式:子命令、子子命令等。在该模型中,“上层”功能可能或多或少是调度程序,并且不具有有关给定路线内的子功能需要哪些参数的信息。该模型最纯粹的场景是当子命令是插件并且“上”层实际上没有关于子功能的信息时,除了插件应遵守的调用约定之外。
在这些情况下,我认为 pythonic 方法是将参数从较高级别的函数传递到较低级别的函数,并让工作级别决定哪些是有用的。可能的参数范围将在调用约定中定义。这是基于 DRY 的 Pythonic——不要重复自己。如果低级/工作函数定义了哪些输入是必需的或可选的,那么在更高级别上不重复此信息通常是有意义的。
这同样适用于任何控制反转流设计,而不仅仅是带有插件的 CLI 应用程序。在许多应用程序设计中我不会使用这种方法,但它在这里有效。
输入的含义必须在它可能出现的最高级别设置——作为较低级别的接口规范(约定,而不是编程)。否则,输入将没有语义意义。
如果一个输入可以被多个子功能使用,即控制流中存在链接或管道概念,则还需要在输入的最顶层定义输入的默认值。