激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務器之家 - 腳本之家 - Python - 一文理解Python命名機制

一文理解Python命名機制

2022-01-23 22:56AI伽月 Python

這篇文章主要介紹的是Python的命名機制,文章回先提出問題,然后根據問題逐步解析,感興趣的小伙伴可以參考一下,希望對你有所幫助

猜測下面這段程序的輸出:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class A(object):
       def __init__(self):
              self.__private()
              self.public()
       def __private(self):
              print 'A.__private()'
       def public(self):
              print 'A.public()'
class B(A):
       def __private(self):
              print 'B.__private()'
       def public(self):
              print 'B.public()'
b = B()

1、初探

正確的答案是:

?
1
2
A.__private()
B.public()

如果您已經猜對了,那么可以不看我這篇博文了。如果你沒有猜對或者心里有所疑問,那我的這篇博文正是為您所準備的。

一切由為什么會輸出“A.__private()”開始。但要講清楚為什么,我們就有必要了解一下Python的命名機制。

Python manual,變量名(標識符)是Python的一種原子元素。當變量名被綁定到一個對象的時候,變量名就指代這個對象,就像人類社會一樣,不是嗎?當變量名出現在代碼塊中,那它就是本地變量;當變量名出現在模塊中,它就是全局變量。模塊相信大家都有很好的理解,但代碼塊可能讓人費解些。在這里解釋一下:

代碼塊就是可作為可執行單元的一段Python程序文本;模塊、函數體和類定義都是代碼塊。不僅如此,每一個交互腳本命令也是一個代碼塊;一個腳本文件也是一個代碼塊;一個命令行腳本也是一個代碼塊。

接下來談談變量的可見性,我們引入一個范圍的概念。范圍就是變量名在代碼塊的可見性。如果一個代碼塊里定義本地變量,那范圍就包括這個代碼塊。如果變量定義在一個功能代碼塊里,那范圍就擴展到這個功能塊里的任一代碼塊,除非其中定義了同名的另一變量。但定義在類中的變量的范圍被限定在類代碼塊,而不會擴展到方法代碼塊中。

2、迷蹤

據上節的理論,我們可以把代碼分為三個代碼塊:類A的定義、類B的定義和變量b的定義。根據類定義,我們知道代碼給類A定義了三個成員變量(Python的函數也是對象,所以成員方法稱為成員變量也行得通。);類B定義了兩個成員變量。這可以通過以下代碼驗證:

?
1
2
3
4
5
6
7
8
9
>>> print '/n'.join(dir(A))
_A__private
__init__
public
>>> print '/n'.join(dir(B))
_A__private
_B__private
__init__
public

咦,為什么類A有個名為_A__privateAttribute 呢?而且__private消失了!這就要談談Python的私有變量軋壓了。

3、探究

Python的朋友都知道Python把以兩個或以上下劃線字符開頭且沒有以兩個或以上下劃線結尾的變量當作私有變量。私有變量會在代碼生成之前被轉換為長格式(變為公有)。轉換機制是這樣的:在變量前端插入類名,再在前端加入一個下劃線字符。這就是所謂的私有變量軋壓(Private name mangling)。如類A里的__private標識符將被轉換為_A__private,這就是上一節出現_A__private__private消失的原因了。

再講兩點題外話:

  • 一是因為軋壓會使標識符變長,當超過255的時候,Python會切斷,要注意因此引起的命名沖突。
  • 二是當類名全部以下劃線命名的時候,Python就不再執行軋壓。如:
?
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
>>> class ____(object):
       def __init__(self):
              self.__method()
       def __method(self):
              print '____.__method()'
>>> print '/n'.join(dir(____))
__class__
__delattr__
__dict__
__doc__
__getattribute__
__hash__
__init__
__method              # 沒被軋壓
__module__
__new__
__reduce__
__reduce_ex__
__repr__
__setattr__
__str__
__weakref__
>>> obj = ____()
____.__method()
>>> obj.__method()      # 可以外部調用
____.__method()

現在我們回過頭來看看為什么會輸出“A.__private() ”吧!

4、真相

相信現在聰明的讀者已經猜到答案了吧?如果你還沒有想到,我給你個提示:真相跟C語言里的宏預處理差不多。

因為類A定義了一個私有成員函數(變量),所以在代碼生成之前先執行私有變量軋壓(注意到上一節標紅的那行字沒有?)。軋壓之后,類A的代碼就變成這樣了:

?
1
2
3
4
5
6
7
8
class A(object):
       def __init__(self):
              self._A__private()          # 這行變了
              self.public()
       def _A__private(self):           # 這行也變了
              print 'A.__private()'
       def public(self):
              print 'A.public()'

是不是有點像C語言里的宏展開???

因為在類B定義的時候沒有覆蓋__init__方法,所以調用的仍然是A.__init__,即執行了self._A__private(),自然輸出“A.__private()”了。

下面的兩段代碼可以增加說服力,增進理解:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
>>> class C(A):
       def __init__(self):          # 重寫__init__,不再調用self._A__private
              self.__private()       # 這里綁定的是_C_private
              self.public()
       def __private(self):
              print 'C.__private()'
       def public(self):
              print 'C.public()'
>>> c = C()
C.__private()
C.public()
############################
>>> class A(object):
       def __init__(self):
              self._A__private()   # 調用一個沒有定義的函數,Python會把它給我的 ^_^~
              self.public()
       def __private(self):
              print 'A.__private()'
       def public(self):
              print 'A.public()'
>>>a = A()
A.__private()
A.public()

到此這篇關于一文理解Python命名機制的文章就介紹到這了,更多相關理解Python命名機制內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://zhuanlan.zhihu.com/p/65386589

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 成人免费网站在线观看视频 | ,欧美特黄特色三级视频在线观看 | 一本色道久久综合亚洲精品小说 | 久久网站热最新地址4 | 久久男 | 91精品国产91久久久 | 国产一区二区三区视频观看 | 国产精品无码久久久久 | 日韩不卡一区二区 | 亚洲精品一区二区三区免 | 欧美日韩在线看片 | 色天使中文字幕 | 日本一区二区不卡在线观看 | 国产精品视频二区不卡 | 免费人成在线观看网站 | 日韩视频一二三 | 毛片免费看的 | 中文字幕在线播放不卡 | 日韩av一二三区 | 特级西西444www大精品视频免费看 | 欧美一级黄色片在线观看 | 欧美成在人线a免费 | 日本黄色免费观看视频 | 亚洲人片在线观看 | 久久国产精品免费视频 | 国产精品亚洲综合一区二区三区 | 九九视屏 | 国内精品国产三级国产a久久 | www国产成人免费观看视频 | 黄色小视频免费在线观看 | 精品一区二区三区欧美 | 一级免费黄色免费片 | 蜜桃视频日韩 | 久久99精品久久久久久久久久久久 | 成人免费一区二区 | 久久国产精品二区 | 国产噜噜噜噜久久久久久久久 | 午夜视频久久 | 黄色的视频免费观看 | av在线收看 | 成人一区二区在线观看视频 |