天天看點

python學習(十六)——多态、封裝、反射、、動态導入子產品、類内置attr方法

一、多态

# 不同的執行個體調用同樣的方法,産生不同的結果
# 多态來自繼承
class H2O:
    def __init__(self,name,temperature):
        self.name=name
        self.temperature=temperature
    def turn_ice(self):
        if self.temperature < 0:
            print('[%s]溫度太低結冰了' %self.name)
        elif self.temperature > 0 and self.temperature < 100:
            print('[%s]液化成水' %self.name)
        elif self.temperature > 100:
            print('[%s]溫度太高變成了水蒸氣' %self.name)
    def aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(self):
        pass

class Water(H2O):
    pass
class Ice(H2O):
    pass
class Steam(H2O):
    pass

w1=Water('水',25)
i1=Ice('冰',-20)
s1=Steam('蒸汽',3000)

# w1.turn_ice()
# i1.turn_ice()
# s1.turn_ice()

def func(obj):
    obj.turn_ice()

func(w1)  #---->w1.turn_ice()
func(i1)  #---->i1.turn_ice()
# def func(obj):
#     obj.turn_ice()
#
# func(w1)
# func(i1)
# func(s1)
           

二、封裝

# 第一層封裝:類就是麻袋,本身是一種封裝
# 第二層封裝: _ (單下劃線)對外部隐藏,隻能内部使用--- 僅僅是約定,仍然可以通路到
#             __ (雙下劃線)python會對其重命名為--- _People__star
# 第三層封裝:隻在内部使用,外部無法調用到,并且提供一個接口

#----------------------------封裝一--------------------------------
class People:
    __star='earth111111111111'
    __star1='earth111111111111'
    __star2='earth111111111111'
    __star3='earth111111111111'
    def __init__(self,id,name,age,salary):
        print('----->',self.__star)
        self.id=id
        self.name=name
        self.age=age
        self.salary=salary

    def get_id(self):
        print('我是私有方法啊,我找到的id是[%s]' %self.id)

    #通路函數
    def get_star(self):
        print(self.__star)



p1=People('123123123123','alex','18',100000000)
# print(p1.__star)
print(People.__dict__)
# print(p1.__star)
print(p1._People__star)
#
# p1.get_star()
p1.get_star()

#----------------------------封裝示例2------------------------------------------
class Room:
    def __init__(self,name,owner,width,length,high):
        self.name=name
        self.owner=owner
        self.__width=width       # 最開始的時候不要用下劃線開頭
        self.__length=length
        self.__high=high

    def tell_area(self): # 此時我們想求的是面積 --接口函數(不推薦)
        return self.__width * self.__length *self.__high

    def tell_width(self):
        return self.__width


r1=Room('衛生間','alex',100,100,10000)

# arear=r1.__width * r1.__length
print(r1.tell_area())
           

三、反射\自省

1、四個自省函數

# 類和對象都适用
# 判斷object中有沒有一個叫name字元串對應的方法或函數
hasattr(object, name)

# 找名字或者方法函數,default是判斷為False時輸出資訊
hasattr(object, name, default)

# 修改
setattr(x, y, v)

# 删除
delattr(x, y)


class BlackMedium:
    feture='Ugly'
    def __init__(self,name,addr):
        self.name=name
        self.addr=addr

    def sell_hourse(self):
        print('【%s】 正在賣房子' %self.name)

    def rent_hourse(self):
        print('【%s】 正在租房子' % self.name)

b1=BlackMedium('abc','rb')
print(hasattr(b1,'name'))
           

2、反射的使用

# 可插拔式設計
#--------------------------使用者------------------------------
from ftp_client import FtpClient

f1=FtpClient('1.1.1.1')
# f1.put()

if hasattr(f1,'put'):
    func_get=getattr(f1,'put')
    func_get()
else:
    print('其他的邏輯')

#-------------------------用戶端-------------------------------
class FtpClient:
    'ftp用戶端,但是還沒有實作具體的功能'
    def __init__(self,addr):
        print('正在連接配接伺服器[%s]' %addr)
        self.addr=addr
# 後面實作的功能
    # def put(self):
    #     print('正在上傳檔案')
           

三、動态導入子產品

module_t=__import__('m1.t') # 導入子產品隻導入了m1
print(module_t)
module_t.t.test1()

import  importlib
m=importlib.import_module('m1.t') #導入例如m1.t
print(m)
m.test1()
m._test2()

#---------------------當導入全部時,_開頭的不能導入---------------------
from m1.t import *
# from m1.t import test1,_test2

test1()
_test2()  #出錯
           

四、類的内置attr屬性

# 不重寫就用預設的,重寫就用重寫的
class Foo:
    x = 1
    def __init__(self, y):
        self.y = y

    def __getattr__(self, item):   # 用處較多
        print('執行__getattr__')
    
    def __delattr__(self, item):
        print('删除操作')
        self.__dict.pop(item)

    def __setattr__(self, key, value):
        print('__setattr__執行')
        # self.key = value    無限遞歸,錯誤
        self.__dict__[key] = value


f1 = Foo(10)
# 調用一個不存在的屬性時執行
print(f1.y)
print(getattr(f1, 'y')) # len(str)--->str.__len__()
f1.asdasd # 執行__getattr__
# 删除時執行
del f1.y

print(f1.__dict__)# 添加成功

           

五、二次加工标準類型(包裝、授權)

#------------------------------包裝------------------------------------
class List(list):
    def append(self, p_object):
        if type(p_object) is str:
            # self.append(p_object)
            super().append(p_object)
        else:
            print('隻能添加字元串類型')

    def show_midlle(self):
        mid_index=int(len(self)/2)
        return self[mid_index]


# l2=list('hell oworld')
# print(l2,type(l2))

l1=List('helloworld')
# print(l1,type(l1))
# print(l1.show_midlle())
l1.append(1111111111111111111111)
l1.append('SB')
print(l1)

#-----------------------------------授權--------------------------------
# 通過__getattribute__實作
import time
class FileHandle:
    def __init__(self,filename,mode='r',encoding='utf-8'):
        # self.filename=filename
        self.file=open(filename,mode,encoding=encoding)
        self.mode=mode
        self.encoding=encoding
    def write(self,line):
        print('------------>',line)
        t=time.strftime('%Y-%m-%d %X')
        self.file.write('%s %s' %(t,line))

    def __getattr__(self, item):
        # print(item,type(item))
        # self.file.read
        return getattr(self.file,item)

f1=FileHandle('a.txt','w+')
# print(f1.file)
# print(f1.__dict__)
# print('==>',f1.read) #觸發__getattr__
# print(f1.write)
f1.write('1111111111111111\n')
f1.write('cpu負載過高\n')
f1.write('記憶體剩餘不足\n')
f1.write('硬碟剩餘不足\n')
# f1.seek(0)
# print('--->',f1.read())