python 詳解類class的存取控制:單底線_與雙底線__(四)__python

來源:互聯網
上載者:User

Python中沒有存取控制的關鍵字,例如private、protected (java)等等。但是,在Python編碼中,有一些約定來進行存取控制。

1、單底線”_” 在Python中,通過單底線”“來實現模組層級別的私人化,變數除外。一般約定以單底線”“開頭的函數為模組私人的,也就是說”from moduleName import * “將不會引入以單底線”_”開頭的函數。

現在有一個模組 example_example.py,內容用如下,模組中一個變數名和一個函數名分別以”_”開頭:

name = 'bruce'_tall = 180def call_for():    print('name is :',name)    print('_tall is',_tall)def _call_for():    print('name is :',name)#_call_for = _call_for()    print('_tall is',_tall)

_tall is 180

再次調用該指令碼:

#呼叫指令碼模組example_exampleimport example_example#調用不帶底線變數example_example.nameOut[12]: 'bruce'#調用帶底線變數example_example._tall     #對於變數單底線不會影響調用Out[13]: 180#調用不帶底線函數example_example.call_for()Out[16]: name is : bruce _tall is 180#調用不帶底線函數會報錯example_example._call_for()Traceback (most recent call last):  File "<ipython-input-15-e642b1386946>", line 1, in <module>    example_example._call_for()TypeError: 'NoneType' object is not callable


2、雙底線”__” 對於Python中的類屬性,可以通過雙底線”__”來實現一定程度的私人化,因為雙底線開頭的屬性在運行時會被”混淆”(mangling)。

class person(object):    tall = 180    hobbies = []    def __init__(self, name, age,weight):        self.name = name        self.age = age        self.weight = weight        self.__Id = 430    @classmethod    def infoma(cls):        print(cls.__Id)# person.infoma()Bruce = person("Bruce", 25,180)print(Bruce.age)print(Bruce.__Id)
25
---------------------------------------------------------------------------AttributeError                            Traceback (most recent call last)<ipython-input-32-ae0c1d7abe5a> in <module>()     15 Bruce = person("Bruce", 25,180)     16 print(Bruce.age)---> 17 print(Bruce.__Id)AttributeError: 'person' object has no attribute '__Id'

其實,通過內建函數dir()就可以看到其中的一些原由,”__address”屬性在運行時,屬性名稱被改為了”_person__address”(屬性名稱前增加了單底線和類名)

print(dir(Bruce))

#可以看到Bruce中有_person__Id的屬性,相較原__Id屬性,變得可調用['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_person__Id', 'age', 'hobbies', 'infoma', 'name', 'tall', 'weight']

所以說,即使是雙底線,也沒有實現屬性的私人化,因為通過下面的方式還是可以直接存取”__address”屬性:

print(Bruce._person__Id)

430 #通過使屬性__Id名前增加了單底線_和類名person來實現屬性的可調用


雙底線的另一個重要的目地是,避免子類對父類同名屬性的衝突

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()

A.__private()

B.public()

當執行個體化B的時候,由於沒有定義_ _init_ 函數,將調用父類的 _ _init_ _,但是由於雙底線的”混淆”效果,”self.__private()”將變成 “self._A__private()”。

總結: 
“_”和” __”的使用 更多的是一種規範/約定,不沒有真正達到限制的目的: “_”:以單底線開頭的表示的是 protected 類型的變數,即只能允許其本身與子類進行訪問;同時表示弱內部變數標示,如,當使用”from moduleNmae import *”時,不會將以一個底線開頭的對象引入。 “__”:雙底線的表示的是私人類型的變數。只能是允許這個類本身進行訪問了,連子類也不可以,這類屬性在運行時屬性名稱會加上單底線和類名


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.