简体   繁体   English

函数全局名称中的Python静态变量未定义

[英]Python static variable in function global name not defined

I have written a function to calculate the heading between two points only if a vehicle reports that it's moving and that the vehicle has moved 20cm between points. 我编写了一个仅在车辆报告正在行驶并且车辆在两点之间移动20cm时才计算两点之间的航向的函数。

The function uses static variables - or at least it would if it worked - to keep track of previous positions and heading values. 该函数使用静态变量-或至少可以使用它-跟踪先前的位置和航向值。

Here is the code: 这是代码:

def withCan(pos):

    eastdist = pos[0]-previous_pos[0]
    northdist = pos[1]-previous_pos[1]
    canflag = pos[2]

    if (canflag == 1 or canflag==2):

        if (previous_canflag == 1 and canflag == 2):
            previous_heading += 180.0
            previous_canflag = canflag
        elif (previous_canflag == 2 and canflag == 1):
            previous_heading += 180.0
            previous_canflag = canflag
        else:
            previous_canflag = canflag

    if ( (canflag == 1 or canflag == 2) and math.sqrt(northdist*northdist+eastdist*eastdist) > canstep ): 
        previous_heading = math.degrees(math.atan2(eastdist, northdist))
        previous_pos[0] = pos[0]
        previous_pos[1] = pos[1]

    return previous_heading

withCan.previous_pos = [0.0,0.0]
withCan.previous_heading = 0.0
withCan.previous_canflag = 0
withCan.canstep = 0.2

positions = backandforth([100,100]) #populates an array of form [x,y,canflag]

for p in positions:
    print withCan(p)

I am getting an error that says eastdist = pos[0]-previous_pos[0] NameError: global name 'previous_pos' is not defined . 我收到一条错误消息,说eastdist = pos[0]-previous_pos[0] NameError: global name 'previous_pos' is not defined Please could someone explain the cause of this error? 请有人可以解释此错误的原因吗?

When you do this: 执行此操作时:

def foo():
    pass

foo.name = 1

You are not creating a global name name . 您没有在创建全局名称name Instead you are adding a property to the foo function! 相反,您是向foo函数添加属性! You can access it with: 您可以通过以下方式访问它:

def foo():
    return foo.name

foo.name = 1

But that is quite weird. 但这很奇怪。 If you need a global name, just do it: 如果您需要一个全局名称,请执行以下操作:

def foo():
    global name
    name += 1
    return name

name = 1

Remember that if you want to modify the global name from the function, you have to declare it as global . 请记住,如果要从函数中修改全局名称,则必须将其声明为global If you fail to do this, you can use it but you cannot assign to it. 如果无法执行此操作,则可以使用它,但不能分配给它。

Your confusion with static names may come from using classes. 您对静态名称的困惑可能来自使用类。 But note that in your code withCan is not a class, it is a plain function! 但是请注意,在您的代码中withCan不是一个类,它是一个普通函数!

It looks like what you are trying to do is writing a class... 您似乎正在尝试写一门课...

class WithCan():
    def __init(self, previous_pos)__:
        self.previous_pos=previous_pos

    def withCan(self, pos):
        # your function as class method

Then you could initialize an instance 然后您可以初始化一个实例

withCan=WithCan(previous_pos)

and access it 并访问它

withCan.previous_pos=...

You can do static variables in Python using function attributes, but you need to use the full name inside the function to access those attributes. 可以使用函数属性在Python中执行静态变量,但是您需要使用函数内部的全名来访问这些属性。

Here's a short demo. 这是一个简短的演示。

def test(a):
    print a, a + test.b
    test.b += 1

test.b = 5
test(3)
test(10)

output 输出

3 8
10 16

However, it would be more usual to do this sort of thing using a class, as shown in Tim's answer. 但是,如蒂姆的回答所示,使用类来进行此类操作会更常见。

Another way to do statics in Python is to give your function default mutable arguments, but many people are uncomfortable with that. 在Python中执行静态操作的另一种方法是为您的函数提供默认的可变参数,但是许多人对此感到不舒服。 But if you're curious, please see “Least Astonishment” in Python: The Mutable Default Argument . 但是,如果您感到好奇,请参阅Python:Mutable Default Argument中的“最小惊讶”

Let me contribute a perhaps more streamlined way of emulating static variables in functions that could make the OP's example maybe easier to read: 让我为在函数中模拟静态变量的一种可能更简化的方式做出贡献,这可能会使OP的示例更易于阅读:

def with_can(pos):
  if not hasattr(with_can, "canflag"):
    # set up and initialise the static variables
    with_can.canflag = 0
    with_can.previous_pos = [0.0,0.0]
    with_can.previous_heading = 0.0
    with_can.canstep = 0.2

  # ... use them ...
  eastdist = pos[0]-with_can.previous_pos[0]
  # ... etc ...

Basically at the first invocation we detect that one of the "static" variables ( canflag ) is not yet there so we add and initialise all of them. 基本上,在第一次调用时,我们检测到“静态”变量( canflag )尚不存在,因此我们添加并初始化了所有变量。 After that they can be used as indicated. 之后,可以按照指示使用它们。

However, as others have pointed out already, it is much better to write a class with data members instead of these "static" function variables. 但是,正如其他人已经指出的那样,编写一个带有数据成员的类而不是这些“静态”函数变量要好得多。

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

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