導航:首頁 > 編程語言 > python中的作用域

python中的作用域

發布時間:2022-04-30 09:47:35

python什麼是閉包 閉包的作用域

簡單說,閉包就是根據不同的配置信息得到不同的結果

再來看看專業的解釋:閉包(Closure)是詞法閉包(Lexical
Closure)的簡稱,是引用了自由變數的函數。這個被引用的自由變數將和這個函數一同存在,即使已經離開了創造它的環境也不例外。所以,有另一種說法
認為閉包是由函數和與其相關的引用環境組合而成的實體。

python實例

看概念總是讓人摸不著頭腦,看幾個python小例子就會了

def make_adder(addend):
def adder(augend):
return augend + addend
return adder

p = make_adder(23)
q = make_adder(44)

print p(100)
print q(100)

運行結果:
123
144

分析一下:

我們發現,make_adder是一個函數,包括一個參數addend,比較特殊的地方是這個函數裡面又定義了一個新函數,這個新函數裡面的一個變數正好是外部make_adder的參數.也就是說,外部傳遞過來的addend參數已經和adder函數綁定到一起了,形成了一個新函數,我們可以把addend看做新函數的一個配置信息,配置信息不同,函數的功能就不一樣了,也就是能得到定製之後的函數.

再看看運行結果,我們發現,雖然p和q都是make_adder生成的,但是因為配置參數不同,後面再執行相同參數的函數後得到了不同的結果.這就是閉包.

Ⅱ python 2.7 變數作用域的疑問

在函數中定義和修改全局變數,需要使用global關鍵字。但訪問全局變數(不修改它的值),可以省略global關鍵字。python這樣設計的意義在於,防止python程序員不小心修改了全局變數。使用global關鍵字後,程序員很清楚自己正在做什麼。


在例三中,b()函數並沒有修改全局變數u。u是一個對象的引用,有唯一的對象ID。在修改了變數的引用,導致變數ID改變是,才算是「修改了對象」。例如:

u={}
deffoo():
globalu
u=1
returnu
printfoo()

這是全局變數u被修改,因為它由一個字典變成了一個int對象,它的值發生了變化。


望採納,謝謝支持!

Ⅲ python for循環作用域問題

你append(alien),意味著,你的aliens 裡面裝了20個 alien,並且這20個alien都是內存地址是一樣的,也就是20個人共用一桶水,其中一個人把裡面的水換成了啤酒,大家喝的只能是啤酒.
解決辦法:
for aliens_number in range(20):
a=alien.()
aliens.append(a)

Ⅳ 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 中作用域與命名空間的問題

i=2這一句是定義了一個局部變數i,並賦值為2;這個時候全局作用域的i會被屏蔽,所以全局變數i是沒有被修改的所以結果是1;


訪問全局變數時可以直接訪問,但是修改全局作用域的時候一定要在賦值之前,進行如下聲明:

deff():

globali


i=2


因為python里賦值語句和聲明變數是一個體的,所以需要global來告訴解釋器i是全局變數,接下來的i=2才能被當作是賦值

------------------追答---------------------

同一個代碼塊(作用域)里, 同一個變數的作用域只能是同一種或者說同一個變數只能來自同一個作用域, 不能是一會是局部變數然後又變成全局變數;

i = i + 1

首先前面的'i='表明了i是一個局部變數(沒有global聲明, 創建局部變數), 然後後面的'i+1'里的i自然也是局部變數(同一個函數下同一個變數,i已經是局部變數了, 不能再當作全局變數去用), 那麼自然會報錯, i在使用前未聲明

i += 1

報錯就更明顯了, 沒有global聲明 那麼再修改變數i的時候, 自然是當作局部變數, 使用前未聲明

變數的查找順序遵循 LEGB 可以自己網路

關於作用域給你再寫個簡單的示例, 你對照著理解一下

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

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

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

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

Ⅶ 深入探究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變數的作用域到底怎麼理解怎麼用呢謝謝!

你可以 在 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 字典實現的,不過通常不關心具體的實現方式(除非出於性能考慮),以後也有可能會改變其實現方式。以下有一些命名空間的例子:內置命名(像 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中的作用域相關的資料

熱點內容
網頁伺服器崩潰怎麼回事 瀏覽:650
cnc編程前景怎麼樣 瀏覽:319
lniux命令詳解 瀏覽:493
linuxmysql查詢日誌 瀏覽:368
老捷達夥伴壓縮比 瀏覽:93
改後綴加密 瀏覽:432
郵局選址問題演算法 瀏覽:14
河北伺服器內存雲主機 瀏覽:12
在電腦上怎麼找到加密狗圖標 瀏覽:435
電腦的瀏覽器怎麼打開pdf文件怎麼打開 瀏覽:142
pdf卡片庫下載 瀏覽:11
單片機中二進製表示什麼 瀏覽:725
java網路編程推薦 瀏覽:794
施耐德開關編程 瀏覽:66
組織胚胎學pdf 瀏覽:844
linux查看發包 瀏覽:496
加密貨幣交易所暴利時代 瀏覽:824
歌詞滾動效果android 瀏覽:14
程序員一天的六場戰斗 瀏覽:797
自製壓縮泵的做法 瀏覽:622