當前位置:首頁 » 編程語言 » python3作用域

python3作用域

發布時間: 2022-04-13 03:40:46

python變數的作用域到底怎麼理解怎麼用呢謝謝!

你可以 在 B頁面 裡面直接 調用 一下 函數
運行一下 ,你可以發現應該和 剛才 執行A 頁面 報的是同樣的錯誤;

這是 因為 在B 頁面裡面 並沒有 s1List 這樣一個數組

在運行A頁面時,因為有了 from b import * ,python解釋器就可以找的getS1和getS2這樣的函數名;可以 在 import 之後 print dir() 來查看 當前作用域下可用的名字 ,可以看到 getS1 和getS2 都在其中

之所以 執行 A頁面錯誤,是A頁面調用 函數 getS1 時,在B頁面中 執行 函數時找不到 s1List這個數組,因為在A 頁面的那個 s1List 是不在 B頁面的作用范圍內的。

Ⅱ 深入探究Python中變數的拷貝和作用域問題

這篇文章主要介紹了Python中變數的拷貝和作用域問題,包括一些賦值、引用問題,以及相關函數在Python2和3版本之間的不同,需要的朋友可以參考下

python
中賦值語句總是建立對象的引用值,而不是復制對象。因此,python
變數更像是指針,而不是數據存儲區域,
這點和大多數
OO
語言類似吧,比如
C++、java

~
1、先來看個問題吧:
在Python中,令values=[0,1,2];values[1]=values,為何結果是[0,[...],2]?
?
1
2
3
4
>>>
values
=
[0,
1,
2]
>>>
values[1]
=
values
>>>
values
[0,
[...],
2]
我預想應當是
?
1
[0,
[0,
1,
2],
2]
但結果卻為何要賦值無限次?
可以說
Python
沒有賦值,只有引用。你這樣相當於創建了一個引用自身的結構,所以導致了無限循環。為了理解這個問題,有個基本概念需要搞清楚。
Python
沒有「變數」,我們平時所說的變數其實只是「標簽」,是引用。
執行
?
1
values
=
[0,
1,
2]
的時候,Python
做的事情是首先創建一個列表對象
[0,
1,
2],然後給它貼上名為
values
的標簽。如果隨後又執行
?
1
values
=
[3,
4,
5]
的話,Python
做的事情是創建另一個列表對象
[3,
4,
5],然後把剛才那張名為
values
的標簽從前面的
[0,
1,
2]
對象上撕下來,重新貼到
[3,
4,
5]
這個對象上。
至始至終,並沒有一個叫做
values
的列表對象容器存在,Python
也沒有把任何對象的值復制進
values
去。過程如圖所示:
執行
?
1
values[1]
=
values
的時候,Python
做的事情則是把
values
這個標簽所引用的列表對象的第二個元素指向
values
所引用的列表對象本身。執行完畢後,values
標簽還是指向原來那個對象,只不過那個對象的結構發生了變化,從之前的列表
[0,
1,
2]
變成了
[0,
?,
2],而這個
?
則是指向那個對象本身的一個引用。如圖所示:
要達到你所需要的效果,即得到
[0,
[0,
1,
2],
2]
這個對象,你不能直接將
values[1]
指向
values
引用的對象本身,而是需要吧
[0,
1,
2]
這個對象「復制」一遍,得到一個新對象,再將
values[1]
指向這個復制後的對象。Python
裡面復制對象的操作因對象類型而異,復制列表
values
的操作是
values[:]
#生成對象的拷貝或者是復制序列,不再是引用和共享變數,但此法只能頂層復制
所以你需要執行
?
1
values[1]
=
values[:]
Python
做的事情是,先
dereference
得到
values
所指向的對象
[0,
1,
2],然後執行
[0,
1,
2][:]
復制操作得到一個新的對象,內容也是
[0,
1,
2],然後將
values
所指向的列表對象的第二個元素指向這個復制二來的列表對象,最終
values
指向的對象是
[0,
[0,
1,
2],
2]。過程如圖所示:
往更深處說,values[:]
復制操作是所謂的「淺復制」(shallow
),當列表對象有嵌套的時候也會產生出乎意料的錯誤,比如
?
1
2
3
4
a
=
[0,
[1,
2],
3]
b
=
a[:]
a[0]
=
8
a[1][1]
=
9
問:此時
a

b
分別是多少?
正確答案是
a

[8,
[1,
9],
3],b

[0,
[1,
9],
3]。發現沒?b
的第二個元素也被改變了。想想是為什麼?不明白的話看下圖
正確的復制嵌套元素的方法是進行「深復制」(deep
),方法是
?
1
2
3
4
5
6
import


a
=
[0,
[1,
2],
3]
b
=
.deep(a)
a[0]
=
8
a[1][1]
=
9
2、引用
VS
拷貝:
(1)沒有限制條件的分片表達式(L[:])能夠復制序列,但此法只能淺層復制。
(2)字典

方法,D.()
能夠復制字典,但此法只能淺層復制
(3)有些內置函數,例如
list,能夠生成拷貝
list(L)
(4)
標准庫模塊能夠生成完整拷貝:deep
本質上是遞歸

(5)對於不可變對象和可變對象來說,淺復制都是復制的引用,只是因為復制不變對象和復制不變對象的引用是等效的(因為對象不可變,當改變時會新建對象重新賦值)。所以看起來淺復制只復制不可變對象(整數,實數,字元串等),對於可變對象,淺復制其實是創建了一個對於該對象的引用,也就是說只是給同一個對象貼上了另一個標簽而已。
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
L
=
[1,
2,
3]
D
=
{'a':1,
'b':2}
A
=
L[:]
B
=
D.()
print
"L,
D"
print
L,
D
print
"A,
B"
print
A,
B
print
"--------------------"
A[1]
=
'NI'
B['c']
=
'spam'
print
"L,
D"
print
L,
D
print
"A,
B"
print
A,
B

L,
D
[1,
2,
3]
{'a':
1,
'b':
2}
A,
B
[1,
2,
3]
{'a':
1,
'b':
2}
--------------------
L,
D
[1,
2,
3]
{'a':
1,
'b':
2}
A,
B
[1,
'NI',
3]
{'a':
1,
'c':
'spam',
'b':
2}
3、增強賦值以及共享引用:
x
=
x
+
y,x
出現兩次,必須執行兩次,性能不好,合並必須新建對象
x,然後復制兩個列表合並
屬於復制/拷貝
x
+=
y,x
只出現一次,也只會計算一次,性能好,不生成新對象,只在內存塊末尾增加元素。

x、y
為list時,
+=
會自動調用
extend
方法進行合並運算,in-place
change。
屬於共享引用
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
L
=
[1,
2]
M
=
L
L
=
L
+
[3,
4]
print
L,
M
print
"-------------------"
L
=
[1,
2]
M
=
L
L
+=
[3,
4]
print
L,
M

[1,
2,
3,
4]
[1,
2]
-------------------
[1,
2,
3,
4]
[1,
2,
3,
4]
4、python
從2.x
到3.x,語句變函數引發的變數作用域問題
先看段代碼:
?
1
2
3
4
5
6
7
8
9
def
test():
a
=
False
exec
("a
=
True")
print
("a
=
",
a)
test()

b
=
False
exec
("b
=
True")
print
("b
=
",
b)

python
2.x

3.x

你會發現他們的結果不一樣:
?
1
2
3
4
5
6
7
2.x:
a
=
True
b
=
True

3.x:
a
=
False
b
=
True
這是為什麼呢?
因為
3.x

exec
由語句變成函數了,而在函數中變數默認都是局部的,也就是說
你所見到的兩個
a,是兩個不同的變數,分別處於不同的命名空間中,而不會沖突。
具體參考
《learning
python》P331-P332
知道原因了,我們可以這么改改:
?
1
2
3
4
5
6
7
8
9
10
11
12
def
test():
a
=
False
ldict
=
locals()
exec("a=True",globals(),ldict)
a
=
ldict['a']
print(a)

test()

b
=
False
exec("b
=
True",
globals())
print("b
=
",
b)
這個問題在
stackoverflow
上已經有人問了,而且
python
官方也有人報了
bug。。。
具體鏈接在下面:
http://stackoverflow.com/questions/7668724/variables-declared-in-execed-code-dont-become-local-in-python-3-documentatio
http://bugs.python.org/issue4831
http://stackoverflow.com/questions/1463306/how-does-exec-work-with-locals

Ⅲ PYTHON 的變數作用域與內存分配

原理:python中任何變數都是對象,所以參數只支持引用傳遞方式。即通過名字綁定的機制,把實際參數的值和形式參數的名稱綁定在一起,形式參數和實際參數指向內存中的同一個存儲空間。
回答問題2:
每一次給變數賦值就是把這個名稱的值在一個新內存中存儲 你print (id (a)) 會發現每一次f(x),a的內存地址都是新的。所以你的問題二中L=[4,3] 與之前的L[]不是同一個名稱,所以append上a就是[4,3,3](簡明點就是L=[4,3]與L=[1,2]是兩不同名的玩意)
討論問題1:
在你的程序中a=1,a=2,a=5是int對象的三個實例,所以佔用的是三段不同的內存,自然在程序執行完收回內存的時候才會被清理;而L是通過列表的append方法進行變化時,print (f(1))
print (f(2)) print (f(5))是對對一個實例進行操作的,所以內存地址不變; 同理print (f(3,[4,3]))直接給L賦值時,由於 是一個新的列表實例了,內存位置自然變化。

產生以上的問題的根本原因就是python的精髓:萬物皆對象 (賦值的過程是對象的實例化)

看完自己的回答後:感覺真的很繞,不過我是盡力了,希望你能看懂,不明白的話,在追問里註明吧!

Ⅳ Python語言中作用域怎麼理解

命名空間 是從命名到對象的映射。當前命名空間主要是通過 Python 字典實現的,不過通常不關心具體的實現方式(除非出於性能考慮),以後也有可能會改變其實現方式。以下有一些命名空間的例子:內置命名(像 abs() 這樣的函數,以及內置異常名)集,模塊中的全局命名,函數調用中的局部命名。某種意義上講對象的屬性集也是一個命名空間。關於命名空間需要了解的一件很重要的事就是不同命名空間中的命名沒有任何聯系,例如兩個不同的模塊可能都會定義一個名為 maximize 的函數而不會發生混淆-用戶必須以模塊名為前綴來引用它們。
順便提一句,我稱 Python 中任何一個「.」之後的命名為 屬性 --例如,表達式 z.real 中的 real 是對象 z 的一個屬性。嚴格來講,從模塊中引用命名是引用屬性:表達式 modname.funcname 中,modname 是一個模塊對象,funcname 是它的一個屬性。因此,模塊的屬性和模塊中的全局命名有直接的映射關系:它們共享同一命名空間![1]
屬性可以是只讀過或寫的。後一種情況下,可以對屬性賦值。你可以這樣做: modname.the_answer = 42 。可寫的屬性也可以用 del 語句刪除。例如: del modname.the_answer 會從 modname 對象中刪除 the_answer 屬性。
不同的命名空間在不同的時刻創建,有不同的生存期。包含內置命名的命名空間在 Python 解釋器啟動時創建,會一直保留,不被刪除。模塊的全局命名空間在模塊定義被讀入時創建,通常,模塊命名空間也會一直保存到解釋器退出。由解釋器在最高層調用執行的語句,不管它是從腳本文件中讀入還是來自互動式輸入,都是 __main__ 模塊的一部分,所以它們也擁有自己的命名空間(內置命名也同樣被包含在一個模塊中,它被稱作 builtins )。
當調用函數時,就會為它創建一個局部命名空間,並且在函數返回或拋出一個並沒有在函數內部處理的異常時被刪除。(實際上,用遺忘來形容到底發生了什麼更為貼切。)當然,每個遞歸調用都有自己的局部命名空間。
作用域 就是一個 Python 程序可以直接訪問命名空間的正文區域。這里的直接訪問意思是一個對名稱的錯誤引用會嘗試在命名空間內查找。盡管作用域是靜態定義,在使用時他們都是動態的。每次執行時,至少有三個命名空間可以直接訪問的作用域嵌套在一起:

Ⅳ Python 的類中到底有沒有建立作用域

類在定義的時候是有作用域的,這個作用域內的變數只能在 class 塊內訪問,而不能在類的方法(函數)中訪問。

Ⅵ python中函數變數作用域和類變數作用域怎麼搞都錯,煩躁中

python中,變數的作用域要弄清楚。只有mole、class、def、lambda才會引入作用域,其他的代碼塊是不會引入作用域的。
1
圖一中,你在函數中聲明了d為全局變數,但這樣是無效的,程序運行結果,已經說明這一點。

global這個關鍵字,是用來「在函數中修改全局變數值」的聲明,而不是「在局部函數中定義一個全局變數」的聲明。這里要注意一下。
你可以再局部函數外面聲明變數d,再加上你原先的函數,就可以修改、訪問這個變數了。

2
在類中函數的變數,作用域只在函數中。圖二中,jian這個變數分別在yu(),yu1()兩個函數中,是處於不同的定義域中的,是不能相互訪問的。
所以,在各自函數中,只有先定義了jian變數,才能再使用。
如果想在yu1()中訪問yu()中的jian變數,就需要將jian變數變成全局變數,即在class中定義一個全局變數jian,這樣yu1(),yu()函數都可以訪問了

Ⅶ python中什麼叫局部作用域

1.這個怎麼看,我不能理解;2.全局變數局部變數有什麼區別嗎? 區別肯定有的,不然名字就沒必要區分了。全局的作用域比較大,一般在程序代碼中任何地方都可以調用,局部變數一般只在函數內部使用。3.函數,說白了就是實現不同功能的代碼段,比如MAX(a,b,c,...)函數,求最大值, MIN(a,b,c,...)函數,求最小值等、、、、還有很多。函數一般只知道使用方法(比如所需參數,返回值)和實現功能就行。

Ⅷ 學習python必備的基礎知識

學Python應先復從Python開發基礎部分入手,如學習Python語言介紹、環境安裝、 Python基本語法、基本數據類型、 二進制運算、流程式控制制、 字元制編碼、文件處理、 數據類型、用戶認證、函數、 三級菜單程序、購物車程序開發、 員工信息表開發、內置方法、 遞歸、迭代器、裝飾器、 模塊的跨目錄導入、 b加密百\re正則\logging日誌模塊、 常用標准庫學習、 軟體開發規范學習、 計算器程序、 ATM程序開發等,學完這些基本算是入度門了

Ⅸ python函數作用域的相關問題

global i表示聲明一個全局變數i,而函數A當中的i還是第2行定義的局部變數i。第7行輸出的是第2行定義的i,而第10行輸出的是全局變數i。

熱點內容
java單例實現 發布:2025-01-20 11:48:40 瀏覽:333
cad為什麼載入不了配置 發布:2025-01-20 11:37:45 瀏覽:16
伺服器記錄的手機ip 發布:2025-01-20 11:32:47 瀏覽:672
sparksql查詢 發布:2025-01-20 11:27:51 瀏覽:204
安卓奧特曼格鬥進化1怎麼發大招 發布:2025-01-20 11:17:03 瀏覽:605
試驗數據存儲 發布:2025-01-20 11:03:38 瀏覽:305
聯想如何將密碼退出 發布:2025-01-20 10:51:41 瀏覽:972
ftp傳輸文件連接失敗 發布:2025-01-20 10:49:39 瀏覽:723
xp共享訪問不了 發布:2025-01-20 10:40:05 瀏覽:946
基恩士plc編程手冊 發布:2025-01-20 10:11:30 瀏覽:910