2013-03-19 91 views
2

我一直具有錯誤的Python:分配錯誤之前引用的局部變量

UnboundLocalError: local variable 'new_speedDx' referenced before assignment

試圖運行下面的函數:

def new_speedD(boid1): 
    bposx = boid1[0] 
    if bposx < WALL: 
     new_speedDx = WALL_FORCE 
    elif bposx > WIDTH - WALL: 
     new_speedDx = -WALL_FORCE 

    bposy = boid1[1] 
    if bposy < WALL: 
     new_speedDy = WALL_FORCE 
    elif bposx > WIDTH - WALL: 
     new_speedDy = -WALL_FORCE 

    return new_speedDx, new_speedDy 

在這個函數中,boid1是具有4個元素的向量( xpos,ypos,xvelocity,yvelocity),大寫的所有變量都是常量(數字)。 任何人有一個想法如何解決這個問題?我在互聯網上發現了很多可能的解決方案,但似乎沒有任何工作..

+2

請注意,'bposx = boid1 [0]'和'bposy = boid1 [1]'可以使用拆包更好地寫入:'bposx,bposy = boid1'。 – 2013-03-19 18:16:07

+0

另外兩個元素呢? – user2089012 2013-03-19 18:26:53

+0

如果它是一個更大的元組,在3.x中,您可以執行'bposx,bposy,* _ = boid1',它會將任何額外的值作爲列表分配給'_'(通常用於指示被丟棄的值),早期版本只需添加'_'s,因爲'boid1'中會有值 - 例如,有四個元素:'bposx,bposy,_,_ = boid1'。當然,你可以使用真實姓名,但如果你不使用它們,'_'s明確表示這是故意的。 – 2013-03-19 18:30:02

回答

4

如果這兩個條件都不成立,會發生什麼?

if bposx < WALL: 
    new_speedDx = WALL_FORCE 
elif bposx > WIDTH - WALL: 
    new_speedDx = -WALL_FORCE 

... new_speedDx從不分配,因此它的值是不確定的。

您可以通過指定new_speedDx應該是在這種情況下,有什麼緩解這樣的:

if bposx < WALL: 
    new_speedDx = WALL_FORCE 
elif bposx > WIDTH - WALL: 
    new_speedDx = -WALL_FORCE 
else: 
    new_speedDx = 0. 
5

它必須是可能的,bposx既不大於WALL小於WIDTH也更大 - WALL。

如:

bposx = 10 
WALL = 9 
WIDTH = 200 

if bposx < WALL: # 10 is greater than 9, does not define new_speedDx 
    new_speedDx = WALL_FORCE 
elif bposx > WIDTH - WALL: # 10 is less than (200 - 9), does not define new_speedDx 
    new_speedDx = -WALL_FORCE 

沒有看到你的程序的其餘部分就很難提出一個合理的後退值,但是你可能要添加的東西,如:

else: 
    new_speedDx = 0 
+0

增加了jsut,它的工作原理! – user2089012 2013-03-19 18:25:51

+1

太好了。你可能已經這樣做了,但我會注意到你可能想爲new_speedDy做同樣的事情,因爲它容易遭遇同樣的問題。 – uptownnickbrown 2013-03-19 18:34:30

1

說明

正如其他人指出的,你不是在處理WALL <= pos <= WIDTH - WALL的情況。

推薦變化

大概是京東方投資與當前的速度繼續,如果它不碰了壁。其他人的代碼將速度設置爲0,如果boid沒有撞牆。這種解決方案在使用現有速度方面是獨特的。我認爲這對你的情況很重要。

代碼

def new_speedD(boid1): 
    def new_speed(pos, velocity): 
     return WALL_FORCE if pos < WALL \ 
      else (-WALL_FORCE if pos > WIDTH - WALL \ 
      else velocity) 
    xpos, ypos, xvelocity, yvelocity = boid1 
    new_speedDx = new_speed(posx, xvelocity) 
    new_speedDy = new_speed(posy, yvelocity) 
    return new_speedDx, new_speedDy 

有些人認爲這個代碼是很難理解。這裏是一個簡要說明:

  1. 回報WALL_FORCE如果pos < WALL
  2. 否則,返回-WALL_FORCE如果pos> WIDTH - WALL
  3. 否則,返回速度

這裏是一個general question on the ternary operator。記住,認爲,「這是由一些pythonistas皺起了眉頭。」

如果不使用此代碼...

返回到原始和修復錯字在yvelocity情況:bposx > WIDTH - WALLyvelocity不依賴於xpos

+0

我真的沒有看到將if語句變爲三元操作符的好處 - 它只是使行太長而難以閱讀。 – 2013-03-19 18:31:14

+0

@Lattyware:好吧,首先,找出原始代碼中存在拼寫錯誤是微不足道的:'bposy = boid1 [1] if bposy WIDTH - WALL: new_speedDy = -WALL_FORCE'請參閱y-case中的bposx檢查?在使用單線三元運算符的x和y平行構造中顯而易見。 – hughdbrown 2013-03-19 18:34:21

+0

而這一切都傾倒在一條線上呢?我完全不同意 - 這些使得它變得難以理解。如果沒有別的,PEP-8建議行不應超過79個字符寬。 – 2013-03-19 18:37:57

相關問題