首先,感谢大家的帮助。但我不明白我应该如何更改此代码
我已经开始修改您的代码,以便它可以正常运行,但其中也存在一些其他错误,并且我没有尝试理解您的所有参数。
它看起来像这样,但我将在下面解释。
# --- OP's attempt that fails ---
# BinSearch.objtobin(obj_function=max(objectivelist))
# -- -- -- -- -- -- -- -- -- -- --
# --- Using an instance ---
figure_this_out_yourself = 100
# this variable is a placeholder for any parameters I had to supply
myBinSearchInstance = BinSearch(
length = figure_this_out_yourself,
leng = [figure_this_out_yourself],
r = figure_this_out_yourself,
obj_function = figure_this_out_yourself,
middle = figure_this_out_yourself)
myBinSearchInstance.objtobin(obj_function = max(objectivelist))
这里需要掌握一个重要概念:self。
让我们在这里考虑这个简单的示例函数,它总是输出比上次大一的数字。
counter = 0
def our_function ():
global counter
counter = counter + 1
return counter
print(our_function())
它是可以的,但是它使用一个全局变量来跟踪它的状态。想象一下同时将它用于两个不同的目的。那将是混乱!
因此,我们将其封装在一个类中。
# unfinished apprach
counter = 0
class OurClass:
# This is called a static method
def our_function ():
global counter
counter = counter + 1
return counter
print(our_function())
当我们尝试运行它时,我们遇到了问题。
NameError: 名称 our_function 未定义
发生这种情况是因为它现在只能在该类中访问。所以我们需要把它称为
print(OurClass.our_function())
这使得周围有相同名称的函数是可以的——只要它们在不同的类中——但这并不能解决我们一次多次使用our_function 的混乱。我们想要的基本上是有两个独立的counter 变量。这就是实例发挥作用的地方:当然,我们可以手动创建使用第二个全局变量的第二个函数,但是当你越来越多地使用它时,它很快就会失控。
所以让我们将counter 移动到我们的类中。
class OurClass:
counter = 0
def our_function ():
global counter
counter = counter + 1
return counter
你猜对了 - 现在 counter 不再定义:
NameError: 名称 counter 未定义
所以让我们将要使用的实例变量作为参数传递给函数。然后使用该实例获取其计数器:
class OurClass:
counter = 0
def our_function (the_instance):
the_instance.counter = the_instance.counter + 1
return the_instance.counter
myInstance = OurClass()
mySecondInstance = OurClass()
print(OurClass.our_function(myInstance))
print(OurClass.our_function(mySecondInstance))
并且成功,两个打印语句都打印1!
但这有点烦人,因为这个the_instance 与其他参数不同。为了使其与众不同,python 允许我们避免使用第一个参数,而是将其作为接收者提供。这两种方法都有效:
print(myInstance.our_function())
print(OurClass.our_function(mySecondInstance))
Python 对这些参数使用非常严格的约定。代替the_instance,将其称为self。见Why is self only a convention?。
class OurClass:
counter = 0
def our_function (self):
self.counter = self.counter + 1
return self.counter
myInstance = OurClass()
mySecondInstance = OurClass()
print(myInstance.our_function())
print(mySecondInstance.our_function())
现在我们差不多完成了!只剩下一件事要理解:__init__()的参数从何而来?
它们从我们构造它的行传递给__init__()。所以让我通过为我们的counter 添加一个起始值来演示:
class OurClass:
counter = 0
def __init__ (self, starting_value):
self.counter = starting_value
def our_function (self):
self.counter = self.counter + 1
return self.counter
myInstance = OurClass(5)
mySecondInstance = OurClass(10)
print(myInstance.our_function())
print(OurClass.our_function(mySecondInstance))
这会打印出6 和11。
但是这些 cmets 对 @staticmethod 意味着什么?为此,请参阅 Difference between staticmethod and classmethod 和 Do we really need @staticmethod decorator in python to declare static method
。
简而言之:您可以使用@staticmethod 或@classmethod 来注释类中的任何方法。
-
@staticmethod 表示当OurClass.foo() 不带self 作为参数时,它可以像myInstance.foo() 一样调用。如果没有那个装饰器,您只能将其称为OurClass.foo(),而不能称为myInstance.foo()。
-
@classmethod 表示它可以像myInstance.foo() 一样被调用,它的第一个参数不是myInstance,而是myInstance 的类,即OurClass。这允许你例如到define alternative constructors。此外,类方法在子类化时不会被继承,因此不会被错误调用。
cmets 指出您也可以使用@staticmethod 并避免创建实例。为此,您不必在类本身中使用任何变量 - 但无论如何您都不会长时间使用这些变量,因此您都可以将它们作为参数传递给函数。