第二十五章 面向对象------封装、内置函数、反射、动态导入
1、封裝
什么是封裝?
1.對外部隱藏內(nèi)部的屬性,以及實現(xiàn)細節(jié),給外部提供使用的接口
注意:封裝有隱藏的意思,但不是單純的隱藏
學習封裝的目的:就是為了能夠限制外界對內(nèi)部數(shù)據(jù)的訪問
python中屬性的權(quán)限分為兩種:
1.公開的
沒有任何限制,誰都可以訪問
2.私有的
只有當前類本身能狗訪問
默認為公共的
為什么要封裝?
1.提高安全性
封裝屬性
2.隔離復雜度
封裝方法
一個類中分為兩種數(shù)據(jù):屬性和方法
封裝屬性
class Student:
def __init__(self,name,age,gender,id_card):
self.name = name
self.age = age
self.gender = gender
self.__id_card = id_card
def show_id_card(self):
?可以在這里添加額外的任何邏輯代碼 來限制外部的訪問
在類的內(nèi)部 可以訪問
print(self.__id_card)
對私有屬性的訪問以及修改
class Student:
def __init__(self,name,age,gender,id_card):
self.name = name
self.age = age
self.gender = gender
self.__id_card = id_card
?訪問被封裝的屬性 稱之為訪問器
def get_id_card(self,pwd):
?可以在這里添加額外的任何邏輯代碼 來限制外部的訪問
?在類的內(nèi)部 可以訪問
if pwd =="123":
return self.__id_card
raise Exception("密碼錯誤!")
?修改被封裝的屬性 稱之為設(shè)置器
def set_id_crad(self,new_id):
?身份證必須是字符串類型
?長度必須是18位
if isinstance(new_id,str) and len(new_id) == 18:
self.__id_card = new_id
else:
raise Exception("身份證號碼 必須是字符串 且長度必須為18!")
什么樣的方法應該被封裝起來?
一個為內(nèi)部提供支持的方法,不應該讓外界直接訪問,那就封裝起來,如下例中的 ?user_auth
class ATM:
def withdraw(self):
self.__user_auth()
self.__input_money()
self.__save_record()
# 輸入賬號和密碼
# 顯示余額
# 輸入取款金額
# 保存記錄
def __user_auth(self):
print('請輸入賬號密碼...')
def __input_money(self):
print('余額為1000000000,請輸入取款金額!')
def __save_record(self):
print('記錄流水......')
封裝原理:
python是通過 變形的方式來實現(xiàn)的封裝
如何變形 在名稱帶有雙下劃線開頭的變量名字前添加_類名 如_Person__id_card
當然通過變形后的名字可以直接訪問被隱藏的屬性 但通過不應該這么做
變形僅在類的定義階段發(fā)生一次 后續(xù)再添加的帶有雙下劃線的任何屬性都不會變形 就是普通屬性
什么時候用?
封裝屬性:
當這個對象存在一個機密性的屬性,例:身份證信息,銀行卡密碼等,這樣屬性不應該被外界直接訪問到時就將其封裝。
封裝方法:
一個為內(nèi)部提供支持的方法,不應該讓外界直接訪問,那就將其封裝。
?
Prorety
作用:將一個方法偽裝成普通屬性;用property是為了希望將訪問私有屬性和普通屬性的方式變得一致。
與Prorety相關(guān)的兩個裝飾器:
setter:用 . (點)語法給屬性賦值是觸發(fā)
deleter:用 . (點)語法刪除屬性時觸發(fā)
例:
calss Teacher:
def __init__(self,name,age.salary):
self.name=name
self.age=age
self.__salary=salary
@property # getter ? # 用于訪問私有屬性的值 ? 也可以訪問普通屬性
def salary(self):
return self.__salary
@salary.setter # 用來設(shè)置私有屬性的值 ?也可以設(shè)置普通屬性
def salary(self):
self.__salary=new_salary
@salary.deleter ?# 用來設(shè)置私有屬性的值 ?也可以刪除普通屬性
# print("can not delete salary!")
del ?self.__dict__['Teacher__salary']
Property 計算屬性使用場景:
什么是計算屬性:
一個屬性它的值不是固定死的,而是通過計算動態(tài)產(chǎn)生的。
class Person:
def __inin__(self,name,height,weight):
self.name=name
self.height=height
self.weight=weight
@aproperty
def ?BMI(self):
return sdlf.weight/(self.height**2)
@setter
def ?BMI(self,new_BMI):
print('BMI 不支持自定義......')
p=person('egon',1.7,80)
print(p.BMI)
P.BMI=10
?
多態(tài):?多態(tài)不是一個具體的技術(shù)或代碼,指的是,多個不同類型對象,可以響應同一個方法,產(chǎn)生不同結(jié)果
使用多態(tài)的好處:
只需要學習積累中的使用方法即可,不需要關(guān)心具體的哪一個類,實現(xiàn) ?
?以不變應萬變 ?提高靈活性 ?提高擴展性
如果沒有多態(tài),需要分別學習 person cat pig 的不同使用方法,這對于使用者而言太麻煩了
鴨子類型:就是典型的多態(tài),多重不同類型 使用方法一樣
案例:
class Cat():
def bark(self):
print("喵喵喵")
def run(self):
print("四條腿跑!")
def sleep(self):
print("趴著睡!")
class Pig():
def bark(self):
print("哼哼哼!")
def run(self):
print("四條腿跑!")
def sleep(self):
print("側(cè)躺著睡!")
# 一個用來管理動物的方法 只要你傳入是一個動物 我就按照動物的標準來使用 完全不用考慮你具體是什么類型
def management_animal(animal):
print("==================正在溜%s=============" % animal.__class__.__name__)
animal.bark()
animal.run()
animal.sleep()
?
常用的內(nèi)置函數(shù)
__str__
對象轉(zhuǎn)成字符串是被強制執(zhí)行
__del__
__del__:當對象被刪除前會自動調(diào)用 ,該方法聲明時候會刪除對象?
1.程序運行結(jié)束,解釋器退出,將自動刪除所有數(shù)據(jù)
2.手動調(diào)用del 時也會刪除對象
注意:該函數(shù)不是用來刪除對象的
使用場景:
當你的對象在創(chuàng)建時,開啟了不屬于解釋器的資源,例如打開一個文件必須保證對象被刪除時,
同時關(guān)閉額外的資源,如文件。
__del__也稱之為析構(gòu)函數(shù),析構(gòu),構(gòu)造的反義詞
構(gòu)造:值得是從無到有
析構(gòu):至從有到無
簡單的說就對象所有數(shù)據(jù)全部刪除
總結(jié):__del__該函數(shù),用于在對象刪除前做一些清理操作
class Person:
def __init__(self,name,path,mode="rt",encoding="utf-8"):
self.name = name
self.file = open(path,mode,encoding=encoding)
?
# 讀取數(shù)據(jù)的方法
def read_data(self):
return self.file.read()
def __del__(self):
print("del run!")
self.file.close()
?
反射(英文中叫反省,自省)
面向?qū)ο笾械姆词≈档氖?#xff0c;一個對象必須具備,發(fā)現(xiàn)自身屬性,以及修改自身屬性的能力
一個對象在設(shè)計初期,可能考慮不夠周全后期需要刪除或修改已經(jīng)存在的屬性,和增加屬性
反射就是通過字符串來操作對象屬性
涉及到方法:
hasattr 判斷是否存在某個屬性
getattr 獲取某個屬性的值
setattr 新增或修改某個屬性
delattr 刪除某個屬性
class MY_CMD:
?
? ?def dir(self):
? ? ? ?os.system("dir")
?
? ?def ipconfig(self):
? ? ? ?os.system("ipconfig")
?
cmd = MY_CMD()
?
while True:
? ?name = input("請輸入要執(zhí)行的功能:")
? ?if hasattr(cmd,name):
? ? ? ?method = getattr(cmd,name)
? ? ? ?print(method)
? ? ? ?method()
? ?else:
? ? ? ?print("sorry this method is not exists....!") ?
動態(tài)導入模塊
直接寫import 稱之為靜態(tài)導入 建立在一個基礎(chǔ)上:提前已經(jīng)知道有這個模塊
動態(tài)導入 指的是 在需要的任何時候 通過指定字符串類型的包名稱來導入需要的模塊
import importlib
mk = importlib.import_module(m_name)
mk 即導入成功的模塊
"""
該方式常用在框架中 因為框架設(shè)計者不可能提前預知后續(xù)需要的模塊和類
?
?
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/sry622/p/10896914.html
總結(jié)
以上是生活随笔為你收集整理的第二十五章 面向对象------封装、内置函数、反射、动态导入的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 求一个女性个人名言个性签名
- 下一篇: 呼和浩特三中实验集团校长奖学金算体育成绩