如何避免过多的参数传递?
我正在用Python开发一个中等规模的程序,这个程序分成了5个模块。程序通过主模块,比如main.py,使用OptionParser来接受命令行参数。这些选项后来会用来决定其他模块中的方法是怎么工作的,比如a.py和b.py。当我想让用户自定义程序的行为时,我发现我需要在a.py中的一个方法里使用这个用户定义的参数,而这个方法并不是直接由main.py调用的,而是由a.py中的另一个方法调用。
main.py:
import a
p = some_command_line_argument_value
a.meth1(p)
a.py:
meth1(p):
# some code
res = meth2(p)
# some more code w/ res
meth2(p):
# do something with p
这种过多的参数传递让我觉得很浪费,也不太对,但我想了很久也想不出什么好的设计模式来解决这个问题。虽然我有一些正式的计算机科学教育背景(在我本科时有计算机科学的辅修),但我真正开始欣赏良好的编码实践是自从我开始使用Python之后。请帮我成为一个更好的程序员!
6 个回答
2
如果“a”是一个真实的对象,而不仅仅是一组独立的辅助方法,你可以在“a”里面创建一个“p”的成员变量,并在你创建“a”对象的时候给它赋值。这样一来,你的主类在调用meth1和meth2的时候就不需要再传递“p”了,因为“a”已经被创建好了。
8
创建与你的程序相关的对象,并把每个对象对应的命令行选项存储在里面。比如:
import WidgetFrobnosticator
f = WidgetFrobnosticator()
f.allow_oncave_widgets = option_allow_concave_widgets
f.respect_weasel_pins = option_respect_weasel_pins
# Now the methods of WidgetFrobnosticator have access to your command-line parameters,
# in a way that's not dependent on the input format.
import PlatypusFactory
p = PlatypusFactory()
p.allow_parthenogenesis = option_allow_parthenogenesis
p.max_population = option_max_population
# The platypus factory knows about its own options, but not those of the WidgetFrobnosticator
# or vice versa. This makes each class easier to read and implement.
4
也许你应该把你的代码更好地组织成类和对象?在我写这个的时候,Jimmy 提供了一个基于类实例的答案,所以这里我给出一个纯粹基于类的答案。如果你只想要一种行为,这样做会很有用;但如果你有可能在某些时候想要不同的默认设置,那你就应该使用普通的面向对象编程,也就是在 Python 中传递类实例,并在实例中设置属性 p,而不是在类中设置。
class Aclass(object):
p = None
@classmethod
def init_p(cls, value):
p = value
@classmethod
def meth1(cls):
# some code
res = cls.meth2()
# some more code w/ res
@classmethod
def meth2(cls):
# do something with p
pass
from a import Aclass as ac
ac.init_p(some_command_line_argument_value)
ac.meth1()
ac.meth2()