python 数组赋值_pythonamp;numpy的赋值
有點編程基礎的童鞋看到這個標題可能會有點懵逼,這還是個問題嗎?不就是個等號(=)解決問題嘛!我也希望是如此簡單,因為上個星期被這個問題折磨到崩潰!
一般的python程序需要賦值時的確是通過等號(=)實現的,不管是變量還是數組,例如:
i=1
pi=3.1415926
x=numpy.arange(1,10)
也可以實現一些稍微復雜的操作:
ilon=90
jlat=40
corr = Corr_piont_and_plane( djf[:,jlat,ilon] , djf )
其中Corr_piont_and_plane是一個函數,有兩個參數,djf是冬季距平(500hPa位勢高度場),三維數組,函數實現的功能是選擇其中一個點(參數1,一維數組)和這個冬季距平(參數2)求時間相關,返回一個二維的相關系數矩陣,表征相關系數的空間分布。研究氣候的童鞋會經常用到這個函數,只不過參數1大概率是某個指數序列,參數2大概率是前冬海溫距平。
如果這個Corr_piont_and_plane函數是python寫的,以上的代碼是沒有問題的,返回的結果也是正確的。但如果玩了一點騷操作,Corr_piont_and_plane是由Fortran或者C寫的,編譯成python可調用的動態庫(如果對這個騷操作感興趣,可以點這里),那前面的代碼就是個大坑,我在這個大坑里轉了一個星期。我先直接給明確結論,這個代碼應該怎么寫,然后再解釋為什么。正確的代碼應該這么寫:
ilon=90
jlat=40
point=djf[:,jlat,ilon].copy()
corr = Corr_piont_and_plane( point,?djf )
這個就涉及到今天這個技術貼的主題,numpy的賦值,更加python或者numpy的說法是拷貝。等號(=)實現的是淺拷貝,而numpy.copy()實現的是深度拷貝。盡量用簡單的語言進行解釋:在一個python程序,新建一個numpy的array之后,內核會分配一組內存用來保存數據,但是怎么進行管理呢?內核認識這片內存的地址,但是這個地址保存著數據,數組的名字,比如djf,指向這個數組的首地址。打個比方,一個小區,有好幾棟樓,每棟樓好幾層,然后一梯兩戶或者一梯三戶,每個房子對著一戶人家,小區物業怎么管理呢,正常情況下是幾棟幾零幾(地址)住著誰家(數據),然后鄰居之間關系好,會擁有下一戶業主家的秘鑰(下一個數據的地址,至于下一戶是樓上樓下,還是同層別的住戶,甚至于別的樓同門牌號的業主,和內存優先機制有關,列優先還是行優先,不同語言不一樣,就是看小區物業自己咋規定)。回歸主題,當進行索引或者切片的時候,返回的其實是地址,不是數據,內核會訪問內存地址獲取數據。但是當切片出來一個數組,比如這個point,等于(=)相當于給這些數據打上標記,叫做引用,數據的內存地址沒有變化,但是用深度拷貝,相對于創建一個新數組保存新的數據,內存地址發生變化了。下圖是一個簡單示例,b是a的淺拷貝,所以b就是a,但是c是a的深度拷貝,如果c不是a。還用小區做例子進行解釋,就是有一棟樓的某一個扇面的下水道壞了,要進行處理。小區物業記下了這一個扇面屬于哪一棟樓的哪個哪個扇面,安排維修師傅更換下水道,這屬于淺拷貝,因為住戶還都住在這里,當維修人員發現樓房年久失修,更換下水道也不管事,只能異地拆遷的時候,屬于深度拷貝,因為住戶換地方住了。
再次回歸主題,當所有的代碼都是基于python編寫,直接把切片后的數組當做參數進行傳遞沒有任何問題,但是C-API接口進行傳遞時,就會存在問題,問題在于參數傳遞的是地址,到了Fortran編寫的subroutine里,訪問數組的首地址能夠正確識別,但是后面的數據就錯了,因為傳遞過來的地址Fortran不認識,可能原因這么幾點,還需要進一步確認:1、通過接口傳遞切片數組時,抹掉了切片信息,子程序默認還是內存的下一個地址去讀數據,更深層次的原因可能是python對變量進行了對象封裝,叫做PyObject,2、python和C默認行優先,Fortran默認列優先,數據尋址找錯了方向。基于這些原因,需要進行深度拷貝,重建參數數組的內存地址邏輯,再進行參數傳遞,才是正確的操作。
最后,對結論進行總結:python&numpy的賦值一般通過淺拷貝實現,即等于(=),也可以把切片數組作為參數進行傳遞,代碼簡潔,節省內存,當需要使用C-API接口傳遞參數,建議對參數使用深度拷貝賦值之后再進行參數傳遞。
總結
以上是生活随笔為你收集整理的python 数组赋值_pythonamp;numpy的赋值的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: oracle adg 备份,Oracle
- 下一篇: java calendar 毫秒_jav