Python,重写函数进行优化的最佳方法

Python,重写函数进行优化的最佳方法,python,optimization,overriding,overloading,Python,Optimization,Overriding,Overloading,我不知道如何最好地描述这个问题,但我只是想优化一下,因为我已经做了上亿次了。所以我试图尽可能地消除逻辑。因此,为了简单起见,让我们看下面一个简单的类: class Steps(): def __init__(self, descending, value): self.descending = descending self.value = value def step(self): if self.descending: se

我不知道如何最好地描述这个问题,但我只是想优化一下,因为我已经做了上亿次了。所以我试图尽可能地消除逻辑。因此,为了简单起见,让我们看下面一个简单的类:

class Steps():
   def __init__(self, descending, value):
      self.descending = descending
      self.value = value

   def step(self):
      if self.descending:
         self.value -= 1
      else:
         self.value += 1

   def other_funcs1(self):
      pass

   def other_funcs2(self):
      pass

a = Steps(descending=True, value=0)
b = Steps(descending=False, value=0)

a.step() # say this is done 100 million times
b.step() # say this is done 100 million times
由于我们在开始时已经知道它是否在下降/上升,因此在该步骤()中似乎没有必要使用逻辑“if self.descending”,特别是如果我们调用它数百万次

一种更好的方法是继承基类,如:

class Steps():
   def __init__(self, value):
      self.value = value

   def other_funcs1(self):
      pass

   def other_funcs2(self):
      pass

class StepsInc(Steps):
   def __init__(self, value):
      Steps.__init__(self, value)
   
   def step(self):
      self.value += 1

class StepsDec(Steps):
   def __init__(self, value):
      Steps.__init__(self, value)
   
   def step(self):
      self.value -= 1

a = StepsDec(value=0)
b = StepsInc(value=0)

a.step() # say this is done 100 million times
b.step() # say this is done 100 million times
由于我们不再做不必要的“如果”陈述,上述情况应该更为理想。但是如果我有多个函数,它们依赖于不同的参数,我应该怎么做呢?因此,除了“降序”之外,我还有其他可以具有不同功能的参数。我不想有太多的课,可能看起来很乱

我想到的一个解决方案是,我可以做类似的事情,但不确定这是否是pythonic:

class Steps():
       def __init__(self, descending, value):
          self.descending = descending
          self.value = value
          self.step = self.stepDec if self.descending else self.stepInc # can have multiple of this for different functions and parameters
          # more potential example
          #self.func = self.func1 if self.new_param else self.func2

       def stepInc(self):
          self.value += 1

       def stepDec(self):
          self.value -= 1

       def other_funcs1(self):
          pass

       def other_funcs2(self):
          pass

    
    
    a = Steps(descending=True, value=0)
    b = Steps(descending=False, value=0)
    
    a.step() # say this is done 100 million times
    b.step() # say this is done 100 million times
因此,这个类似乎比继承基类的另一个类更干净。我可以有很多其他的函数,它们可以基于不同的参数。所以有两个问题:1)这是pythonic吗?如果不是的话,还有什么更好的方法来实现它2)我如何覆盖默认函数,比如“repr”

对于第二个问题,假设打印(a)我想打印“我在下降”,打印(b)我想打印“我在上升”。我知道这没有多大意义,但我只是想知道我如何能克服这些。我完全可以用继承类的例子来实现这一点,其中每个类都有自己的“repr”函数。但是,有没有一种方法可以用我的最新例子来做到这一点呢?因为这看起来更干净,特别是根据不同的参数有更多的函数


希望这个问题是清楚的。谢谢你的帮助

嗯,有一种很好的方法可以解决你的问题。解决方案是通过将方法注入构造函数,将其动态添加到对象中。因为,解决方案很简单,所以我只提供以下代码:

#注意:在这种方法中,方法只存在于对象实例中
#该方法与类无关
#注意这一点
导入类型
def desc(自我):
self.value-=1
def公司(自我):
self.value+=1
类步骤():
定义初始值(自、函数、降序、值):
#将func添加为方法
#其中,方法名为step
self.step=types.MethodType(func,self)
#这里没有什么变化
自下降
自我价值=价值
a=步数(描述,真,0)
b=步数(inc,False,0)
a、 步骤();
打印(“a:{}的值”。格式(a.value));
b、 步骤();
打印(“b的值:{}”。格式(b.value));
输出为:

value of a: -1
value of b: 1
现在,您可能会惊讶地听到:我不会向任何人推荐它

让我解释一下原因:

  • 首先,如果您以这种方式创建了很多对象,那么有很多方法需要与这些对象关联。你可能会浪费很多内存
  • 对象实例与不属于类的方法绑定。这可能会使正在阅读您的代码的人感到困惑
  • 如果您遵循的是严格的oop编码风格,那么您只是将这些函数保留在公开的位置,或者可能只是包装在一个类中,但这并不是解决此问题的有效方法
  • 我知道,性能是您非常关心的问题,但我仍然建议您查看
    策略模式
    。多上几节课不会伤害到你,当你明白这几节课能给你多大的灵活性时。每个了解该模式的人都只需一眼就能理解您的代码


    现在,我说了很多。但是,我想提到的最后一件事是,如果您真的对
    性能
    非常感兴趣,您可以
    编写扩展
    ,或者
    切换到编译(更快)语言

    ,回答关于打印的第二个问题。在上一个示例中,您只需像设置self.step那样进行操作。self.step_str=“下降”如果self.descending,则为“上升”。那就把它传给你的印刷品好了,我怎么没想到呢。谢谢我猜原来的问题更复杂,而且似乎没有那么简单,因为还需要传递其他值。但是你肯定回答了我的问题,哈哈。这是蟒蛇吗?或者我可以做一个更好的命名约定来确保它是函数而不是变量吗?如果你根据其他值增加/减少一个,我想知道你是否可以在你的类中添加一个字段
    \u delta
    。该字段为1或-1,并且在其中一个参数更改时更新。在
    step()
    函数中,只需执行
    self.value+=self.\u delta
    。没有更多的
    if
    else
    了,但是现在你必须添加一个非常量值。是的,我想这个例子是可行的,但真正的问题实际上是按数量逐步解决的。这个数量每一步都在变化。是的,我知道很难用简单的版本来描述实际问题,但我肯定会考虑未来的解决方案。问题,这个例子不是你有一个战略模式,但你不会推荐吗?@user1179317它看起来像战略模式。但这不是正确的版本。特别是执行方法。通过编程到接口(或者,您也可以说,编程到超类型)来实现“策略模式”更好。但在这个例子中,这个方面确实缺失了。我希望,你现在清楚了。老实说,我不清楚有什么区别。但我会尽力去寻找它。谢谢though@user1179317再一次,你可以争论,如果它是“战略模式”还是“战略模式”,并且可以深入讨论,但在我看来,最好不要称之为“战略模式”。当我思考模式时,两个想法非常重要