2013-04-09 45 views
6
def f(x): 
    x=x/5. 
    return x 
def g(x): 
    x/=5. 
    return x 

x_var = np.arange(5,dtype=np.double) 
f(x_var) 
print x_var 
g(x_var) 
print x_var 

Output: 
[ 0. 1. 2. 3. 4.] 
[ 0. 0.2 0.4 0.6 0.8] 

這種行爲有點奇怪,我一直認爲x/= 5。相當於x = x/5。 。但顯然,g(x)函數不會在/ =操作中創建新的引用。任何人都可以爲此提供解釋嗎?numpy自我分裂的意外行爲

回答

5

我一直以爲x/= 5。相當於X = X/5

是,除非類覆蓋__idiv__操作者,像numpy.ndarray一樣。 numpy.ndarray將覆蓋它以就地修改數組,這很好,因爲它避免了在不需要複製時創建數組的新副本。正如你所猜測的那樣,它也會覆蓋其他運營商的__i*__

+0

感謝您的解釋,我找不到可能導致我期待此行爲的文檔。 – bluecat 2013-04-09 16:44:07

+5

這不是一個numpy問題,它是一個通過引用對象傳遞的問題。所有'__i * __'的默認實現都是在可能的情況下進行操作,請閱讀[docs](http://docs.python.org/reference/datamodel.html#object.__iadd__)。將一個Python列表傳遞給一個函數def f(a):a * = 3;返回a',它會修改您調用它的原始對象,而不是簡單地返回修改後的副本。 – Jaime 2013-04-09 16:52:00

+1

謝謝,這是我正在尋找的文檔參考。所以如果可能的話,它應該在原地進行操作。如果__i * __不可用,它將默認爲正常的__ * __操作。 – bluecat 2013-04-09 17:03:15

3

Python的就地操作符允許操作修改等式左邊的對象,而不是創建一個新對象。你會看到list S和其他內置可變類型相同的行爲:

x = [] 
y = x 
x += [1] 
print y # prints [1] because x still refers to the same object as y 
x = x + [2] 
print x # prints [1, 2] for obvious reasons 
print y # prints [1] again because x has been rebound to a new list 
      # while y still refers to the original one 

所以這是預期的行爲。

當處理不可變類型時,當然會創建一個新對象,因爲現有的對象不能被修改。

0

我一直以爲x/= 5。相當於x = x/5。

它不是。當你這樣做x=x/5.,你其實引擎蓋下方進行獨立的操作:

temporary = x/5. 
x = temporary 

而當你使用/=運營商,你是明確要求Python來修改你的對象x到位,而不需要創建臨時對象。正如其他答案中提到的那樣,/運營商調用您的對象的__div__方法(如果有),而/=調用其方法__idiv__

如果您正在修改的對象很大,則就地修改非常有用:不需要創建一個很大的臨時對象。但是,如果你不小心,它會咬你。特別是,有一個功能修改其輸入參數而不發出警告通常不是一個好主意......