简体   繁体   English

在 Python 中从另一个函数调用变量

[英]Calling a Variable from Another Function in Python

I have spent the past few hours reading around but I'm not really understanding what I am sure is a very basic concept: passing values (as variables) between different functions.在过去的几个小时里,我一直在阅读,但我并没有真正理解我所确定的一个非常基本的概念:在不同的函数之间传递值(作为变量)。

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

When I run the above code, BinSearch.objtobin code gives "objtobin() missing 1 required positional argument: 'self'" What should I do for this error?当我运行上面的代码时,BinSearch.objtobin 代码给出了“objtobin() missing 1 required positional argument: 'self'” 这个错误我该怎么办? Thanks for help!感谢帮助!

Firstly, thank you all for your help.首先,感谢大家的帮助。 But I do not understand how should I change this code但我不明白我应该如何更改此代码

I have started modifying your code so that it would run without errors, but there are a few other mistakes in there as well, and I have not tried to make sense of all your parameters.我已经开始修改您的代码,以便它可以无错误地运行,但其中还有一些其他错误,而且我还没有尝试弄清您的所有参数。

It would look something like this, but I will explain below.它看起来像这样,但我将在下面解释。

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

There is one important concept to be grasped here: self .这里需要掌握一个重要的概念: self

Let us consider this simple example function here, which shall always output a number one larger than last time.让我们在这里考虑这个简单的示例函数,它总是输出一个比上次大 1 的数字。

counter = 0
def our_function ():
    global counter
    counter = counter + 1
    return counter

print(our_function())

It is okay as it is, but it uses a global variable to keep track of its state.它是可以的,但是它使用一个全局变量来跟踪它的状态。 Imagine using it for two different purposes at the same time.想象一下同时将它用于两个不同的目的。 That would be chaos!那将是混乱! So instead, we package this inside a class.因此,我们将其打包在一个类中。

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

When we try to run this, we run into a problem.当我们尝试运行它时,我们遇到了一个问题。

NameError: name our_function is not defined NameError: name our_function未定义

This happens because it is now accessible only within that class.发生这种情况是因为它现在只能在该类中访问。 So we need to call it as所以我们需要把它称为

print(OurClass.our_function())

That makes it okay to have functions with the same name around - as long as they are in different classes - but it does not solve our chaos for using our_function multiple times at once.这使得拥有相同名称的函数是可以的——只要它们在不同的类中——但这并不能解决我们一次多次使用our_function的混乱。 What we want is basically to have two independent counter variables.我们想要的基本上是有两个独立的counter变量。 This is where instances come into play: Of course we could manually create a second function that uses a second global variable, but that gets out of hand quickly when you use it more and more.这就是实例发挥作用的地方:当然,我们可以手动创建使用第二个全局变量的第二个函数,但是当您越来越多地使用它时,它很快就会失控。

So let's move counter inside our class.因此,让我们在班级内部移动counter

class OurClass:
    counter = 0
    def our_function ():
        global counter
        counter = counter + 1
        return counter

You guessed it - now counter is no longer defined:你猜对了 - 现在counter不再定义:

NameError: name counter is not defined NameError:名称counter未定义

So let us pass the instance variable that we want to use into the function as a parameter.因此,让我们将要使用的实例变量作为参数传递给函数。 And then use that instance to get its 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))

And successfully, both print statements print 1 !并成功地,两个打印语句打印1

But that is a bit annoying because this the_instance is something that is not like the other arguments.但这有点烦人,因为这个the_instance与其他参数不同。 To make it distinct, python allows us to avoid the first parameter and instead provide it as the receiver.为了使它与众不同,python 允许我们避免使用第一个参数,而是将其作为接收器提供。 Both of these work:这两个工作:

print(myInstance.our_function())
print(OurClass.our_function(mySecondInstance))

Python uses a very strong convention for these parameters. Python 对这些参数使用了非常强的约定 Instead of the_instance , call it self .而不是the_instance ,称其为self See Why is self only a convention?请参阅为什么 self 只是一个约定? . .

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

Now we're almost done!现在我们快完成了! Just one thing left to understand: Where do the parameters of __init__() come from?只剩下一件事需要理解: __init__()的参数从何而来?
They are passed to __init__() from the line where we construct it.它们从我们构造它的行传递给__init__() So let me demonstrate by adding a starting value for our counter :所以让我通过为我们的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))

This prints 6 and 11 .这将打印611


But what do those comments mean with @staticmethod ?但是这些评论对@staticmethod意味着@staticmethod For that, see Difference between staticmethod and classmethod and Do we really need @staticmethod decorator in python to declare static method .为此,请参阅staticmethod 和 classmethod 之间的区别我们是否真的需要在 python 中使用 @staticmethod 装饰器来声明静态方法
In short: You can annotate any method in a class with either @staticmethod or @classmethod .简而言之:您可以使用@staticmethod@classmethod注释类中的任何方法。

  • @staticmethod means that it can be called like myInstance.foo() when OurClass.foo() does not take self as a parameter. @staticmethod意味着当OurClass.foo()不将self作为参数时,它可以像myInstance.foo()一样调用。 Without that decorator, you could only call it as OurClass.foo() but not as myInstance.foo() .如果没有那个装饰器,您只能将其称为OurClass.foo()而不能称为myInstance.foo()
  • @classmethod means that it can be called like myInstance.foo() and it does not get myInstance as the first parameter, but instead the class of myInstance , which is OurClass . @classmethod意味着它可以像myInstance.foo()一样被调用,并且它不会将myInstance作为第一个参数,而是将myInstance的类,即OurClass That allows you eg to define alternative constructors .这允许您例如定义替代构造函数 Also, a class method is not inherited when you subclass it, so it won't be mistakenly called.此外,类方法在子类化时不会被继承,因此不会被错误地调用。

The comments are pointing out that you could also use a @staticmethod and avoid creating an instance.评论指出您还可以使用@staticmethod并避免创建实例。 For that, you would have to not use any variables in the class itself - but you aren't using those for long anyways, so you could all pass them as parameter to the function.为此,您不必在类本身中使用任何变量 - 但无论如何您都不会长时间使用这些变量,因此您可以将它们作为参数传递给函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM