python面向對象之封裝


1. 封裝(實際封裝python中的封裝只是一個約定)

第一層面的封裝:類就好像一個袋子,這就是一種封裝

第一階段:

# 如果我們要定義學生jack如何定義?
name = 'jack'
age = 17
sex = '男'
這三個變量可以用來形容jack這個人(當然你也可以使用字典,列表去描述).但是我們用三個變量去形容這個人,有什么弊端?
	弊端:太零散,如果學生太多,需要有很多變量去描述
為了解決這個問題,因此才有了類。

第二階段:

class Student(object):

    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex

one = Student('jack',17,'男') # 這里的one就相當於一個學生jack,所有的屬性都封裝到了one變量中。這里的Student類,相當於一個模板。只要給定它name,age,sex,它就能創建出一個學生對象。
two = Student('aaa',16,'男')
three = Student('bbb',15,'女')
four = Student('ccc',14,'男')
five = Student('ddd',13,'女')
print(f'姓名:{one.name}   年齡:{one.age}    性別:{one.sex}')
姓名:jack   年齡:17    性別:男

到這里,不知道你是否已經體會到使用類封裝的便利沒!

第二層面的封裝:類中定義私有的,只有類內部使用,外部無法訪問(比如_(杠) __(杠杠) )

第一階段:

class Student(object):

    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex


one = Student('plf',18,'男')
one.name = 'who'
one.age = -28
one.sex = '人妖'
print(f'姓名:{one.name}   年齡:{one.age}    性別:{one.sex}')
姓名:who   年齡:-28    性別:人妖

問題:我們在外部能隨意訪問到對象one的屬性,並且隨意修改,這樣數據是不安全的,因為我們需要將屬性隱藏起來。那我們應該如何去做了?

第二階段:

class Student(object):

    def __init__(self,name,age,sex):
        self.__name = name
        self.__age = age
        self.__sex = sex

one = Student('plf',18,'男')

print(one._Student__name)
print(one._Student__age)
print(one._Student__sex)

one._Student__age = 20	
print(one._Student__age)


rint(one.__name)       # 報錯,無該屬性
print(one.name)         # 報錯,無該屬性
plf
18
男
20

此時發現,我們雖然不能使用one.name或者one.__name訪問到該屬性。但是我們可使用one._Student__age訪問到對象的age屬性並且能修改。說明python在設置私有屬性的時候,只是把屬性的名字換成了其他的名字。

總結:

​ 類中以_或者__的屬性,都是私有屬性,禁止外部調用。雖然我們可以通過特殊的手段獲取到,並且賦值,但是最好不要這么做(約定俗成)

問題:現在我將name,age,sex設置為私有屬性,但是我又想讓他們通過我指定的接口去訪問或者修改我的屬性,應該如何實現了?

第三階段:

Student(object):

    def __init__(self,name,age,sex):
        self.__name = name
        self.__age = age
        self.__sex = sex

    def get_name(self):
        return self.__name


    def set_name(self,name):
        if len(name) > 1 :
            self.__name = name
        else:
            print("name的長度必須要大於1個長度")

    def get_age(self):
        return self.__age

    def set_age(self, age):
        if age > 0 and age < 150:
            self.__age = age
        else:
            print("輸入的年齡必須要大於0,小於150歲")

one = Student('plf',18,'男')

one.set_name('a')       # 通過自己設置接口,可以有效規避臟數據
print(one.get_name())       # 通過接口獲取數據


one.set_age(-9)         # 通過自己設置接口,可以有效規避臟數據
print(one.get_age())    # 通過接口獲取數據
name的長度必須要大於1個長度
plf
輸入的年齡必須要大於0,小於150歲
18

這樣我們就自定義了自己屬性的接口,它的好處在於:規避臟數據

問題:使用接口設置獲取數據 和 使用點方法(one.name = 18 或者print(one.name))設置數據相比, 點方法使用更方便,我們有什么方法達到 既能使用點方法,同時又能讓點方法直接調用到我們的接口了? 其他python已經幫我們實現了,讓我們一起看一下吧!

第四階段:

class Student(object):

    def __init__(self,name,age,sex):
        self.__name = name
        self.__age = age
        self.__sex = sex

    @property
    def name(self):
        return self.__name

    @name.setter
    def name(self,name):
        if len(name) > 1 :
            self.__name = name
        else:
            print("name的長度必須要大於1個長度")

    @property
    def age(self):
        return self.__age

    @age.setter
    def age(self, age):
        if age > 0 and age < 150:
            self.__age = age
        else:
            print("輸入的年齡必須要大於0,小於150歲")


one = Student('plf',18,'男')

one.name = '張三'
print(one.name)

one.age = 170
print(one.age)
張三
輸入的年齡必須要大於0,小於150歲
18

總結:

  1. 使用 @property 裝飾器時,接口名不必與屬性名相同.
  2. 凡是賦值語句,就會觸發set方法。獲取屬性值,會觸發get方法


免責聲明!

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



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