我的Python學習筆記(三):私有變量


一、私有變量的定義

在Python中,有以下幾種方式來定義變量:

  • xx:公有變量
  • _xx:單前置下划線,私有化屬性或方法,類對象和子類可以訪問,from somemodule import *禁止導入
  • __xx:雙前置下划線,私有化屬性或方法,無法在外部直接訪問(名字重整所以訪問不到)
  • __xx__:雙前后下划線,系統定義名字(不要自己發明這樣的名字)
  • xx_:單后置下划線,用於避免與Python關鍵詞的沖突

 

如以下例子所示,我在test類中定義了num,_num 和 __num三個屬性,並創建了test的類對象t,對這三個屬性進行訪問,__num不能被訪問到

class test(object):
    def __init__(self):
        self.num = 10
        self._num = 20
        self.__num = 30

t = test()
print(t.num)    # 10
print(t._num)   # 20
# print(t.__num)  # AttributeError: 'test' object has no attribute '__num'

可以使用命令dir查看t中的屬性和方法,__num的名字已經被重整為“_test__num”了,可以使用t._test__num對__num進行訪問

注:雖然私有變量可以通過_類名__變量名來訪問,但強烈建議不要這樣做

 

二、使用不同方法導入模塊,模塊中私有變量的使用區別

在使用不同方法導入模塊后,是否能使用模塊中的私有屬性和方法,有以下兩種情況

  • 在使用 from somemodule import * 導入模塊的情況下,不能導入或使用私有屬性和方法
  • 在使用 import somemodule 導入模塊的情況下,能導入並使用私有屬性和方法

首先我們先創建一個test.py文件,將下面代碼復制進去:

num = 10
_num = 20
__num = 30

def test():
    print("--test--")

def _test2():
    print("--test2--")

def __test3():
    print("---test3--")
  • 使用 from somemodule import * 進行導入,不能導入私有變量,結果如下:
In [1]: from test import *

In [2]: num
Out[2]: 10

In [3]: _num
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-3-6dd7111d6a95> in <module>()
----> 1 _num

NameError: name '_num' is not defined

In [4]: __num
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-4-f0ba2c4a214a> in <module>()
----> 1 __num

NameError: name '__num' is not defined

In [5]: test()
--test--

In [6]: _test2()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-6-d29889233d08> in <module>()
----> 1 _test2()

NameError: name '_test2' is not defined

In [7]: __test3()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-7-17e592a156f3> in <module>()
----> 1 __test3()

NameError: name '__test3' is not defined

 

  • 使用 import somemodule 進行導入,能導入私有變量,結果如下:
In [8]: import test

In [9]: test.num
Out[9]: 10

In [10]: test._num
Out[10]: 20

In [11]: test.__num
Out[11]: 30

In [12]: test.test()
--test--

In [13]: test._test2()
--test2--

In [14]: test.__test3()
---test3--

 

三、對類中的私有屬性進行操作的方法

如果你想對類中的私有屬性進行操作時,有以下三種方法:

1、getter和setter:

添加getter和setter方法,類對象通過調用這兩種方法來對私有屬性進行操作

class test(object):
    def __init__(self):
        self.__num = 10
        
    def getNum(self):
        return self.__num

    def setNum(self, value):
        self.__num = value

t = test()
print(t.getNum())   # 10
t.setNum(20)
print(t.getNum())   # 20

 

  2、property方法

class test(object):
    def __init__(self):
        self.__num = 10

    def getNum(self):
        return self.__num
    
    def setNum(self, value):
        self.__num = value

    num = property(getNum,setNum)

t = test()
print(t.num)   # 10
t.num = 20
print(t.num)   # 20

關於property方法,我們來看下官方文檔:

由文檔可得:

  • property方法包含四個參數,分別為fget,fset,fdel,doc,分別對應getter方法,setter方法,deleter方法和方法說明
  • property()方法返回一個property屬性,如果c是C的實例,那么c.x會調用getter方法,c.x = value會調用setter方法,而del c.x會調用deleter方法

  

  3、@property

class test(object):
    def __init__(self):
        self.__num = 10

    @property
    def num(self):
        return self.__num

    @num.setter
    def num(self, value):
        self.__num = value

t = test()
print(t.num)   # 10
t.num = 20
print(t.num)   # 20

關於@property,官方文檔如下:

 

根據文檔可得:

  • 我們可以把property()方法當成一個裝飾器來使用,使用@property對方法進行裝飾
  • 裝飾器@property把方法x()轉換成了與方法名同名的getter方法,"I'm the 'x' property."是property的doc參數
  • 調用方法和property()方法一樣


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM