2012-05-25 160 views
0
#it's python 3.2.3 
class point: 
    def __init__(self, x, y): 
     self.x = x 
     self.y = y 

    def __eq__(self, point): 
     return self.x == point.x and self.y == point.y 

    def __str__(self): 
     return 'point(%s, %s)' % (self.x, self.y) 

def someFunc(point): 
    if point.x > 14: point.x = 14 
    elif point.x < 0: point.x = 0 

    if point.y > 14: point.y = 14 
    elif point.y < 0: point.y = 0 

    return point 

somePoint = point(-1, -1) 
print('ONE: %s' % somePoint) 
if somePoint == someFunc(somePoint): 
    print('TWO: %s' % somePoint) 

變量的變化我看到有後第一打印() 但變量somePoint沒有somePoint變量賦值神奇地改變後如果聲明由於未知原因,

輸出這一計劃的應該是

ONE: point(-1, -1) 

但它是

ONE: point(-1, -1) 
TWO: point(0, 0) 

任何人可以解釋我爲什麼somePoint後

if somePoint == someFunc(somePoint): 

病情變化?

p.s.對不起,如果我的英語不好

+1

您正在更改'somePoint'中的** mutable **變量。你會期待什麼? – JBernardo

+1

而不是修改'someFunc'裏面的'somePoint',你應該創建一個新的點對象並返回它作爲比較。 –

+0

@JBernardo可變性(這裏)與對象有關,而不是變量..變量恰好指定了正在被突變的(相同)對象。 – 2012-05-25 16:32:42

回答

4

你改變point裏面的值函數someFunc當你在你的if語句調用它 ,所以我期望的值是(0,0)在 結束。原因是你正在傳遞一個引用(或「按對象共享傳遞」)給函數,並且稍後會反映對它的任何更改。這與傳值方法不同的是,本地副本是自動生成的。

爲避免更改傳入的原始point,您可以在someFunc內創建局部變量。

事情是這樣的:

def someFunc(a_point): # note new parameter name 

    loc_point = point(a_point.x, a_point.y) # new local point 

    if loc_point.x > 14: loc_point.x = 14 
    elif loc_point.x < 0: loc_point.x = 0 

    if loc_point.y > 14: loc_point.y = 14 
    elif loc_point.y < 0: loc_point.y = 0 

    return loc_point 

而且,它可能最好不要使用point是指你的類和您的參數。

+0

我應該'返回點(otherpoint.x,otherpoint.y)'? – foxneSs

+2

我認爲這裏的關鍵點是,在Python中,對象是通過引用*而不是按值傳遞的。在C++中,如果使用類似的簽名,我們會希望在調用函數時創建一個副本。但在Python中,沒有這樣的副本。 –

+0

GRR。沒有。停止以「通過參考」。這句話令人困惑和超載。語義更好,並且明確地稱爲「按對象共享呼叫」。 (結尾咆哮。) – 2012-05-25 16:34:08

2

調用someFunc()使用by-reference語義,以便它修改的對象恰好就是您調用它的對象。看起來你期待值函數的語義,函數獲取它傳遞的對象的副本。