Python編程筆記--私有化

1、私有化的實現

在Python中想定義一個類是比較簡單的,好比要定義一個Person類,以下代碼便可:微信

# -*- coding: utf-8 -*-
# __author : Demon
# date : 1/5/18 8:24 PM

class Person(object):
    pass

p1 = Person()

固然咱們也能夠給類添加相應的屬性,好比Person的姓名,年齡,性別等,而且在new一個Person對象後能夠對這些屬性進行修改,以下代碼所示:spa

# -*- coding: utf-8 -*-
# __author : Demon
# date : 1/5/18 8:24 PM

class Person(object):
    def __init__(self, name, age, sex):
        self.name = name #姓名
        self.age = age #年齡
        self.sex = sex #性別

    def __str__(self): #定義直接打印Person對象,輸出的內容。至關於Java中的toString()方法
        return ('%s , %s , %s '  % (self.name, self.age, self.sex))

p1 = Person('Demon', 18, 'M')
print(p1) #Demon , 18 , M 

p1.age = 28 #修改對象的年齡
print(p1) #Demon , 28 , M

Python是面向對象的語言,咱們都知道面向對象的三大特色:繼承、封裝和多態。而在上面的代碼中,咱們能夠輕易地經過person. 調用屬性來訪問和修改值,這明顯不符合面向對象中封裝的思想。好比對於Person類中的年齡屬性,可能比較私人,因此咱們不但願能夠任意的訪問和修改它的值。在Java中,咱們是經過private關鍵字來裝飾屬性私有,那麼在Python中有沒有相似的關鍵字呢?顯然是有的,在Python中採起在變量名前加__(兩個下劃線)的方式來將屬性私有。以下代碼所示:對象

# -*- coding: utf-8 -*-
# __author : Demon
# date : 1/5/18 8:24 PM

class Person(object):
    def __init__(self, name, age, sex):
        self.name = name #姓名
        self.__age = age #年齡,將年齡私有
        self.sex = sex #性別

    def __str__(self): #定義直接打印Person對象,輸出的內容。至關於Java中的toString()方法
        return ('%s , %s , %s '  % (self.name, self.__age, self.sex))

p1 = Person('Demon', 18, 'M')
print(p1) #Demon , 18 , M

p1.age = 28 #這裏只是給p1對象動態的增長了一個age屬性
print(p1) #Demon , 18 , M
print(p1.age) #28

初看上面的代碼,彷佛感受並無達到私有的目的,由於咱們經過p1.age仍是成功地進行了賦值,程序並無報錯。其實這裏是由於Python能夠動態地給對象增長屬性和方法,這句話至關於動態地給p1這個對象增長了一個age屬性。因此在咱們作了賦值操做以後,咱們再次打印p1,age的值依然是18。說明咱們確實已經將類裏的age屬性進行的私有。同理方法的私有也是同樣的處理。繼承

 

2、私有化的注意事項

在Python中,有幾種方式來定義變量:utf-8

一、以單劃線開頭:這種類型的變量能夠經過對象.調用,可是它表示的意思是我能夠調用,但請把我視爲是私有的。並且若是是經過from xxx_module import *是沒法訪問的,可是若是是import xxx_module的方式,則能夠訪問到,類對象和子類也均可以訪問。get

二、僅以雙劃線開頭:這種類型的變量就是私有。可是它能夠經過__類名__變量名來訪問,但強烈建議不要這樣作it

三、以雙劃線開頭,並以它結尾:這種類型的變量在Python中一般都表示具備特殊意義的變量,好比__init__,__str__等。因此咱們在定義變量時不要這樣定義class

四、僅以單劃線結尾:這種類型的變量是用於避免與Python關鍵字進行衝突所採起的一種解決辦法import

以下圖演示訪問權限效果:變量

 

3、property的使用

上面的介紹了,經過加雙劃線開頭的方式實現了變量和方法。參照在學Java時的思路,若是想要訪問私有變量,咱們會給變量添加get和set方法。一樣咱們在Python中也是同樣的處理,代碼以下所示:

class Person(object):
    def __init__(self, name, age, sex):
        self.name = name #姓名
        self.__age = age #年齡,將年齡私有
        self.sex = sex #性別

    def getAge(self):
        return self.__age

    def setAge(self, age):
        self.__age = age

p1 = Person('Demon', 18, 'M')
print(p1.getAge()) #18

p1.setAge(28)
print(p1.getAge()) #28

可是這樣看着彷佛不是很方便,每次都要調用一個方法。有沒有可能像以前同樣調用p1. age = 28就能直接賦值呢?顯然在Python中是能夠的,這就要用到property。

property的定義:

使用代碼示例:

class Person(object):
    def __init__(self, name, age, sex):
        self.name = name #姓名
        self.__age = age #年齡,將年齡私有
        self.sex = sex #性別

    def getAge(self):
        return self.__age

    def setAge(self, age):
        self.__age = age

    age = property(getAge, setAge, 'This is age property')

p1 = Person('Demon', 18, 'M')
print(p1.age) #18

p1.age = 28
print(p1.age) #28

說明:

1. property接受四個參數,分別是get, set, del, doc,前三個參數分別對應get方法,set方法,del方法,順序不能出錯。最後一個參數是doc,至關於對方法進行說明。

2. property返回一個property屬性,返回值的變量名與最終對象. 後面的名稱是一致的

 

觀察上面的代碼,咱們仍然須要多寫一行property的代碼,而Python其實提供了一個更方便的實現方式來達到上述要求,即便用@property。說明以下:

示例代碼以下: 

class Person(object):
    def __init__(self, name, age, sex):
        self.name = name #姓名
        self.__age = age #年齡,將年齡私有
        self.sex = sex #性別

    @property
    def age(self):  #注意方法名直接爲變量名
        return self.__age

    @age.setter     #注意方法名直接爲變量名
    def age(self, age):
        self.__age = age


p1 = Person('Demon', 18, 'M')
print(p1.age) #18

p1.age = 28
print(p1.age) #28

 說明:

1. @property至關於對age方法進行了一個裝飾,它使得咱們能經過對象.方法名來調用對應的屬性

2. @property所裝飾的方法名與對象 . 調用的名稱要保持一致

3. @property會生成另外的裝飾器,@方法名.setter, @方法名.getter, @方法名.deleter,分別對應set, get, del方法。這裏get方法用得不多,由於已經經過@property直接對應到了get方法 

 

微信搜索【帕森與加瓦】可關注公衆號

相關文章
相關標籤/搜索