简体   繁体   中英

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.

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 . 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 . Instead you are adding a property to the foo function! 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 . 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!

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.

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. But if you're curious, please see “Least Astonishment” in Python: The 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:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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