欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

一文理解Python命名機制

 更新時間:2021年10月12日 10:23:41   作者:AI伽月  
這篇文章主要介紹的是Python的命名機制,文章回先提出問題,然后根據(jù)問題逐步解析,感興趣的小伙伴可以參考一下,希望對你有所幫助

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

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、初探

正確的答案是:

A.__private()
B.public()


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

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

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

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

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

2、迷蹤

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

>>> print '/n'.join(dir(A))
_A__private
__init__
public
>>> print '/n'.join(dir(B))
_A__private
_B__private
__init__
public

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

3、探究

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

再講兩點題外話:

  • 一是因為軋壓會使標(biāo)識符變長,當(dāng)超過255的時候,Python會切斷,要注意因此引起的命名沖突。
  • 二是當(dāng)類名全部以下劃線命名的時候,Python就不再執(zhí)行軋壓。如:
>>> 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()      # 可以外部調(diào)用
____.__method()

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

4、真相

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

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

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__方法,所以調(diào)用的仍然是A.__init__,即執(zhí)行了self._A__private(),自然輸出“A.__private()”了。

下面的兩段代碼可以增加說服力,增進(jìn)理解:

>>> class C(A):
       def __init__(self):          # 重寫__init__,不再調(diào)用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()   # 調(diào)用一個沒有定義的函數(shù),Python會把它給我的 ^_^~
              self.public()
       def __private(self):
              print 'A.__private()'
       def public(self):
              print 'A.public()'
>>>a = A()
A.__private()
A.public()

到此這篇關(guān)于一文理解Python命名機制的文章就介紹到這了,更多相關(guān)理解Python命名機制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Pycharm配置Anaconda環(huán)境的詳細(xì)圖文教程

    Pycharm配置Anaconda環(huán)境的詳細(xì)圖文教程

    PyCharm是一款很好用很流行的python編輯器,Anaconda通過管理工具包、開發(fā)環(huán)境、Python版本,大大簡化了你的工作流程,下面這篇文章主要給大家介紹了關(guān)于Windows系統(tǒng)下Pycharm配置Anaconda環(huán)境的相關(guān)資料,需要的朋友可以參考下
    2023-02-02
  • python3.4爬蟲demo

    python3.4爬蟲demo

    今天小編就為大家分享一篇關(guān)于python3.4爬蟲demo,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • Python argparse中的action=store_true用法小結(jié)

    Python argparse中的action=store_true用法小結(jié)

    這篇文章主要介紹了Python argparse中的action=store_true用法小結(jié),本文結(jié)合示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-02-02
  • Python基于正則表達(dá)式實現(xiàn)計算器功能

    Python基于正則表達(dá)式實現(xiàn)計算器功能

    這篇文章主要介紹了Python基于正則表達(dá)式實現(xiàn)計算器功能,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-07-07
  • Python基礎(chǔ)之logging模塊知識總結(jié)

    Python基礎(chǔ)之logging模塊知識總結(jié)

    用Python寫代碼的時候,在想看的地方寫個print xx 就能在控制臺上顯示打印信息,這樣子就能知道它是什么了,但是當(dāng)我需要看大量的地方或者在一個文件中查看的時候,這時候print就不大方便了,所以Python引入了logging模塊來記錄我想要的信息,需要的朋友可以參考下
    2021-05-05
  • python Scrapy框架原理解析

    python Scrapy框架原理解析

    這篇文章主要介紹了python Scrapy框架原理的相關(guān)資料,幫助大家更好的理解和使用python爬蟲,感興趣的朋友可以了解下
    2021-01-01
  • 如何從Python 程序中運行 PowerShell 腳本

    如何從Python 程序中運行 PowerShell 腳本

    Windows PowerShell 由數(shù)十個內(nèi)置 cmdlet 組成,它們提供了豐富的功能集,本文將重點討論從 Python 代碼執(zhí)行 PowerShell 邏輯,感興趣的朋友跟隨小編一起看看吧
    2023-10-10
  • Python內(nèi)建模塊collections實現(xiàn)特殊容器數(shù)據(jù)類型

    Python內(nèi)建模塊collections實現(xiàn)特殊容器數(shù)據(jù)類型

    collections模塊是Python的內(nèi)建模塊之一,它實現(xiàn)了特殊的容器數(shù)據(jù)類型,提供了Python內(nèi)建的數(shù)據(jù)類型dict、list、set、和tuple的高效替代選擇
    2023-06-06
  • python使用numpy按一定格式讀取bin文件的實現(xiàn)

    python使用numpy按一定格式讀取bin文件的實現(xiàn)

    這篇文章主要介紹了python使用numpy按一定格式讀取bin文件的實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • 用Python selenium實現(xiàn)淘寶搶單機器人

    用Python selenium實現(xiàn)淘寶搶單機器人

    今天給大家?guī)淼氖顷P(guān)于Python實戰(zhàn)的相關(guān)知識,文章圍繞著用Python selenium實現(xiàn)淘寶搶單機器人展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06

最新評論