面向對象進階一

反射

通過字符串的形式操作對象相關的屬性
四個可以實現自省的函數:hasattr、getattr、setattr、delattr

class People:
    country = 'China'
    def __init__(self,Name):
        self.name = Name

hasattr

p = People('spring')
print(p.__dict__)
print(hasattr(p,'country'))
print(hasattr(p,'__doc__'))
print(hasattr(p,'name'))
print(hasattr(p,'__init__'))
print(hasattr(People,'country'))

getattr

res = getattr(p,'country')
print(res)
res = getattr(p, 'age', '沒有設定age')
print(res)
res = getattr(People, 'country')
print(res)

setattr

p.age = 18
print(p.age)
print(p.__dict__)
setattr(p, 'age', 28)
print(getattr(p, 'age'))
setattr(People,'country','USA')
print(getattr(People,'country'))

delattr

print(hasattr(p, 'age'))
delattr(p, 'age')  #res = getattr(p, 'age', '沒有設定age') # 找不到可以設個返回值,不設定找不到會報錯。

print(hasattr(p, 'age'))

使用反射的好處:


1.通過字符串來導入模塊,動態導入模塊

#不推薦這個
m = __import__('time')
print(m.time())

#推薦方法
import importlib
m = importlib.import_module('time')
print(m.time())

2.可插拔機制,實現可插拔機制

#module

class FtpClient:
    def __init__(self, addr):
        print('正在連接服務器[%s]'%addr)
        self.addr = addr
    # def get(self):
    #     print('get')
from module import FtpClient
f1 = FtpClient('192.168.1.1')
if hasattr(f1, 'get'):
    func_get = getattr(f1, 'get')
    func_get()
else:
    print('---->不存在此方法')

反射當前模塊屬性(成員)

import sys
x = 22
class Foo:
    pass

def s1():
    print('s1')

def s2():
    print('s2')
this_module = sys.modules[__name__]
print(this_module)
print(hasattr(this_module,'s1'))
print(this_module.s1)

__setattr__, __delattr__, __getattr__

#__setattr__, __delattr__, __getattr__

class Foo:
    def __init__(self,Name):
        self.name = Name

    def __setattr__(self, key, value):
        print('---setattr-----key: %s value: %s'%(key, value))
        self.__dict__[key] = value

    def __delattr__(self, item):
        print('------delattr-----item: %s'%item)
        # self.__dict__.pop(item)
        del self.__dict__[item]

    def __getattr__(self, item):
        print('----getattr----item: %s'%item)


#setattr
cc = Foo('spring')
print(cc.__dict__)
print(cc.name)
cc.__dict__['age'] = 166
print(cc.age)

#delattr
print(cc.__dict__)
del cc.age
print(cc.__dict__)

#getattr  屬性不存在纔會運行 和getattr() 結合使用
print('!'*100)
print(cc.zz)

定製自己的數據類型

1 基於繼承標準的數據類型來定製數據類型

class List(list):
    def append(self, object: int):
        if not isinstance(object,int):
            raise TypeError('must be int')
        super().append(object)
        #list.append(self,object)

    def insert(self, index: int, object: int):
        if not isinstance(object, int):
            raise TypeError('must be int')
        super().insert(index, object)

cc = List([1,2,3])
print(cc)
#cc.append('3')
cc.append(33)
print(cc)

cc.insert(0,22)
print(cc)

2 授權的方式定製數據類型

import time
class Open:
    def __init__(self, file_path, m='r', encode='utf-8'):
        self.x = open(file_path, mode=m, encoding=encode)
        self.file_path = file_path
        self.encoding = encode
    def write(self, line):
        print('寫入: ', line)
        t = time.strftime('%Y-%m-%d %X')
        self.x.write('%s %s'%(t, line))
    def __getattr__(self, item):
        return getattr(self.x, item)


f = Open('a.txt', m='a+')
f.x.write('sss\n')
f.write('zzz\n')
f.seek(0)
print(f.read())



class List:
    def __str__(self):
        return str(self.cont)
    def __init__(self,cont):
        self.cont = cont
    def append(self,value):
        if not isinstance(value, str):
            raise TypeError('must be str')
        self.cont.append(value)
    @property
    def mid(self):
        if len(self.cont) == 1 or len(self.cont) == 0:  #如果list爲口活着只有一個元素返回list本身
            return self.cont
        a, b = divmod(len(self.cont), 2)
        if b != 0:
            return self.cont[a+1]    #如果奇數返回中間數
        else:
            return self.cont[a:a+2]  #如果是偶數返回中間的2個數

    def __getattr__(self, item):     #其餘方法都使用list自帶
        return getattr(self.cont,item)

cc = List(['b','a','c','d'])
print(cc.mid)
cc.append('z')
cc.sort()
print(cc)


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章