面向物件程式設計(三)
阿新 • • 發佈:2022-04-08
面向物件程式設計(三)
繼承下的派生實際應用
# 功能:重寫已有方法,在保證原來功能正常的情況下加入自己需要的功能 import datetime import json dict1 = {'datetime':datetime.datetime.today(),'time':datetime.date.today()} # res = json.dumps(dict1) # print(res) # Object of type 'datetime' is not JSON serializable class MyJSONEncoder(json.JSONEncoder): def default(self,o): # 形參o就是即將要被序列化的資料物件 print('重寫了') if isinstance(o, datetime.datetime): return o.strftime('%Y-%m-%d %X') # datetime格式轉成字串 elif isinstance(o, datetime.date): return o.strftime('%Y-%m-%d') # data時間格式轉成字串 return super(MyJSONEncoder, self).default(o) # 重新呼叫父類的方法,防止以前的功能不能用 res = json.dumps(dict1,cls=MyJSONEncoder) print(res) # {"datetime": "2022-04-08 16:01:19", "time": "2022-04-08"}
面向物件三大特徵之封裝
# 封裝的含義 將類中的某些名字'隱藏'起來 不讓外界直接呼叫 隱藏的目的是為了提供專門的通道(介面)去訪問 在通道內可以新增額外的功能 # 如何封裝 eg: class Student(object): def __init__(self,name,age): self.name = name self.age = age __school = '家裡蹲大學' # 名字前面加槓槓'__'即是封裝該名字的意思 def func1(self): print('func1') def __func2(self): # 函式名前面加__就是封裝整個函式 print('func2') obj1 = Student('petter',18) # print(obj1.name) # petter # print(obj1.__school) # AttributeError: 'Student' object has no attribute '__school' obj1.func1() # func1 obj1.__func2() # AttributeError: 'Student' object has no attribute '__func2' # 怎麼呼叫封裝資料? eg: class Student(object): def __init__(self, name, age): self.name = name self.age = age __school = '家裡蹲大學' # 名字前面加槓槓'__'即是封裝該名字的意思 def func1(self): print('func1') def __func2(self): # 函式名前面加__就是封裝整個函式 print('func2') def interface_school(self): # 定義呼叫資料的介面 print('我來自%s'%self.__school) def interface_func2(self): # 定義呼叫函式的介面 self.__func2() obj1 = Student('petter', 18) obj1.interface_school() # 我來自家裡蹲大學 obj1.interface_func2() # func2 """ 將資料隱藏起來就限制了類外部對資料的直接操作,然後類內應該提供相應的介面來允許類外部間接地操作資料, 介面之上可以附加額外的邏輯來對資料的操作進行嚴格地控制 目的的是為了隔離複雜度,例如ATM程式的取款功能,該功能有很多其他功能組成 比如插卡、身份認證、輸入金額、列印小票、取錢等,而對使用者來說,只需要開發取款這個功能介面即可,其餘功能我們都可以隱藏起來 """
property(方法偽裝成資料)
eg: # 輸入正方形邊長,計算周長和麵積 class Calculate(object): def __init__(self, r): self.r = r @property def perimeter(self): return '該正方形的周長是%f' % (self.r * 4) @property def area(self): return '該正方形的面積是%f' % (self.r ** 2) obj1 = Calculate(5) print(obj1.perimeter) # 和資料一樣的呼叫方式 print(obj1.area) 執行結果: 該正方形的周長是20.000000 該正方形的面積是25.000000
小發現
def func():
a = 2
return '執行結果是%s'%a * 3
print(func())
執行結果:
執行結果是2執行結果是2執行結果是2
如果return關鍵字後面有運算,要括號括起來,否則會出現多重輸出
面向物件三大特徵之多型
# 什麼是多型?
一種事物的多種形態
eg:
植物>>>草本植物、木本植物、禾本植物
# 多型性
str,dict,tuple,set是不同的資料型別,他們的類也是不同
但是統計長度的方法都叫len,這就是多型
eg:
class Cat(object):
def call(self):
print('貓叫了')
class Dog(object):
def call(self):
print('狗叫了')
class Pig(object):
def call(self):
print('豬叫了')
obj1 = Cat()
obj2 = Dog()
obj3 = Pig()
obj1.call() # 貓叫了
obj2.call() # 狗叫了
obj3.call() # 豬叫了
'''
有相同操作的類,在定義這種操作時,應統一命名,生成不同的物件後,用不同的物件呼叫同一個方法名實現不同類裡的操作
面向物件的多型性也需要python程式設計師自己去遵守
'''
# 雖然python推崇的是自由 但是也提供了強制性的措施來實現多型性(不推薦使用)
eg:
import abc
class Animal(object,metaclass=abc.ABCMeta):
@abc.abstractmethod # 這個語法糖使用後,在繼承這個類時,必修要實現下面的方法
def call(self):
pass
class Cat(Animal):
def aa(self):
print('aa')
class Dog(Animal):
def call(self):
pass
def aa(self):
print('aa')
# obj1 = Cat()
# obj1.aa() # TypeError: Can't instantiate abstract class Cat with abstract methods call
obj2 = Dog()
obj2.aa() # aa
面向物件之反射
# 什麼是反射
專業解釋:指程式可以訪問、檢測和修改本身狀態或者行為的一種能力
大白話:其實就是通過字串來操作物件的資料和功能
# 反射需要掌握的四個方法
hasattr():判斷物件是否含有字串對應的資料或者功能
getattr():根據字串獲取對應的變數名或者函式名
setattr():根據字串給物件設定鍵值對(名稱空間中的名字)
delattr():根據字串刪除物件對應的鍵值對(名稱空間中的名字)
# 反射的實際應用
# 編寫小程式,判斷物件中是否有指定的名字,有則取出展示
class Student(object):
school = '家裡蹲大學'
obj1 = Student()
res = input('請輸入欄位').strip()
if hasattr(obj1, res): # 如果obj1物件裡面有欄位,返回Ture
name = getattr(obj1, res) # 獲取字串對應變數名或函式名
if callable(name): # 如果可呼叫
print('類中有一個功能%s'%res,obj1.name())
else:
print('類中有一個變數%s'%res,obj1.name)
else:
print('沒找到')
setattr(obj1, 'name','petter' ) # 建立新名字
delattr(obj1,'school') # 刪除名字