歡迎加入QQ討論群258996829
麥子學院 頭像
蘋果6袋
6
麥子學院

Python學習之訪問控制

發(fā)布時間:2018-04-15 23:16  回復:0  查看:2478   最后回復:2018-04-15 23:16  

Python從設計之初就是一門面向對象的語言,面向對象思想的第一個要素就是封裝。所謂封裝,通俗的講就是類中的屬性和方法,分為公有和私有,公有可以被外界訪問,私有不能被外界訪問,這就是封裝中最關鍵的概念——訪問控制。本文和大家分享的就是訪問控制相關內容,一起來看看吧,希望對想學習python的童鞋有所幫助。

  訪問控制有三種級別:私有、受保護、公有

  私有(Private):只有類自身可以訪問 受保護(Protected):只有類自身和子類可以訪問 公有(Public):任何類都可以訪問

  由于Python不像Java,有訪問控制符(private / public / protected),所以Python的訪問控制也是容易被應聘者忽視和搞錯的。

  公有(Public

  在Python的類中,默認情況下定義的屬性都是公有的。

  class Foo(object):

  bar = 123

  def __init__(self, bob):

  self.bob = bob

  print(Foo.bar)  # 123

  foo = Foo(456)

  print(foo.bob)  # 456

  上面類 Foo 中的 bar 屬性就是類屬性, __init__ 方法中定義的bob是實例屬性, bar bob 都是公有的屬性,外部可以訪問,分別print類中的 bar 和實例中的 bob ,輸出了對應的值。

  受保護(Protected

  在Python中定義一個受保護的屬性,只需要在其名字前加一個下劃線 _ ,我們將Foo方法中的bob  bar 改為 _bob  _bar ,他們就變成了受保護的屬性了,代碼如下:

  class Foo(object):

  _bar = 123

  def __init__(self, bob):

  self._bob = bob

  class Son(Foo):

  def print_bob(self):

  print(self._bob)

  @classmethod

  def print_bar(cls):

  print(cls._bar)

  Son.print_bar()  # 123

  son = Son(456)

  son.print_bob()  # 456

  定義一個類 Son 繼承自 Foo ,由于受保護的對象只能在類的內部和子類中被訪問,不能直接調用 print(Son._bar)  print(son._bob) 來輸出這兩個屬性的值,所以定義了 print_bar  print_bob 方法,實現在子類中輸出,這段代碼也正常的輸出了 _bar  _bob 的值。

  接下來,試著反向驗證一下,在類的外部,能不能訪問其屬性,將上面代碼的輸出部分修改如下:

  print(Son._bar)  # 123

  son = Son(456)

  print(son._bob)  # 456

  (假裝)驚訝的發(fā)現,竟然沒有報錯,也輸出了正確的值。

  Python中用加下劃線來定義受保護變量,是一種約定的規(guī)范,而不是語言層面真的實現了訪問控制,所以,我們定義的保護變量,依然可以在外部被訪問到(這是個feature,不是bug)。

  私有(private

  Python定義私有屬性,需要在屬性名前加兩個下劃線 __ ,把上面的代碼修改一下,運行一下會發(fā)現下面的代碼中的任何一個print都會報錯的。

  class Foo(object):

  __bar = 123

  def __init__(self, bob):

  self.__bob = bob

  class Son(Foo):

  def print_bob(self):

  print(self.__bob)  # Error

  @classmethod

  def print_bar(cls):

  print(cls.__bar)  # Error

  print(Son.__bar)  # Error

  son = Son(456)

  print(son._bob)  # Error

  深入一下——私有屬性真的就訪問不到了嗎?

  要了解私有屬性是否真的訪問不到,需要從Python是如何實現私有屬性入手。CPython中,會把雙下劃線的屬性變?yōu)?nbsp;_ClassName__PropertyName 的形式,用代碼演示一下:

  class Foo(object):

  __bar = 123

  print(Foo._Foo__bar)  # 123

  運行一下可以知道,正常輸出了 __bar 的值,但是不推薦這樣去訪問私有屬性,因為不同的Python解釋器對于私有屬性的處理不一樣。

  特例

  使用雙下劃線定義私有屬性,有一種特殊情況,當屬性后也有兩個下劃線的時候,這個屬性會被Python解釋器當做魔術方法,從而不做私有處理。

  class Foo(object):

  __bar__ = 123

  print(Foo.__bar__)  # 123

  上面代碼輸出了123,證明Python解釋器并沒有把 __bar__ 當做私有屬性。當定義私有屬性時,需要注意名字最后最多只能有一個下劃線。

  另一個特例

  假如定義的屬性名就叫 __ 呢?不妨直接試一下:

  class Foo(object):

  __ = 123

  print(Foo.__)  # 123

  可以發(fā)現名字叫 __ 的屬性也不會被認為是私有屬性,名字是多個下劃線的屬性也不是私有屬性(比如 _______ )。

 

 

來源:網絡

您還未登錄,請先登錄

熱門帖子

最新帖子

?