【问题标题】:Calling a Variable from Another Function in Python在 Python 中从另一个函数调用变量
【发布时间】:2020-03-01 21:19:45
【问题描述】:

过去几个小时我一直在阅读,但我并没有真正理解我确信是一个非常基本的概念:在不同函数之间传递值(作为变量)。

class BinSearch:
    def __init__(self,length,leng,r,obj_function,middle):
        self.length = length
        self.leng = leng
        self.r = r
        self.obj_function = obj_function
        self.middle = middle
        self.objtobin(obj_function)

    def BinarySearch(length,leng,r):
        mid = np.arange(0,len(length),1)
        middle = min(mid) + (max(mid)-min(mid))//2
        L_size = []
        L = length[middle]
        L_size.append(L)
        return L

    def objtobin(self,obj_function):
        # length,leng,middle = BinSearch.BinarySearch()
        if (obj_function>=0.98):
            return BinSearch.BinarySearch(self.length,min(leng),self.middle-1)
        else:
            return BinSearch.BinarySearch(self.length,self.middle+1,max(leng))
BinSearch.objtobin(obj_function=max(objectivelist))

当我运行上面的代码时,BinSearch.objtobin 代码给出“objtobin() missing 1 required positional argument: 'self'” 这个错误我该怎么办? 感谢您的帮助!

【问题讨论】:

  • objtobin 是一个实例方法。您应该创建一个类的实例并使用它来调用该方法。
  • 我会先给你答案,稍后再寻找重复项以获得更好的解释:因为objtobin 需要self,所以你需要在实例上调用它,而不是在类上调用它。创建一个实例bs = BinSearch(length, leng, r, objfunction, middle),然后像bs.objtobin(...一样调用它
  • 令我惊讶的是,我没有找到一个完全重复的问题。希望this answer对你有帮助
  • 首先,感谢大家的帮助。但我不明白我应该如何更改此代码。你能“@lucidbrot”帮帮我吗?
  • 这会是类中@staticmethod 装饰器的用例,以便可以在外部调用该函数吗?据我所知,这个问题是objtobin 函数利用 self 变量进行返回,使其共同依赖于对象实例。

标签: python


【解决方案1】:

首先,感谢大家的帮助。但我不明白我应该如何更改此代码

我已经开始修改您的代码,以便它可以正常运行,但其中也存在一些其他错误,并且我没有尝试理解您的所有参数。

它看起来像这样,但我将在下面解释。

# --- 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))

这会打印出611


但是这些 cmets 对 @staticmethod 意味着什么?为此,请参阅 Difference between staticmethod and classmethodDo 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 并避免创建实例。为此,您不必在类本身中使用任何变量 - 但无论如何您都不会长时间使用这些变量,因此您都可以将它们作为参数传递给函数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-04-29
    • 2021-04-23
    • 1970-01-01
    • 2017-11-04
    • 1970-01-01
    • 1970-01-01
    • 2017-05-18
    相关资源
    最近更新 更多