Python 使用*args、**kwargs管理客户端类中调用的各种对象的API(面向对象设计)

Python 使用*args、**kwargs管理客户端类中调用的各种对象的API(面向对象设计),python,class,oop,Python,Class,Oop,有一个Python类,比如Environment,它需要从其他类调用方法,比如pedden、Car、Plane。在实践中,我将这些类的一个实例传递到环境的某个方法中,该方法调用传入的对象的一个方法。行人、汽车、飞机共享一些类似功能的方法,例如get_speed,但get_speed应根据对象的不同使用不同的输入进行调用:例如Pederen.get_speedsoil_type和Plane.get_speedweather_type、air_resistance。环境中的某个方法调用。获取在某个点

有一个Python类,比如Environment,它需要从其他类调用方法,比如pedden、Car、Plane。在实践中,我将这些类的一个实例传递到环境的某个方法中,该方法调用传入的对象的一个方法。行人、汽车、飞机共享一些类似功能的方法,例如get_speed,但get_speed应根据对象的不同使用不同的输入进行调用:例如Pederen.get_speedsoil_type和Plane.get_speedweather_type、air_resistance。环境中的某个方法调用。获取在某个点传入的对象的速度。我的问题是,我希望来自环境的此调用适用于传入的任何对象,因此我需要处理传入对象的不同输入集。获取速度取决于传入对象的类型。这样做的有效/优雅方式是什么

我想做的是:

添加到get_speed方法中,对于所有这些对象,参数*args、**kwargs,忽略这些对象捕获的任何参数 在Environment类中,调用object_passed_In.get_speed和所有可能有用的参数soil_type、air_resistance、weather_type`,并放弃在*args、**kwargs中捕获的任何参数。 这个解决方案行吗?对我来说,它似乎不太干净。有没有更好的方法呢?

环境不应该关心细节。相反,environment方法的调用方应该负责传递必要的参数

class Environment:

    # Precondition: argument obj must have a callable 'get_speed' attribute
    def foo(self, obj, *args, **kwargs):
        ...
        speed = obj.get_speed(*args, **kwargs)
        ...


...

e = Evironment()
e.foo(ped, soil_type="dirt")
e.foo(plane, "cloudy", .032)
# etc
可能更好,Environment.foo甚至不需要知道正在调用get_speed;相反,它可以调用一个零参数函数,传递的函数负责使用正确的参数调用对象的get_speed方法。如果foo本身需要使用参数而不是要传递的参数来获得速度,那么这可能会更简单


谢谢你的帮助!你能给我解释一下为什么将所有参数捕获到*args、**kwargs中,并且,我假设,仅从*args**kwargs中检索任何参数在Peander、Plane中的方法中都是有用的,这比将所有参数显式命名到obj.get_speed(从Environment.foo调用)中要好?我对它有感觉,但我不能很好地解释为什么。第二,如果foo本身需要采用非要传递的参数来提高速度,那么为什么第二个解决方案会更简单呢?事实确实如此,这是一个封装问题。环境不一定需要知道get_speed所期望的参数的名称才能传递它们。在编写环境时,甚至可能存在不存在的Plane、Car等的子类,因此您无法知道它们可能采用的参数。如果foo采用一组固定的位置参数,那也没什么大不了的:foo的参数排在第一位,剩下的任何参数都会传递给您以提高速度。但这使得foo本身无法接受任意数量的参数:无法判断foo的参数从何处停止,也无法判断speed的参数从何处开始。
from functools import partial


class Environment:

    def foo(self, f, x):
        speed = f()


e = Environment()
e.foo(partial(ped.get_speed, soil_type="dirt"), 9)
e.foo(partial(plane.get_speed, "cloudy", .032), 6)
# etc