第六篇:面向对象高级

1、反射
面向对(OOP)的优点:
面向对象是一种更高级别的结构化编程,有两点好处:
通过封装明确内外;通过继承+多态在语言层面支持了归一化设计。
泛化/特化
泛化:基于继承,表示所有子类与父类有一样的特点
特化:所有子类的自定义
自省/反射
自省也称为反射,这个性质展示了某对象是如何在运行期间获得自身信息的,
主要指程序可以访问、检测、修改它本身状态和行为的一种能力。
四个可以实现自省的函数,只用于类和对象
hasattr(obj,name)				判断obj对象是否能调用到name字符串的方法或属性
getattr(obj,name,default)		从obj对象中调用name字符串并得到结果
setattr(obj,x,y)				给obj对象设置属性,属性名x,属性值为y
delattr(obj,name)				从obj对象中删除name方法或者属性

class Bm():
    feture = 'ugly'
    def __init__(self,name,addr):
        self.name = name
        self.addr = addr
    def sel_hourse(self):
        print('不买')
    def rent_hourse(self):
        print('不租')
b1 = Bm('中介','上海')
print(b1.__dict__)
b1.sel_hourse()

print(hasattr(b1,'name'))		实质就是判断能否调用到name字符串属性或者方法
print(hasattr(b1,'sel_hourse'))

print(getattr(b1,'name'))
print(getattr(b1,'sel_hourse'))	
print(getattr(b1,'sel','不存在'))	可以设置默认值,防止没有报错

setattr(b1,'sb','true')
setattr(b1,'name','黑的')
setattr(b1,'func',lambda x:x+1)		增加和修改数据属性和函数属性
print(b1.__dict__)

# del b1.name
delattr(b1,'name')
print(b1.__dict__)

反射的应用场景:两个人(A,B)合作一个项目,A需要B的模块,但B没有写,此时可以利用反射
在调用前判断是否由此项功能,如果有调用,没有执行其他功能
即:实现定义好接口,接口只有在被完全执行时才会真正的执行,实现了即插即用。
import sys
obj = sys.modules[__name__]			
print(hasattr(obj,'x'))				检测自己文件是否存在某一属性


2、模块导入
from web1.web2 import t
t.test()
from web1.web2.t import *
test()
from web1 import web2.t				注意:这种导入是错误的
模块名是字符串时:
module_t = __import__('web1.web2.t')不管嵌套多少层,返回的都是最顶层模块
print(module_t)						module_t = web1
module_t.web2.t.test()

import importlib
m = importlib.import_module('web1.web2.t')	定位到调用模块
print(m)							m = t
m.test()


3、类的attr属性
class Foo():
	x = 1
	def __init__(self,y):
		self.y = y
	def __getattr__(self,item):
		print('你要查的属性不存在')
	def __setattr__(self,key,value):
		print('--from setattr')
		#self.key = value			注:这种设置会导致无限递归,错误
		self.__dict__[key] = value	应该这样设置
	def __delattr__(self,item)
		print('---from delattr')
		#del self.item				注:这种删除会导致无限递归,错误
		self.__dict__.pop(item)		这样删除正确

__getattr__:查找的属性不存在时会执行该函数;
__setattr__\__delattr__:设置属性或者删除属性时会执行函数。
f1 = foo(10)						实例化就是设置属性(赋值)的过程,会执行setattr
f1.z = 3
f1.y
f1.ssssss							查找的属性不存在执行__getattr__
del f1.x

4、包装/授权
继承的方式完成包装:
python中提供了标准数据类型和很多内置方法,但是在很多场景下需要根据标准数据类型来
定制我们自己的数据类型,新增/改写方法,这就利用到了继承和派生。
class List(list):
	def append(self,obj):
		if type(obj) is str:
			super().append(obj)
	@property
	def mid(self):
		index = len(self)//2
		return self[index]
l = List('hello')
l.append('23')
print(l.mid)
组合的方式完成授权:
授权是包装的一个特性,包装一个类型通常是对已存在的类型进行定制(新建、修改和删除原功能),
其他保持原样。授权是已更新的功能由新类的某部分处理,但已存在的功能授权给对象的默认属性。
授权的关键:__getattr__方法
class Handfile():
	def __init__(self,filename,mode,encoding='utf8')
		self.file = open(filename,mode,encoding)
		self.mode = mode
		self.encoding = encoding
	def __getattr__(self,item)
		return getattr(self.file,item)
	def write(self,line):
		t = time.strftime('%Y-%m-%d %X')
		self.file.write('%s %s'%(t,line))
f1 = Handfile('a.txt','a')
f1.read
f1.write('内存不足')

5isinstance(obj,cls)/issubclass(sub,super)/__getattrbute__
isinstance(obj,cls):判断对象是否由类实例化而来
issubcass(sub,super):判断sub是否是super的子类
__getattrbute__:了解即可和__getattr__配合使用时的情况
class Foo():
    def __init__(self,x):
        self.x = x
    def __getattr__(self, item):
        print('执行的是getattr')
    def __getattribute__(self, item):
        print('执行的是getattribute')
        raise AttributeError('抛出异常')
f1 = Foo(10)
f1.x				/			
f1.xxxxxx
属性不管存在不存在,输出结果都是'执行的是getattribute''执行的是getattr',这是因为
不管属性是否存在都会执行__getattribute__方法,raise AttributeError('抛出异常')会
导致出现异常,而__getattr__的存在,接收了异常,因此不影响程序的运行。

5、item系列
item和attr效果一样,仅仅是调用方式不一样,item:通过字典,attr:通过.
class Foo:
    def __getitem__(self, item):
        print('getitem',item)
        return self.__dict__[item]
    def __setitem__(self, key, value):
        print('setitem')
        self.__dict__[key]=value
    def __delitem__(self, key):
        print('delitem')
        self.__dict__.pop(key)
f1 = Foo()
f1['name']='egon'
print(f1.__dict__)
print(f1['name'])			查看属性,不存在报错
del f1['name']
print(f1.__dict__)

6strrepr和自定制format
都属于包装范畴,对原有的功能进行编辑。
format_dic = {
    'ymd':'{0.year}{0.mon}{0.day}',
    'm-d-y':'{0.mon}{0.day}{0.year}'
}
class Date():
    def __init__(self,year,mon,day):
        self.year = year
        self.mon = mon
        self.day = day
    def ff(self,format_spec):
    # def __format__(self,format_spec):
        print('-----')
        fm = format_dic[format_spec]
        return fm.format(self)

d1 = Date(2021,7,5)
print(d1.ff('ymd'))
# print(d1.__format__('m-d-y'))

7、slots和doc属性
slots是一个类变量,变量值可以是列表、元组等可迭代对象,意味着其实例对象只有数据属性
为了节省内存空间,用__slots__来取代实例的__dict__属性
class Foo:
    __slots__ = ['name','age']
f1 = Foo()
f1.name = [1,2,3]
f1.age = 18
print(f1.name)
print(f1.age)
print(f1.__slots__)

class Foo():
    '文档信息'
    pass
class Bar(Foo):
    pass
print(Foo.__dict__)
print(Bar.__dict__)
注:文档属性无法被继承

8、module、name和析构方法
from lib.aa import C
c1 = C()
print(c1.__module__)
print(c1.__class__)
c1的模块来自类的模块
析构方法:当对象在内存中被释放时,自动触发进行,
析构函数的调用是解释器进行垃圾回收自动触发的。
class Foo():
    def __init__(self,name):
        self.name = name
    def __del__(self):
        print('我执行了')
f1 = Foo('alex')
f2 = Foo('ssss')
del f1		只有删除实例f1时,才会触发__del__函数,删除实例的某个属性则不会
print(----)	当打印完成后整个程序运行结束,f2的内存被释放也会触发__del__函数

9、描述符
描述符:至少实现了__get__()\__set__()\__delete__()中的一个,也称为描述符协议
__get__()		:被代理属性调用时触发
__set__()		:被代理属性赋值时触发
__delete__()	:被代理属性删除时触发
作用:用来代理另外一个类的类属性
描述符分为数据描述符(至少实现了__get__和__set__)和非数据描述符(没有实现__set__)
注意:必须把描述符定义成这个类的类属性,不能定义到构造函数中;
要严格遵循优先级:类属性>数据描述符>实例属性>非数据描述符>找不到
class Foo:
    def __get__(self, instance, owner):
        print('get方法')
    def __set__(self, instance, value):
        print('set')
        # print(self,instance,value)
        # instance.__dict__['x'] = value
    def __delete__(self, instance):
        print('delete')
        instance.__dict__.pop('x')

class Bar:
    x = Foo()
    def __init__(self,name):
        self.name = name
print(Bar./x)
Bar.x = 333
b1 = Bar('ales')
b1.x
b1.x = 'ss'
print(b1.__dict__)
del b1.x
print(b1.__dict__)
b1.ddddd
描述符的应用:对传入的参数进行自定制类型
class Typed:
    def __init__(self,key,ex_type):
        self.key = key
        self.ex_type = ex_type
    def __get__(self, instance, owner):
        print('get方法')
        return instance.__dict__[self.key]
    def __set__(self, instance, value):
        print('set方法')
        if not instance or type(value) is not str:
            raise TabError('%s传入的不是%s'%(self.key,self.ex_type))
        instance.__dict__[self.key] = value
    def __delete__(self, instance):
        print('delete方法')
        instance.__dict__.pop(self.key)
class People:
    name = Typed('name',str)
    def __init__(self,name,age,salary):
        self.name = name
        self.age = age
        self.salary =salary
# p1 = People('alex',29,13000)
p1 = People(111,29,10100)
# print(p1.name)
p1.name = 'lili'

利用描述符自定制property
class La:
    def __init__(self,func):
        print(func)
        self.func = func
        print('---->')
    def __get__(self, instance, owner):
        print('get方法')
        if instance is None:
            return self
        res = self.func(instance)
        setattr(instance,self.func.__name__,res)
        # print(self.func.__name__)
        return res
class Room:
    def __init__(self,name,w,l):
        self.name = name
        self.w = w
        self.l = l
    @La             #area = La(area)
    def area(self):
        return self.w*self.l
r1 = Room('alex',1,1)
# print(Room.__dict__)
print(r1.area)

property补充
class Foo:
    @property
    def AAA(self):
        print('get的时候运行我')
    @AAA.setter
    def AAA(self,val):
        print('set的时候运行',val)
    @AAA.deleter
    def AAA(self):
        print('删除的时候运行')
f1 =Foo()
# f1.AAA
# f1.AAA = 123
print(Foo.__dict__)
del f1.AAA
# print(f1.__dict__)
print(Foo.__dict__)
注:只有property静态属性不能赋值和删除,如果需要,必须设置需加@AAA.setter和@AAA.deleter
并且只有在属性AAA定义property之后才能定义AAA.setter和AAA.deleter

10、__call__\__next__\__iter__
__call__:对象后面加括号,触发执行。
class Foo:
    def __call__(self, *args, **kwargs):
        print('执行了')
f1 = Foo()
f1()
定义一个类,类实例的对象能够实现可迭代
class Foo:
    def __init__(self,n):
        self.n = n
    def __iter__(self):
        return self
    def __next__(self):
        if self.n == 13:
            raise StopIteration('出现异常')
        else:
            self.n +=1
        return self.n
f1 = Foo(10)
print(f1.__iter__())

11、上下文管理协议
上下文管理操作即with语句,为了让一个对象能够兼容with语句,必须在这个对象中声明
__enter__和__exit__方法。
class Foo:
    def __init__(self,name):
        self.name = name
    def __enter__(self):
        print('执行enter')
        return self
    def __exit__(self, exc_type, exc_val, exc_tb):
        print('执行exit')
        return True		当句举存在时,就把异常吃掉,不会报错,但是异常后的with的代码块
						就不在执行,但会继续执行with外后面的代码		
with Foo('a.txt') as f:	触发__enter__函数,拿到的结果赋值给f
    print(f)			
    print(f.xxxxxx)with中代码出现错误时,会直接触发__exit__
    # print(f.name)		当没有异常时,with下的代码运行结束触发__exit__.
    print('-------->')

12、类的装饰器
给类添加数据属性功能
def Typed(**kwargs):
    def deco(obj):
        print(kwargs)
        print(obj)
        for key,val in kwargs.items():
            setattr(obj,key,val)
        return obj
    print(kwargs)
    return deco
@Typed(x=1,y=2,z=3)	Typed(x=1,y=2,z=3)-->deco	@deco----->Foo=deco(Foo)
class Foo:
    pass
print(Foo.__dict__)
设置参数类型功能(描述符+装饰器)
class Typed:
    def __init__(self,key,ex_type):
        self.key = key
        self.ex_type = ex_type
    def __get__(self, instance, owner):
        print('get方法')
        return instance.__dict__[self.key]
    def __set__(self, instance, value):
        print('set方法')
        if not instance or type(value) is not str:
            raise TabError('%s传入的不是%s'%(self.key,self.ex_type))
        instance.__dict__[self.key] = value
    def __delete__(self, instance):
        print('delete方法')
        instance.__dict__.pop(self.key)

def deco(**kwargs):
    def wapper(obj):
        for k,v in kwargs.items():    
            setattr(obj,k,Typed(k,v))
        return obj
@deco
class People():
    # name = Typed('name', str)
    # age = Typed('age',int)
    # salary = Typed('salary',float)
    def __init__(self,name,age,salary):
        self.name = name
        self.age = age
        self.salary = salary

13、元类metaclass
元类是类的类,是类的模板,元类是用来控制如何创建类的,正如类是创建对象的模板
元类的实例是类,类的实例是对象
python中任何class定义的类都是type实例化的对象
一个类没有声明自己的元类,那么他的元类就是type
# 定义类的两种方式:
class Foo:
    def __init__(self):
        pass
print(Foo)

FFo = type('FFo',(object,),{'x':1})		#类名,继承的父类(可以多个),类的属性字典
print(FFo)



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值