0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Python 里最具代表性的符號(hào)居然如此強(qiáng)大

Linux愛好者 ? 來(lái)源:Python金牌大牛 ? 作者:Python金牌大牛 ? 2021-06-01 15:06 ? 次閱讀

要說 Python 里使用頻率最高的符號(hào),我想下劃線應(yīng)該排第一吧?

在不同場(chǎng)合下,下劃線有不同含義:比如_var表示內(nèi)部變量;__var表示私有屬性;__var__表示魔術(shù)方法;這些含義有的是程序員群體的約定,如_var;有的是 Python 解釋器規(guī)定的形式,如__var。

本文總結(jié) Python 語(yǔ)言編程中常用下劃線的地方,力圖一次搞懂_用法。目前常見的用法有五種:

_用于臨時(shí)變量

var_用于解決命名沖突問題

_var用于保護(hù)變量

__var用于私有變量

__var__用于魔術(shù)方法

下面我們具體看看這些下劃線應(yīng)用場(chǎng)景。

一、_用于臨時(shí)變量

單下劃線一般用于表示臨時(shí)變量,在 REPL、for 循環(huán)和元組拆包等場(chǎng)景中比較常見。

1.1 REPL單下劃線在 REPL 中關(guān)聯(lián)的是上一次計(jì)算的非 None 結(jié)果。

》》》 1+1

2

》》》 _

2

》》》 a=2+2

》》》 _

2

1+1,結(jié)果為 2,賦值給_;而賦值表達(dá)式a=2+2a 為 4,但整個(gè)表達(dá)式結(jié)果為None,故不會(huì)關(guān)聯(lián)到_。這有點(diǎn)類似日常大家使用的計(jì)算器中的ANS按鍵,直接保存了上次的計(jì)算結(jié)果。

1.2 for循環(huán)中的_for 循環(huán)中_作為臨時(shí)變量用。下劃線來(lái)指代沒什么意義的變量。例如在如下函數(shù)中,當(dāng)我們只關(guān)心函數(shù)執(zhí)行次數(shù),而不關(guān)心具體次序的情況下,可以使用_作為參數(shù)。

nums = 13

for _ in range(nums):

fun_oper()

1.3 元組拆包中的_第三個(gè)用法是元組拆包,賦值的時(shí)候可以用_來(lái)表示略過的內(nèi)容。如下代碼忽略北京市人口數(shù),只取得名字和區(qū)號(hào)。

》》》 city,_,code = (‘Beijing’,21536000,‘010’)

》》》 print(city,code)

Beijing 010

如果需要略過的內(nèi)容多于一個(gè)的話,可以使用*開頭的參數(shù),表示忽略多個(gè)內(nèi)容。如下代碼忽略面積和人口數(shù),只取得名字和區(qū)號(hào)

city,*_,code = (‘Beijing’,21536000,16410.54,‘010’)

1.4 國(guó)際化函數(shù)在一些國(guó)際化編程中,_常用來(lái)表示翻譯函數(shù)名。例如 gettext 包使用時(shí):

import gettext

zh = gettext.tranlation(‘dict’,‘locale’,languages=[‘zh_CN’])

zh.install()

_(‘hello world’)

依據(jù)設(shè)定的字典文件,其返回相應(yīng)的漢字“你好世界”。

1.5 大數(shù)字表示形式_也可用于數(shù)字的分割,這在數(shù)字比較長(zhǎng)的時(shí)候常用。

》》》 a = 9_999_999_999

》》》 a

9999999999

a 的值自動(dòng)忽略了下劃線。這樣用_分割數(shù)字,有利于便捷讀取比較大的數(shù)。

二、var_用于解決命名沖突問題

變量后面加一個(gè)下劃線。主要用于解決命名沖突問題,元編程中遇時(shí) Python 保留的關(guān)鍵字時(shí),需要臨時(shí)創(chuàng)建一個(gè)變量的副本時(shí),都可以使用這種機(jī)制。

def type_obj_class(name,class_):

pass

def tag(name,*content,class_):

pass

以上代碼中出現(xiàn)的class是 Python 的保留關(guān)鍵字,直接使用會(huì)報(bào)錯(cuò),使用下劃線后綴的方式解決了這個(gè)問題。

三、_var用于保護(hù)變量

前面一個(gè)下劃線,后面加上變量,這是僅供內(nèi)部使用的“保護(hù)變量”。比如函數(shù)、方法或者屬性。

這種保護(hù)不是強(qiáng)制規(guī)定,而是一種程序員的約定,解釋器不做訪問控制。一般來(lái)講這些屬性都作為實(shí)現(xiàn)細(xì)節(jié)而不需要調(diào)用者關(guān)心,隨時(shí)都可能改變,我們編程時(shí)雖然能訪問,但是不建議訪問。

這種屬性,只有在導(dǎo)入時(shí),才能發(fā)揮保護(hù)作用。而且必須是from XXX import *這種導(dǎo)入形式才能發(fā)揮保護(hù)作用。

使用from XXX import *是一種通配導(dǎo)入(wildcard import),這是 Python 社區(qū)不推薦的方式,因?yàn)槟愀靖悴磺迥愕降讓?dǎo)入了什么屬性、方法,很可能搞亂你自己的命名空間。PEP8推薦的導(dǎo)入方式是from XXX import aVar , b_func , c_func這種形式。

比如在下例汽車庫(kù)函數(shù) tools.py 里定義的“保護(hù)屬性”:發(fā)動(dòng)機(jī)型號(hào)和輪胎型號(hào),這屬于實(shí)現(xiàn)細(xì)節(jié),沒必要暴露給用戶。當(dāng)我們使用 from tools import * 語(yǔ)句調(diào)用時(shí),其實(shí)際并沒有導(dǎo)入所有_開頭的屬性,只導(dǎo)入了普通 drive 方法。

_moto_type = ‘L15b2’

_wheel_type = ‘michelin’

def drive():

_start_engine()

_drive_wheel()

def _start_engine():

print(‘start engine %s’%_moto_type)

def _drive_wheel():

print(‘drive wheel %s’%_wheel_type)

查看命令空間print(vars())可見,只有 drive 函數(shù)被導(dǎo)入進(jìn)來(lái),其他下劃線開頭的“私有屬性”都沒有導(dǎo)入進(jìn)來(lái)。

{‘__name__’: ‘__main__’, ‘__doc__’: None, ‘__package__’: None, ‘__loader__’: 《_frozen_importlib_external.SourceFileLoader object at 0x005CF868》, ‘__spec__’: None, ‘__annotations__’:{}, ‘__builtins__’: 《module ‘builtins’ (built-in)》, ‘__file__’: ‘。\xiahuaxian.py’, ‘__cached__’: None, ‘walk’: 《function walk at 0x01DA8C40》, ‘root’: ‘。\__pycache__’, ‘_’: [21536000, 16410.54], ‘dirs’: [‘tools.cpython-38.pyc’], ‘city’: ‘Beijing’, ‘code’: ‘010’, ‘drive’: 《function drive at 0x01DBC4A8》}

3.1 突破保護(hù)屬性之所以說是“保護(hù)”并不是“私有”,是因?yàn)?Python 沒有提供解釋器機(jī)制來(lái)控制訪問權(quán)限。我們依然可以訪問這些屬性:

import tools

tools._moto_type = ‘EA211’

tools.drive()

以上代碼,以越過“保護(hù)屬性”。此外,還有兩種方法能突破這個(gè)限制,一種是將“私有屬性”添加到 tool.py 文件的 __all__ 列表里,使from tools import *也導(dǎo)入這些本該隱藏的屬性。

__all__ = [‘drive’,‘_moto_type’,‘_wheel_type’]

另一種是導(dǎo)入時(shí)指定“受保護(hù)屬性”名。

from tools import drive,_start_engine

_start_engine()

甚至是,使用import tools也可以輕易突破保護(hù)限制。所以可見,“保護(hù)屬性”是一種簡(jiǎn)單的隱藏機(jī)制,只有在from tools import *時(shí),由解釋器提供簡(jiǎn)單的保護(hù),但是可以輕易突破。這種保護(hù)更多地依賴程序員的共識(shí):不訪問、修改“保護(hù)屬性”。除此之外,有沒有更安全的保護(hù)機(jī)制呢?有,就是下一部分討論的私有變量。

四、__var用于私有變量

私有屬性解決的之前的保護(hù)屬性保護(hù)力度不夠的問題。變量前面加上兩個(gè)下劃線,類里面作為屬性名和方法都可以。兩個(gè)下劃線屬性由 Python 的改寫機(jī)制來(lái)實(shí)現(xiàn)對(duì)這個(gè)屬性的保護(hù)。

看下面汽車?yán)又校?a target="_blank">品牌為普通屬性,發(fā)動(dòng)機(jī)為“保護(hù)屬性”,車輪品牌為“私有屬性”。

class Car:

def __init__(self):

self.brand = ‘Honda’

self._moto_type = ‘L15B2’

self.__wheel_type = ‘michelin’

def drive(self):

print(‘Start the engine %s,drive the wheel %s,I get a running %s car’%

(self._moto_type,

self.__wheel_type,

self.brand))

我們用var(car1)查看下具體屬性值,

[‘_Car__wheel_type’, ‘__class__’, ‘__delattr__’, ‘__dict__’, ‘__dir__’, ‘__doc__’, ‘__eq__’, ‘__format__’, ‘__ge__’, ‘__getattribute__’, ‘__gt__’, ‘__hash__’, ‘__init__’, ‘__init_subclass__’, ‘__le__’, ‘__lt__’, ‘__module__’, ‘__ne__’, ‘__new__’, ‘__reduce__’, ‘__reduce_ex__’, ‘__repr__’, ‘__setattr__’, ‘__sizeof__’, ‘__str__’, ‘__subclasshook__’, ‘__weakref__’, ‘_moto_type’, ‘brand’, ‘drive’]

可見,實(shí)例化 car1 中,普通屬性 self.brand 和保護(hù)屬性 self._moto_type 都得以保存,兩個(gè)下劃線的私有屬性 __wheel_type 沒有了。取而代之的是_Car_wheel_type這個(gè)屬性。這就是改寫機(jī)制(Name mangling)。兩個(gè)下劃線的屬性,被改寫成帶有類名前綴的變量,這樣子類很難明明一個(gè)和如此復(fù)雜名字重名的屬性。保證了屬性不被重載,保證了其的私有性。

4.1 突破私有屬性這里“私有變量”的實(shí)現(xiàn),是從解釋器層面給與的改寫,保護(hù)了私有變量。但是這個(gè)機(jī)制并非絕對(duì)安全,因?yàn)槲覀円廊豢梢酝ㄟ^ obj._ClasssName__private 來(lái)訪問 __private 私有屬性。

car1.brand = ‘Toyota’

car1._moto_type = ‘6AR-FSE’

car1._Car__wheel_type = ‘BRIDGESTONE’

car1.drive()

結(jié)果

Start the engine 6AR-FSE,

drive the wheel BRIDGESTONE,

I get a running Toyota car

可見,對(duì)改寫機(jī)制改寫的私有變量,雖然保護(hù)性加強(qiáng)了,但依然可以訪問并修改。只是這種修改,只是一種雜耍般的操作,并不可取。

五、__var__用于魔術(shù)方法

變量前面兩個(gè)下劃線,后面兩個(gè)下劃線。這是 Python 當(dāng)中的魔術(shù)方法,一般是給系統(tǒng)程序調(diào)用的。例如上例中的 __init__ 就是類的初始化魔術(shù)方法,還有支持 len 函數(shù)的 __len__ 方法,支持上下文管理器協(xié)議的 __enter__ 和 __exit__ 方法,支持迭代器協(xié)議的 __iter__ 方法,支持格式化顯示的 __repr__ 和 __str__ 方法等等。這里我們?yōu)樯侠?Car 類添加魔術(shù)方法 __repr__ 來(lái)支持格式化顯示。

def __repr__(self):

return ‘***Car %s:with %s Engine,%sWheel***’%

(self.brand,self._moto_type,self.__wheel_type)

未添加__repr__魔術(shù)方法之前,print(car1)結(jié)果為《__main__.Car object at 0x0047F7F0》,這個(gè)結(jié)果讓人看的一頭霧水,增加 repr 魔術(shù)方法之后,顯示結(jié)果為***Car Toyota:with 6AR-FSE Engine,BRIDGESTONE Wheel***清晰明了,利于調(diào)試。這就是魔術(shù)方法的功效:支持系統(tǒng)調(diào)用,改進(jìn)用戶類表現(xiàn),增加協(xié)議支持,使用戶類表現(xiàn)得更像系統(tǒng)類。

5.1 Python魔術(shù)方法分類以下所有魔術(shù)方法均需要在前后加上__,這里省略了這些雙下劃線。

一元運(yùn)算符 neg pos abs invert

轉(zhuǎn)換 complex int float round inex

算術(shù)運(yùn)算 add sub mul truediv floordiv mod divmod pow lshift rshift and xor or

算術(shù)運(yùn)算除 and 之外,前面再加上 r,表示反運(yùn)算。除 dimod 外,前面加上 i,表示就地運(yùn)算。

比較 lt le eq ne gt ge

類屬性 getattr getattribute setattr delattr dir get set delete

格式化 bytes hash bool format

類相關(guān) init del new

列表 getitem

迭代器 iter next

上下文管理器 enter exit

六、總結(jié)

總之,下劃線在 Python 當(dāng)中應(yīng)用還是很廣泛的,甚至可以說 Python 對(duì)下劃線有所偏愛??梢钥吹?_常用于臨時(shí)變量,在 REPL,for 循環(huán),元組拆包和國(guó)際化中得到了廣泛應(yīng)用。var_用于解決命名沖突問題,使用時(shí)比較簡(jiǎn)單易懂的。

_var對(duì)變量的保護(hù),只是一種脆弱的保護(hù),更多依靠程序員的約定。__var用于私有變量,借助改寫機(jī)制支持,已經(jīng)支持了私有變量,但是仍然存在漏洞。對(duì)__var__用于魔術(shù)方法,進(jìn)行了一個(gè)簡(jiǎn)單的介紹,魔術(shù)方法較多,但是理解并不復(fù)雜。希望以后可以進(jìn)一步介紹這些魔術(shù)方法。

編輯:jq

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • python
    +關(guān)注

    關(guān)注

    54

    文章

    4754

    瀏覽量

    84196
  • 解釋器
    +關(guān)注

    關(guān)注

    0

    文章

    103

    瀏覽量

    6475

原文標(biāo)題:Python 里最具代表性的符號(hào),竟如此強(qiáng)大

文章出處:【微信號(hào):LinuxHub,微信公眾號(hào):Linux愛好者】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    pytorch和python的關(guān)系是什么

    在當(dāng)今的人工智能領(lǐng)域,Python已經(jīng)成為了最受歡迎的編程語(yǔ)言之一。Python的易學(xué)易用、豐富的庫(kù)和框架以及強(qiáng)大的社區(qū)支持,使其成為了數(shù)據(jù)科學(xué)、機(jī)器學(xué)習(xí)和深度學(xué)習(xí)等領(lǐng)域的首選語(yǔ)言。而在深度學(xué)習(xí)領(lǐng)域
    的頭像 發(fā)表于 08-01 15:27 ?1125次閱讀

    Python建模算法與應(yīng)用

    Python作為一種功能強(qiáng)大、免費(fèi)、開源且面向?qū)ο蟮木幊陶Z(yǔ)言,在科學(xué)計(jì)算、數(shù)學(xué)建模、數(shù)據(jù)分析等領(lǐng)域展現(xiàn)出了卓越的性能。其簡(jiǎn)潔的語(yǔ)法、對(duì)動(dòng)態(tài)輸入的支持以及解釋語(yǔ)言的本質(zhì),使得Python
    的頭像 發(fā)表于 07-24 10:41 ?324次閱讀

    Python自動(dòng)化測(cè)試框架及其應(yīng)用

    Pytest是一個(gè)非常成熟的全功能的Python測(cè)試框架,與python自帶的unittest測(cè)試框架類似,但是比unittest框架使用起來(lái)更簡(jiǎn)潔,功能更強(qiáng)大。
    的頭像 發(fā)表于 04-03 16:15 ?441次閱讀
    <b class='flag-5'>Python</b>自動(dòng)化測(cè)試框架及其應(yīng)用

    小白請(qǐng)問電路這兩個(gè)半圓代表什么?

    請(qǐng)問電路這兩個(gè)半圓代表什么元件? 沒有搜到呀。 另外,請(qǐng)問下圖中的3.3v 電源是不是都要接到一起. 謝謝
    發(fā)表于 02-16 16:32

    如何使用linux下gdb來(lái)調(diào)試python程序

    如何使用linux下gdb來(lái)調(diào)試python程序? 在Linux下,可以使用GDB(GNU調(diào)試器)來(lái)調(diào)試Python程序。GDB是一個(gè)強(qiáng)大的調(diào)試工具,可以幫助開發(fā)者診斷和修復(fù)程序中的錯(cuò)誤。在本文
    的頭像 發(fā)表于 01-31 10:41 ?2116次閱讀

    斷路器上各種符號(hào)代表什么

    斷路器是一種用于保護(hù)電路免受過載和短路的電器設(shè)備。它能夠通過切斷電流來(lái)阻止意外情況的發(fā)生,從而保護(hù)電器設(shè)備和人身安全。在斷路器上,有許多符號(hào),它們代表著不同的功能和特征。接下來(lái),我將詳細(xì)介紹斷路器上
    的頭像 發(fā)表于 12-15 10:58 ?6997次閱讀

    常見電子元器件符號(hào)的含義

    不同電子元器件的符號(hào)代表著它們的不同功能和特性。以下是一些常見電子元器件的符號(hào)以及它們的含義。
    的頭像 發(fā)表于 12-01 09:18 ?7927次閱讀
    常見電子元器件<b class='flag-5'>符號(hào)</b>的含義

    python中number代表什么

    Python中,number(數(shù)字)是一種內(nèi)置的數(shù)據(jù)類型,用于表示數(shù)值。Python提供了幾種不同的number類型,分別是整數(shù)(int)、浮點(diǎn)數(shù)(float)、復(fù)數(shù)(complex)和布爾值
    的頭像 發(fā)表于 11-22 09:50 ?1592次閱讀

    pythonitem的用法

    item是Python中一個(gè)非常重要的概念,它可以用于多種數(shù)據(jù)結(jié)構(gòu)和算法的實(shí)現(xiàn)。在Python中,item通常用于表示一個(gè)集合或序列中的一個(gè)元素。本文將詳細(xì)介紹item的用法,并探討它在列表、字典
    的頭像 發(fā)表于 11-21 15:09 ?3120次閱讀

    什么是殘余電荷?殘余電荷的代表性試驗(yàn)

    您是否有在日常生活中使用完電器產(chǎn)品拔下插頭后,因觸摸到插頭的金屬部分而發(fā)生觸電的經(jīng)歷呢?我想應(yīng)該大多數(shù)的人應(yīng)該是沒有經(jīng)歷過的。
    的頭像 發(fā)表于 11-21 11:24 ?1751次閱讀
    什么是殘余電荷?殘余電荷的<b class='flag-5'>代表性</b>試驗(yàn)

    榮登2023年《財(cái)富》最具影響力物聯(lián)創(chuàng)新榜

    &準(zhǔn)時(shí)達(dá)項(xiàng)目榮登2023年《財(cái)富》最具影響力物聯(lián)創(chuàng)新榜。以精立業(yè),以質(zhì)取勝,持續(xù)創(chuàng)新!未來(lái),云將繼續(xù)以科技賦能,致力于打造具有
    的頭像 發(fā)表于 11-02 13:45 ?485次閱讀

    解讀可穿戴設(shè)備代表性產(chǎn)品核心技術(shù)原理

    電子發(fā)燒友網(wǎng)站提供《解讀可穿戴設(shè)備代表性產(chǎn)品核心技術(shù)原理.doc》資料免費(fèi)下載
    發(fā)表于 10-31 11:22 ?0次下載
    解讀可穿戴設(shè)備<b class='flag-5'>代表性</b>產(chǎn)品核心技術(shù)原理

    Delorean:優(yōu)秀的Python時(shí)間格式轉(zhuǎn)換工具

    模塊名稱的由來(lái),Delorean 是電影《回到未來(lái)》的那輛極為炫酷的鷗翼汽車,采用這部電影的非常具有代表性
    的頭像 發(fā)表于 10-31 10:51 ?445次閱讀

    Delorean:優(yōu)秀的時(shí)間格式智能轉(zhuǎn)換工具

    名稱的由來(lái),Delorean 是電影《回到未來(lái)》的那輛極為炫酷的鷗翼汽車,采用這部電影的非常具有代表性的汽
    的頭像 發(fā)表于 10-30 10:23 ?339次閱讀

    Camelot:Python強(qiáng)大的PDF表格提取器

    如果你有從PDF中批量提取表格的需求,那么這篇文章就是你的福音。 Python 第三方模塊 Camelot 能夠精準(zhǔn)識(shí)別PDF中的表格信息,并提取為pandas數(shù)據(jù)結(jié)構(gòu),而且還能導(dǎo)出為多種格式
    的頭像 發(fā)表于 10-21 10:57 ?1329次閱讀
    Camelot:<b class='flag-5'>Python</b>超<b class='flag-5'>強(qiáng)大</b>的PDF表格提取器