我写过一个函数来计算两点之间的航向,只有当车辆报告它正在移动并且车辆在点之间移动了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
。有人可以解释这个错误的原因吗?
答案 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
)尚未存在,因此我们添加并初始化所有这些变量。之后,可以按照指示使用它们。
但是,正如其他人已经指出的那样,用数据成员编写一个类而不是这些“静态”函数变量要好得多。