在Python中创建子类与传递多个参数以指定函数的变体
我希望将多个类似的函数(~10个变体)与大量重复或类似的代码组合成更简洁、更面向对象的东西。接下来,我创建了一个中心类,在给定正确参数的情况下,该类的方法具有足够的灵活性,可以转换为我需要的大多数函数:在Python中创建子类与传递多个参数以指定函数的变体,python,python-3.x,function,oop,Python,Python 3.x,Function,Oop,我希望将多个类似的函数(~10个变体)与大量重复或类似的代码组合成更简洁、更面向对象的东西。接下来,我创建了一个中心类,在给定正确参数的情况下,该类的方法具有足够的灵活性,可以转换为我需要的大多数函数: class ThingDoer: def __init__(self, settings): # sets up some attrs ... def do_first_thing(self, args): identical_co
class ThingDoer:
def __init__(self, settings):
# sets up some attrs
...
def do_first_thing(self, args):
identical_code_1
similar_code_1(args)
def do_other_thing(self, otherargs):
similar_code_2(args)
identical_code_2
def generate_output(self):
identical_code
return some_output
当然,实际的事情相当长,有更多不同的参数集
和其他参数集
等等
然后,我在一个相对干净的函数中使用这个类来获得我的输出:
def do_things(name, settings, args, otherargs):
name = ThingDoer(settings)
name.do_first_thing(args)
name.do_second_thing(otherargs)
return name.generate_output()
我的问题是如何处理许多变体。我看到的两个明显的选项是:1)为每个变量指定了不同的选项字典,该字典传递给单个do\u things
函数,或者2)对于提前处理一些不同的arg
和otherarg
的每个变量,具有不同的ThingDoer
子类,并使用指定为参数的所需子类
备选案文1:
# Set up dictionaries of parameter settings
option_1 = {args: args1, otherargs: otherargs1 ...}
option_2 = {args: args2, otherargs: otherargs2 ...}
...
# And then call the single function passing appropriate dictionary
do_things(name, settings, **option)
备选案文2:
# Set up subclasses for each variant
class ThingDoer1(ThingDoer):
def __init__(self):
super().__init__()
self.do_first_thing(args1)
self.do_other_thing(otherargs1)
class ThingDoer2(ThingDoer):
def __init__(self):
super().__init__()
self.do_first_thing(args2)
self.do_other_thing(otherargs2)
...
# And then call the single function passing specific subclass to use (function will be modified slightly from above)
do_things(name, subclass, settings)
当然,还有其他选择
以下哪一种(或完全其他的)是处理这种情况的最佳方式?为什么呢?你要问自己的问题是:
如果功能是新的,那么我们将其添加到我们当时正在开发的任何设备模型的基类中,如果测试失败,并且旧设备需要新功能,我们将对其子类进行修改。一般来说,这取决于您希望向那些将使用您的API的用户公开的自定义级别。假设我们正在编写一些代码来发送HTTP请求(这只是一个示例,显然有很多库用于此) 如果调用者只关心易于配置的值,那么使用具有正常默认值的关键字参数可能是一种方法。也就是说,您的代码可能最终看起来像:
from typing import Dict
def do_request(url: str,
headers: Dict[str, str],
timeout: float = 10.0,
verify_ssl: bool = False,
raise_on_status_error: bool = False):
# ...
do_request('https://www.google.com')
如果您想公开更多定制的行为,您可能会受益于使用几个方法定义基类,这些方法可以被覆盖(或不被覆盖)以提供更具体的行为。比如说:
class HTTPClient(object):
def do_request(self, url: str, *args, **kwargs):
self.before_request(url, *args, **kwargs)
result = self.send(url, *args, **kwargs)
self.after_request(result)
return result
def send(self, url: str, *args, **kwargs):
# Same stuff as the above do_request function.
def before_request(self, *args, **kwargs):
# Subclasses can override this to do things before making a request.
pass
def after_request(self, response):
# Subclasses can override this to do things to the result of a request.
pass
client = HTTPClient()
response = client.do_request('https://www.google.com')
如果需要,子类可以在请求之前和请求之后实现,但默认情况下,其行为与上述等效函数相同
希望这有帮助!如果这与您的用例不相关,请提前表示歉意。您能给出一个更具体的示例,说明您正试图实现的目标吗?现在的问题是,我很难知道您试图避免什么陷阱,以及您希望通过OOP澄清什么。我最初使用的变量函数基本上修改/编译了一组指令,然后将其输入特定的外部建模软件。在我的整个工作流程中,外部软件会被多次调用,使用许多不同的指令配置。因此,这些变体的存在部分是为了以不同的方式配置指令,部分是为了在整个流程的不同阶段进行工作流控制。至于我所希望的重新编码选择,我总体上试图尽量减少重复(以前的代码有很多重复),同时保持合理的可读性和易于理解。以后以最少的代码重复灵活地添加更多变体也很好。速度不那么重要,因为外部软件离瓶颈很远。