http://blog.csdn.net/longshenlmj/article/details/13773977
函數參數傳遞本質上和變量整體復制一樣,只是兩個變量分別為形參a和實參b。那么,a=b后,a變了,b值是否跟着變呢?這取決於對象內容可變不可變
首先解釋一下,什么是Python對象的內容可變不可變?
python的變量是無類型的,如n=1 #變量n無類型(n相當於指針),其指向int數據類型的值,這個值是int類型。
所以,python中,strings, tuples元祖, 和numbers是不可更改的對象,而list,dict等則是可以修改的對象。
舉個列子,
不可變:如,a=5后,a=10,這里實際是新生成一個int值對象10,再讓a指向它,而5被丟棄,不是改變a的值,相當於新生成了a。
可變:如,la=[1,2,3,4]后,la[2]=5則是將list la的第二個元素值更改,本身la沒有動,只是其內部的一部分值被修改了。
那么,python函數的參數傳遞:
可變類型,則類似c++的引用,如list、dict。如fun(la),則是將la真正的傳過去,修改后fun外部的la也會受影響
而不可變類型,則類似c++的值傳遞,如int。如fun(a),傳遞的只是a的值,沒有影響a對象本身。比如在fun(a)內部修改a的值,只是修改另一個復制的對象,不會影響a本身。
同樣的道理,python變量復制也是一樣,a=b:
變量間復制,可變對象是引用,不可變是值copy(新生成值空間,不是變量對象空間)
樣例代碼如下:
a={1:'a',2:'b',3:'c'}
b=a
a[4]='d'
print a,b
#輸出:{1: 'a', 2: 'b', 3: 'c', 4: 'd'} {1: 'a', 2: 'b', 3: 'c', 4: 'd'}
a=10
b=a
a=6
print a,b
#輸出: 6 10
==============================================
http://www.cnblogs.com/loleina/p/5276918.html
def foo(arg):
print(id(arg))
arg = 2
print(id(arg))
print (arg)
a = 1
print(id(a))
foo(a)
print(a)
輸出:
31805800
31805800
31805776
2
1
https://foofish.net/python-function-args.html
變量與對象
Python 中一切皆為對象,數字是對象,列表是對象,函數也是對象,任何東西都是對象。而變量是對象的一個引用(又稱為名字或者標簽),對象的操作都是通過引用來完成的。例如,[]是一個空列表對象,變量 a 是該對象的一個引用
a = []
a.append(1)
在 Python 中,「變量」更准確叫法是「名字」,賦值操作 = 就是把一個名字綁定到一個對象上。就像給對象添加一個標簽。
a = 1

整數 1 賦值給變量 a 就相當於是在整數1上綁定了一個 a 標簽。
a = 2

整數 2 賦值給變量 a,相當於把原來整數 1 身上的 a 標簽撕掉,貼到整數 2 身上。
b = a

把變量 a 賦值給另外一個變量 b,相當於在對象 2 上貼了 a,b 兩個標簽,通過這兩個變量都可以對對象 2 進行操作。
變量本身沒有類型信息,類型信息存儲在對象中,這和C/C++中的變量有非常大的出入(C中的變量是一段內存區域)
函數參數
Python 函數中,參數的傳遞本質上是一種賦值操作,而賦值操作是一種名字到對象的綁定過程,清楚了賦值和參數傳遞的本質之后,現在再來分析前面兩段代碼。

def bar(args):
args.append(1)
b = []
print(b)# 輸出:[]
print(id(b)) # 輸出:4324106952
bar(b)
print(b) # 輸出:[1]
print(id(b)) # 輸出:4324106952

def bad_append(new_item, a_list=[]):
a_list.append(new_item)
return a_list
這段代碼是初學者最容易犯的錯誤,
用可變(mutable)對象作為參數的默認值。函數定義好之后,默認參數 a_list 就會指向(綁定)到一個空列表對象,每次調用函數時,都是對同一個對象進行 append 操作。
因此這樣寫就會有潛在的bug,同樣的調用方式返回了不一樣的結果。
>>> print bad_append('one')
['one']
>>> print bad_append('one')
['one', 'one']

而正確的方式是,把參數默認值指定為None
def good_append(new_item, a_list=None): if a_list is None: a_list = []
a_list.append(new_item)
return a_list

參考:http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#other-languages-have-variables
=========================
from ctypes import *
import os.path
import sys
def test(c):
print "test before "
print id(c)
c+=2
print "test after +"
print id(c)
return c
def printIt(t):
for i in range(len(t)):
print t[i]
if __name__=="__main__":
a=2
print "main before invoke test"
print id(a)
n=test(a)
print "main afterf invoke test"
print a
print id(a)
輸出:
>>>
main before invoke test
39601564
test before
39601564
test after +
39601540
main afterf invoke test
2
39601564
如果還不能理解,先看下面例子
>>> a=1
>>> b=1
>>> id(a)
40650152
>>> id(b)
40650152
>>> a=2
>>> id(a)
40650140
結論:python不允許程序員選擇采用傳值還是傳引用。Python參數傳遞采用的肯定是“傳對象引用”的方式。這種方式相當於傳值和傳引用的一種綜合。
如果函數收到的是一個可變對象(比如字典或者列表)的引用,就能修改對象的原始值--相當於通過“傳引用”來傳遞對象。如果函數收到的是一個不可變對象(比如數字、字符或者元組)的引用,就不能直接修改原始對象--相當於通過“傳值'來傳遞對象。
=================
http://www.cnblogs.com/Richardzhu/p/4723750.html
Python中的對象之間賦值時是按引用傳遞的,如果需要拷貝對象,需要使用標准庫中的copy模塊。
1、copy.copy 淺拷貝 只拷貝父對象,不會拷貝對象的內部的子對象。
2、copy.deepcopy 深拷貝 拷貝對象及其子對象>>> import copy
>>> a = [1,2,3,4,['a','b']] #原始對象
>>> b = a #賦值,傳對象的引用
>>> c = copy.copy(a) //一旦拷貝之后,c就是一個完全獨立的對象,對源對象a的操作並不會影響c。但對於淺拷貝不會拷貝a對象的內部的子對象,對子對象依然是引用,所以a[4].append('c')也會影響c
>>> d = copy.deepcopy(a) //深拷貝,父對象,子對象都是完全獨立的對象,不再受源對象的任何影響
>>> a.append(5) >>> a[4].append('c')
>>> print 'a=',a a= [1, 2, 3, 4, ['a', 'b', 'c'], 5] >>> print 'b=',b b= [1, 2, 3, 4, ['a', 'b', 'c'], 5] >>> print 'c=',c c= [1, 2, 3, 4, ['a', 'b', 'c']] >>> print 'd=',d d= [1, 2, 3, 4, ['a', 'b']]
=================
http://bbs.chinaunix.net/thread-943223-1-1.html
http://www.51testing.com/html/49/101349-815499.html
本來想用一個配置文件config.py作為全局文件,以方便不同文件共享這里面設置的變量,同時也可以在不同的module中設置這個文件的變量的。后來發現,不行。他並非每次都重新導入的。
大家都知道這樣使用全局變量是可以滴
a=1
def m(b):
global a
a=b
m(2)
print a
這樣a就變成2了.
但是現在我是這樣的,我的變量和函數定義在另外一個文件中(utils.py),我在主控腳本(main.py)中調用 比如:
main.py:
from utils import *
print a
print b
modify(5,6)
print a
print b
utils.py:
a=1
b=2
def modify(c,d):
global a
a=c
global b
b=d
這樣怎么就不行了呢?
可行的方法是: #main.py import utils print utils.a print utils.b utils.modify(5,6) print utils.a print utils.b #utils.py a=1 b=2 def modify(c,d): global a a=c global b b=d
應該盡量避免使用全局變量。不同的模塊都可以自由的訪問全局變量,可能會導致全局變量的不可預知性。對全局變量,如果程序員甲修改了_a的值,程序員乙同時也要使用_a,這時可能導致程序中的錯誤。這種錯誤是很難發現和更正的。
全局變量降低了函數或模塊之間的通用性,不同的函數或模塊都要依賴於全局變量。同樣,全局變量降低了代碼的可讀性,閱讀者可能並不知道調用的某個變量是全局變量。
但是某些時候,全局變量能夠解決局部變量所難以解決的問題。事物要一分為二。
python里面全局變量有兩種靈活的用法:
1 聲明法
在文件開頭聲明全局變量variable,
在具體函數中使用該變量時,需要事先聲明 global variable,否則系統將該變量視為局部變量。
CONSTANT = 0 (將全局變量大寫便於識別)
def modifyConstant() :
global CONSTANT
print CONSTANT
CONSTANT += 1
return
if __name__ == '__main__' :
modifyConstant()
print CONSTANT
2模塊法(推薦)
把全局變量定義在一個單獨的模塊中:
#gl.py
gl_1 = 'hello'
gl_2 = 'world'
在其它模塊中使用
#a.py
import gl
def hello_world()
print gl.gl_1, gl.gl_2
#b.py
import gl
def fun1()
gl.gl_1 = 'Hello'
gl.gl_2 = 'World'
第二種方法,適用於不同文件之間的變量共享,而且一定程度上避免了開頭所說的全局變量的弊端,推薦!
第三種方法:傳遞一個可變對象的引用完成共享
python中的深拷貝和淺拷貝和java里面的概念是一樣的,所謂淺拷貝就是對引用的拷貝,所謂深拷貝就是對對象的資源的拷貝。
首先,對賦值操作我們要有以下認識:
- 賦值是將一個對象的地址賦值給一個變量,讓變量指向該地址( 舊瓶裝舊酒 )。
- 修改不可變對象(
str、tuple)需要開辟新的空間 - 修改可變對象(
list等)不需要開辟新的空間
- 淺拷貝僅僅復制了容器中元素的地址
>>> a=['hello',[1,2,3]] >>> b=a[:] >>> [id(x) for x in a] [55792504, 6444104] >>> [id(x) for x in b] [55792504, 6444104] >>> a[0]='world' 修改不可變對象 >>> a[1].append(4) >>> print(a) ['world', [1, 2, 3, 4]] >>> print(b) ['hello', [1, 2, 3, 4]]
這里可以看出,未修改前,a和b中元素的地址都是相同的,不可變的hello,和可變的list地址都一樣,說明淺拷貝只是將容器內的元素的地址復制了一份。
這可以通過修改后,b中字符串沒改變,但是list元素隨着a相應改變得到驗證。
淺拷貝是在另一塊地址中創建一個新的變量或容器,但是容器內的元素的地址均是源對象的元素的地址的拷貝。也就是說新的容器中指向了舊的元素( 新瓶裝舊酒 )。
- 深拷貝,完全拷貝了一個副本,容器內部元素地址都不一樣
>>> from copy import deepcopy >>> a=['hello',[1,2,3]] >>> b=deepcopy(a) >>> [id(x) for x in a] [55792504, 55645000] >>> [id(x) for x in b] [55792504, 58338824] >>> a[0]='world' >>> a[1].append(4) >>> >>> print(a) ['world', [1, 2, 3, 4]] >>> print(b) ['hello', [1, 2, 3]]
這里可以看出,深拷貝后,a和b的地址以及a和b中的元素地址均不同,這是完全拷貝的一個副本,修改a后,發現b沒有發生任何改變,因為b是一個完全的副本,元素地址與a均不同,a修改不影響b。
深拷貝是在另一塊地址中創建一個新的變量或容器,同時容器內的元素的地址也是新開辟的,僅僅是值相同而已,是完全的副本。也就是說( 新瓶裝新酒 )。
