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

时间:2015-06-01 09:59:01

标签: python

我写过一个函数来计算两点之间的航向,只有当车辆报告它正在移动并且车辆在点之间移动了20厘米时才会计算。

该函数使用静态变量 - 或者至少它会起作用 - 来跟踪先前的位置和标题值。

以下是代码:

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)

我收到的错误是eastdist = pos[0]-previous_pos[0] NameError: global name 'previous_pos' is not defined。有人可以解释这个错误的原因吗?

4 个答案:

答案 0 :(得分:6)

执行此操作时:

def foo():
    pass

foo.name = 1

您没有创建全局名称name。相反,您要向foo函数添加属性!您可以使用以下方式访问它:

def foo():
    return foo.name

foo.name = 1

但这很奇怪。如果您需要全局名称,请执行以下操作:

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

name = 1

请记住,如果要从函数中修改全局名称,则必须将其声明为global。如果你没有这样做,你可以使用它但你不能分配它。

您对静态名称的混淆可能来自使用类。但请注意,在您的代码中withCan不是一个类,它是一个简单的函数!

答案 1 :(得分:2)

看起来你要做的就是写一堂课......

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

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

然后你可以初始化一个实例

withCan=WithCan(previous_pos)

并访问它

withCan.previous_pos=...

答案 2 :(得分:1)

可以使用函数属性在Python中执行静态变量,但您需要使用函数内部的全名来访问这些属性。

这是一个简短的演示。

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

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

<强>输出

3 8
10 16

然而,使用课程来做这类事情会更常见,如Tim的答案所示。

在Python中执行静态的另一种方法是为函数提供默认的可变参数,但很多人对此感到不舒服。但如果您有点好奇,请参阅“Least Astonishment” in Python: The Mutable Default Argument

答案 3 :(得分:0)

让我在函数中提供一种更简化的模拟静态变量的方式,这可能会使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 ...

基本上在第一次调用时,我们检测到其中一个“静态”变量(canflag)尚未存在,因此我们添加并初始化所有这些变量。之后,可以按照指示使用它们。

但是,正如其他人已经指出的那样,用数据成员编写一个类而不是这些“静态”函数变量要好得多。