博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python(面向对象5——高级)
阅读量:6858 次
发布时间:2019-06-26

本文共 6936 字,大约阅读时间需要 23 分钟。

一 isinstance(obj,cls)和issubclass(sub,super)

isinstance(obj,cls)检查是否obj是否是类 cls 的对象1 class Foo(object):2     pass3  4 obj = Foo()5  6 isinstance(obj, Foo)issubclass(sub, super)检查sub类是否是 super 类的派生类1 class Foo(object):2     pass3  4 class Bar(Foo):5     pass6  7 issubclass(Bar, Foo)
View Code

二 反射(hasattr getattr setattr)

1 什么是反射

反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。

2 python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)

四个可以实现自省的函数

下列方法适用于类和对象(一切皆对象,类本身也是一个对象)

hasattr(object,name)判断object中有没有一个name字符串对应的方法或属性getattr(object, name, default=None)setattr(x, y, v)delattr(x, y)#应用举例class BlackMedium:    feature='Ugly'    def __init__(self,name,addr):        self.name=name        self.addr=addr    def sell_house(self):        print('%s 黑中介卖房子啦,傻逼才买呢,但是谁能证明自己不傻逼' %self.name)    def rent_house(self):        print('%s 黑中介租房子啦,傻逼才租呢' %self.name)b1=BlackMedium('万成置地','回龙观天露园')#检测是否含有某属性print(hasattr(b1,'name'))print(hasattr(b1,'sell_house'))#获取属性n=getattr(b1,'name')print(n)func=getattr(b1,'rent_house')func()# getattr(b1,'aaaaaaaa') #报错print(getattr(b1,'aaaaaaaa','不存在啊'))#设置属性setattr(b1,'sb',True)setattr(b1,'show_name',lambda self:self.name+'sb')print(b1.__dict__)print(b1.show_name(b1))#删除属性delattr(b1,'addr')delattr(b1,'show_name')delattr(b1,'show_name111')#不存在,则报错print(b1.__dict__)#四个方法的使用演示#类也是对象class Foo(object):     staticField = "old boy"     def __init__(self):        self.name = 'wupeiqi'     def func(self):        return 'func'     @staticmethod    def bar():        return 'bar' print getattr(Foo, 'staticField')print getattr(Foo, 'func')print getattr(Foo, 'bar')#反射当前模块成员import sysdef s1():    print 's1'def s2():    print 's2'this_module = sys.modules[__name__]hasattr(this_module, 's1')getattr(this_module, 's2')
View Code

3 为什么用反射之反射的好处

好处一:实现可插拔机制

可以事先定义好接口,接口只有在被完成后才会真正执行,这实现了即插即用,这其实是一种‘后期绑定’,什么意思?即你可以事先把主要的逻辑写好(只定义接口),然后后期再去实现接口的功能。

好处二:动态导入模块(基于反射当前模块成员)

三 __setattr__,__delattr__,__getattr__

#三者的用法演示class Foo:    x=1    def __init__(self,y):        self.y=y    def __getattr__(self, item):        print('----> from getattr:你找的属性不存在')    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)#__setattr__添加/修改属性会触发它的执行f1=Foo(10)print(f1.__dict__) # 因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值,除非你直接操作属性字典,否则永远无法赋值f1.z=3print(f1.__dict__)#__delattr__删除属性的时候会触发f1.__dict__['a']=3#我们可以直接修改属性字典,来完成添加/修改属性的操作del f1.aprint(f1.__dict__)#__getattr__只有在使用点调用属性且属性不存在的时候才会触发f1.xxxxxx
三者的用法演示

(无限递归是赋值/删除的操作本身,又触发了赋值/删除操作,不断循环)

四 二次加工标准类型(包装)

包装:python为大家提供了标准数据类型,以及丰富的内置方法,其实在很多场景下我们都需要基于标准数据类型来定制我们自己的数据类型,新增/改写方法,这就用到了我们刚学的继承/派生知识(其他的标准类型均可以通过下面的方式进行二次加工)

#二次加工标准类class List(list): #继承list所有的属性,也可以派生出自己新的,比如append和mid    def append(self, p_object):        ' 派生自己的append:加上类型检查'        if not isinstance(p_object,int):            raise TypeError('must be int')        super().append(p_object)    @property    def mid(self):        '新增自己的属性'        index=len(self)//2        return self[index]l=List([1,2,3,4])print(l)l.append(5)print(l)# l.append('1111111') #报错,必须为int类型print(l.mid)#其余的方法都继承list的l.insert(0,-123)print(l)l.clear()print(l)#clear加权限限制class List(list):    def __init__(self,item,tag=False):        super().__init__(item)        self.tag=tag    def append(self, p_object):        if not isinstance(p_object,str):            raise TypeError        super().append(p_object)    def clear(self):        if not self.tag:            raise PermissionError        super().clear()l=List([1,2,3],False)print(l)print(l.tag)l.append('saf')print(l)# l.clear() #异常l.tag=Truel.clear()
View Code

五 __getattribute__

class Foo:    def __init__(self,x):        self.x=x    def __getattribute__(self, item):        print('不管是否存在,我都会执行')f1=Foo(10)f1.xf1.xxxxxx#_*_coding:utf-8_*___author__ = 'Linhaifeng'class Foo:    def __init__(self,x):        self.x=x    def __getattr__(self, item):        print('执行的是我')        # return self.__dict__[item]    def __getattribute__(self, item):        print('不管是否存在,我都会执行')        raise AttributeError('哈哈')f1=Foo(10)f1.xf1.xxxxxx#当__getattribute__与__getattr__同时存在,只会执行__getattrbute__,除非__getattribute__在执行过程中抛出异常AttributeError
View Code

六 __str__,__repr__,__format__

改变对象的字符串显示__str__,__repr__

自定制格式化字符串__format__

#_*_coding:utf-8_*___author__ = 'Linhaifeng'format_dict={    'nat':'{obj.name}-{obj.addr}-{obj.type}',#学校名-学校地址-学校类型    'tna':'{obj.type}:{obj.name}:{obj.addr}',#学校类型:学校名:学校地址    'tan':'{obj.type}/{obj.addr}/{obj.name}',#学校类型/学校地址/学校名}class School:    def __init__(self,name,addr,type):        self.name=name        self.addr=addr        self.type=type    def __repr__(self):        return 'School(%s,%s)' %(self.name,self.addr)    def __str__(self):        return '(%s,%s)' %(self.name,self.addr)    def __format__(self, format_spec):        # if format_spec        if not format_spec or format_spec not in format_dict:            format_spec='nat'        fmt=format_dict[format_spec]        return fmt.format(obj=self)s1=School('oldboy1','北京','私立')print('from repr: ',repr(s1))print('from str: ',str(s1))print(s1)'''str函数或者print函数--->obj.__str__()repr或者交互式解释器--->obj.__repr__()如果__str__没有被定义,那么就会使用__repr__来代替输出注意:这俩方法的返回值必须是字符串,否则抛出异常'''print(format(s1,'nat'))print(format(s1,'tna'))print(format(s1,'tan'))print(format(s1,'asfdasdffd'))#-----------------------------------------------------------------------#自定义format练习date_dic={    'ymd':'{0.year}:{0.month}:{0.day}',    'dmy':'{0.day}/{0.month}/{0.year}',    'mdy':'{0.month}-{0.day}-{0.year}',}class Date:    def __init__(self,year,month,day):        self.year=year        self.month=month        self.day=day    def __format__(self, format_spec):        if not format_spec or format_spec not in date_dic:            format_spec='ymd'        fmt=date_dic[format_spec]        return fmt.format(self)d1=Date(2016,12,29)print(format(d1))print('{:mdy}'.format(d1))#------------------------------------------------------------------#issubclass和isinstance#_*_coding:utf-8_*___author__ = 'Linhaifeng'class A:    passclass B(A):    passprint(issubclass(B,A)) #B是A的子类,返回Truea1=A()print(isinstance(a1,A)) #a1是A的实例
View Code

七 __setitem__,__getitem,__delitem__

class Foo:    def __init__(self,name):        self.name=name    def __getitem__(self, item):        print(self.__dict__[item])    def __setitem__(self, key, value):        self.__dict__[key]=value    def __delitem__(self, key):        print('del obj[key]时,我执行')        self.__dict__.pop(key)    def __delattr__(self, item):        print('del obj.key时,我执行')        self.__dict__.pop(item)f1=Foo('sb')f1['age']=18f1['age1']=19del f1.age1del f1['age']f1['name']='alex'print(f1.__dict__)
View Code

 

转载于:https://www.cnblogs.com/zihe/p/7131511.html

你可能感兴趣的文章
Flask 第四篇 Flask 中的模板语言 Jinja2 及 render_template 的深度用法
查看>>
PHP输出缓冲
查看>>
Windows2003上使用IIS7 Express使用FastCgi运行php
查看>>
安装程序时 “向数据库写入数据时发生错误!”
查看>>
图文:高春辉和他的网站梦
查看>>
网页之间的参数传递
查看>>
HTML5 做波形运动的小球
查看>>
初步学习Django-第四篇:views.PY文件详解
查看>>
OAuth2简易实战(四)-Github社交联合登录
查看>>
Netty学习大纲
查看>>
OC中的私有方法
查看>>
20060427: 部分汉化Together Workflow Editor
查看>>
CentOS中配置VNC Server
查看>>
Table '.\mysql\proc' is marked as crashed and should be repaired 报错
查看>>
分享几段JavaScript
查看>>
C++中的多态和Objective-C中的“多态”
查看>>
js基础五
查看>>
构建执法阅读笔记01
查看>>
【Update】C# 批量插入数据 SqlBulkCopy
查看>>
剑指offer:合并两个排序的链表
查看>>