Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/300.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 当给出方法的选择时,用户应该在实例化时还是以后设置?_Python_Oop - Fatal编程技术网

Python 当给出方法的选择时,用户应该在实例化时还是以后设置?

Python 当给出方法的选择时,用户应该在实例化时还是以后设置?,python,oop,Python,Oop,我将跳转到这个例子,因为我认为它会变得更清楚。我是否更愿意这样做: class Substance(): def __init__(subst,name,density_method,**kwargs): self.name = name self.kwargs = kwargs self.density_method = density_method def density_method_1(self)

我将跳转到这个例子,因为我认为它会变得更清楚。我是否更愿意这样做:

class Substance():

    def __init__(subst,name,density_method,**kwargs):
         
        self.name   = name
        self.kwargs = kwargs
        self.density_method = density_method

    def density_method_1(self):
        #Something Here

    def density_method_2(self):
        #Something Else Here

class Air(Substance):
    Subst.__init__(self,name,gas_density_method=gas_density_method_1,**kwargs)

    # More stuff here

Air_1 = Air('Air_1',T=700,P=101325)
Air_2 = Air('Air_2',gas_density_method=gas_density_method_2,T=700,P=101325)
或者这个:

class Substance():

    def __init__(subst,name,**kwargs):
         
        self.name   = name
        self.kwargs = kwargs
        self.density_method = density_method_1 #Default is now here

    def density_method_1(self):
        #Something Here

    def density_method_2(self):
        #Something Else Here

class Air(Substance):
    Subst.__init__(self,name,**kwargs)

    # More stuff here

Air_1 = Air('Air_1',T=700,P=101325)
Air_2 = Air('Air_2',T=700,P=101325)
Air_2.density_method = density_method_2
这是一个基本的例子,但我每个subst(密度、粘度等)有10多个方法,每个方法可以有1个或多个不同的可能性。这里的答案是否纯粹基于设计,是否有任何良好的“实践”,以及其中一个在性能方面是否更好(对我来说很重要)?另外,如果密度方法2比方法1有更多的参数,会发生什么?(由于用户主动请求方法_2,因此他们有义务知道有额外的参数,因此我现在让它们通过**kwargs传递,以便稍后在相关方法中收集)
提前感谢,祝你度过愉快的一天

最好是注入依赖项。在这种情况下,您的第一个选择更好。它使您的代码更易于测试和模拟。尝试为这两种情况编写测试,您将了解原因。阅读更多关于Python依赖项注入和duck类型的信息。

注入依赖项总是最好的。在这种情况下,您的第一个选择更好。它使您的代码更易于测试和模拟。尝试为这两种情况编写测试,您将了解原因。阅读更多关于Python依赖注入和duck类型的信息。

关于性能。区别实际上可以归结为使用变量和使用字典。在这一点上,你说的是毫秒,这是微型优化,有非常特殊的用例

对于这个场景,实际上没有一个好的“最佳实践”,因此它将更多地取决于您将如何使用这些方法

至于其他具有不同变量的方法,这都要归结到实际调用这些方法的时间。在这段代码中,您只是将它们设置为一个变量,以标准化它们的调用方式,但实际上并没有调用它们。为了增加一致性,我将额外的变量设置为可选的。不过,这也取决于你想让他们做什么,以及你需要他们做什么

编辑: 我误解了你的一些问题,所以我的回答不完全可以理解。根据你的评论,我会这样看

首先,让我们对Substance类别进行一些更改:

class Substance():
    # Notice here I changed 'subst' to self. That was just a syntax error
    def __init__(self, name, density_method, **kwargs):
        self.name = name
        self.kwargs = kwargs
    
        # This is where we get into the substance of the method.
        # The density method is going to be what you call as a method later on.
        # For now we just have to initialize it.
        self.density_method = None

        # This will be the setter function to make it so we can use the 
        # different density methods
        # Since there is a call to it in the init function, we can always call it again later
        self.set_density_method(density_method)
现在我们必须创建setter函数,这样您就可以将不同的值传递到方法中,并让它更改您使用的密度方法。您可以使用getattr(对象,字符串)作为查找方法签名的相对安全的方法。这些文档是用于getattr()的

现在更改空气等级以反映对父级所做的更改:

class Air(Substance):
    # The method variable here is the default density class.
    # If you want there to be no default, remove everything to the right of =
    def __init__(self, name, method='density_method_1', **kwargs):
        Substance.__init__(self, name, density_method=method, **kwargs
因此,随着这些变化,实现也发生了变化,但变化很小

# Initialized with the default density method.
Air_1 = Air('Air_1',T=700,P=101325)
# Calling the designated density method.
Air_1.density_method()

# Again, initialized with the default method.
Air_2 = Air('Air_2',T=700,P=101325)
# Changing the default method after it's initialized.
Air_2.set_density_method('density_method_2')
Air_2.density_method()

# Calling it when setting the method in the class construction
Air_3 = Air('Air_3', method='density_method_3', T=700, P=101325)
Air_3.density_method()
这样做意味着您在编写代码时需要知道密度函数是什么,但是有一些方法可以使用字典来映射类似的内容,但这超出了这个问题的范围

最终代码:

class Substance():
    def __init__(self, name, density_method, **kwargs):
        self.name = name
        self.kwargs = kwargs
        self.density_method = None
        self.set_density_method(density_method)


    def set_density_method(self, new_method):
        self.density_method = getattr(self, new_method)

    def density_method_1(self):
        # Something Here
        print('density 1')

    def density_method_2(self):
        # Something Else Here
        print('density_2')

    def density_method_3(self):
        # Something Else Here
        print('density_3')


class Air(Substance):
    def __init__(self, name, method='density_method_1', **kwargs):
        Substance.__init__(self, name, density_method=method, **kwargs)


Air_1 = Air('Air_1',T=700,P=101325)
Air_1.density_method()
Air_2 = Air('Air_2',T=700,P=101325)
Air_2.set_density_method('density_method_2')
Air_2.density_method()

Air_3 = Air('Air_3', method='density_method_3', T=700, P=101325)
Air_3.density_method()

print('wait')

至于表现。区别实际上可以归结为使用变量和使用字典。在这一点上,你说的是毫秒,这是微型优化,有非常特殊的用例

对于这个场景,实际上没有一个好的“最佳实践”,因此它将更多地取决于您将如何使用这些方法

至于其他具有不同变量的方法,这都要归结到实际调用这些方法的时间。在这段代码中,您只是将它们设置为一个变量,以标准化它们的调用方式,但实际上并没有调用它们。为了增加一致性,我将额外的变量设置为可选的。不过,这也取决于你想让他们做什么,以及你需要他们做什么

编辑: 我误解了你的一些问题,所以我的回答不完全可以理解。根据你的评论,我会这样看

首先,让我们对Substance类别进行一些更改:

class Substance():
    # Notice here I changed 'subst' to self. That was just a syntax error
    def __init__(self, name, density_method, **kwargs):
        self.name = name
        self.kwargs = kwargs
    
        # This is where we get into the substance of the method.
        # The density method is going to be what you call as a method later on.
        # For now we just have to initialize it.
        self.density_method = None

        # This will be the setter function to make it so we can use the 
        # different density methods
        # Since there is a call to it in the init function, we can always call it again later
        self.set_density_method(density_method)
现在我们必须创建setter函数,这样您就可以将不同的值传递到方法中,并让它更改您使用的密度方法。您可以使用getattr(对象,字符串)作为查找方法签名的相对安全的方法。这些文档是用于getattr()的

现在更改空气等级以反映对父级所做的更改:

class Air(Substance):
    # The method variable here is the default density class.
    # If you want there to be no default, remove everything to the right of =
    def __init__(self, name, method='density_method_1', **kwargs):
        Substance.__init__(self, name, density_method=method, **kwargs
因此,随着这些变化,实现也发生了变化,但变化很小

# Initialized with the default density method.
Air_1 = Air('Air_1',T=700,P=101325)
# Calling the designated density method.
Air_1.density_method()

# Again, initialized with the default method.
Air_2 = Air('Air_2',T=700,P=101325)
# Changing the default method after it's initialized.
Air_2.set_density_method('density_method_2')
Air_2.density_method()

# Calling it when setting the method in the class construction
Air_3 = Air('Air_3', method='density_method_3', T=700, P=101325)
Air_3.density_method()
这样做意味着您在编写代码时需要知道密度函数是什么,但是有一些方法可以使用字典来映射类似的内容,但这超出了这个问题的范围

最终代码:

class Substance():
    def __init__(self, name, density_method, **kwargs):
        self.name = name
        self.kwargs = kwargs
        self.density_method = None
        self.set_density_method(density_method)


    def set_density_method(self, new_method):
        self.density_method = getattr(self, new_method)

    def density_method_1(self):
        # Something Here
        print('density 1')

    def density_method_2(self):
        # Something Else Here
        print('density_2')

    def density_method_3(self):
        # Something Else Here
        print('density_3')


class Air(Substance):
    def __init__(self, name, method='density_method_1', **kwargs):
        Substance.__init__(self, name, density_method=method, **kwargs)


Air_1 = Air('Air_1',T=700,P=101325)
Air_1.density_method()
Air_2 = Air('Air_2',T=700,P=101325)
Air_2.set_density_method('density_method_2')
Air_2.density_method()

Air_3 = Air('Air_3', method='density_method_3', T=700, P=101325)
Air_3.density_method()

print('wait')

谢谢你的回答,我会的。性能方面,有什么区别吗?谢谢你的回答,我会的。就性能而言,有什么区别吗?您所说的init定义,是针对父类实体的?我希望能够为不同的child使用不同的默认值(因为某些方法依赖于系数,并且并非所有方法中的所有物质都有系数)。而且,正如现在一样,第一个选项也可以像第二个一样设置,或者我遗漏了什么?至于参数:用户永远不会调用方法。稍后在另一个模块中进行调用的将是代码本身;这就是为什么我需要将方法设置为标准名称(density_method),并且它必须接受所有可能的参数(因此是kwargs)。我可以让额外的变量成为可选的,但它会膨胀一些不需要它们的方法,每次添加新方法时,所有的方法都需要更新这些额外的变量以保持一致性…@zepphit我错过了之前阅读您的问题,并因此回答了一些令人困惑的问题,这就是为什么我在打电话时不应该回答问题的原因。我对其进行了编辑,以提供更完整的解决方案。如果你有什么问题,请告诉我。你所说的init的定义,是针对父类实体的吗?我会的