如何避免过多的参数传递?

3 投票
6 回答
2856 浏览
提问于 2025-04-15 15:08

我正在用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()

撰写回答