python之路--day23--面向对象高级
Posted 木夂各
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python之路--day23--面向对象高级相关的知识,希望对你有一定的参考价值。
内置函数补充:
isinstance:判断对象是不是类的实例
issubclass:判断类是否是一个类的子类
1,反射
指程序可以访问,检测,修改它本身状态或行为的一种能力(自省)
1.1,python面向对象中的反射:通过字符串的形式操作对象相关的属性
1.1.1 四个可以实现自省的函数
hasattr(object,name) 判断object中有没有一个name字符串对应的方法或属性,返回布尔值 class test(): name = ‘egon‘ def run(self): return ‘Helloword‘ t = teat() print(hasattr(t,‘run‘)) True print(hasattr(t,‘Helloword‘)) False
class teat(): name = ‘egon‘ def run(self): return ‘helloword‘ t= test() getattr(t,‘name‘) #获取name属性。存在就打印出来 getattr(t,‘run‘) #获取run方法,存在就打印方法的内存地址,,加括号可以直接运行 getattr(t,‘age’) #获取一个不存在的属性。报错 getattr(t,‘age‘,‘18‘) #若属性不存在,返回一个默认值
给对象的属性赋值,若属性不存在,就先创建在赋值 class test(): name="xiaohua" def run(self): return "HelloWord" t=test() hasattr(t,‘age‘) #判断属性是否存在 setattr(t,‘age‘,‘18‘) #为属性赋值,没有返回值 hasattr(t,‘age‘)#属性存在了
删除object的属性,name对应的属性不存在就报错
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‘))
2.__str__方法
print一个类的实例化对象的时候,会执行类下的__str__函数属性
这个方法必须有一个返回值
def People: def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex def __str__(self): return ‘<名字:%s 年龄:%s 性别: %s> %(self.name,self.age,self.sex)
3.__del__方法
在一个类的对象被删除的条件下,类下的__del__方法会自动执行
一般用在程序使用完申请的系统资源之后,释放系统资源
class People: def __init__(self,name.age,sex): self.name= name self.age=age self.sex=sex def __del__(self): #在对象被删除的条件下,自动执行 print(‘__del__‘)
4.exec方法
exec(object,global,local)
object --字符串形式的命令
global--全局作用域,字典形式--存放object内定义的全局名称
local---局部作用域,字典形式--存放object内定义的局部名称
#可以把exec命令的执行当成是一个函数的执行,会将执行期间产生的名字存放于局部名称空间中--前提是被指定为全局名称 g={ ‘x‘:1, ‘y‘:2 } l={} exec(‘‘‘ global x,z x=100 z=200 m=300 ‘‘‘,g,l) print(g) #{‘x‘: 100, ‘y‘: 2,‘z‘:200,......} print(l) #{‘m‘: 300}
5.元类
概念理解:
python中一切都是对象。类本身也是对象。使用class关键字时,python解释器在加载class时创建一个对象(指的是类,而不是类的实例),所以类也是对象,所以:
-
把类赋值给一个变量
-
把类作为函数参数进行传递
-
把类作为函数的返回值
- 把类作为容器类型的元素
class Foo: pass f1 = Foo()#f1是用过Foo类实例化的对象 #type函数可以查看类型,也可以用来查看对象的类 print(type(f1)) # 输出:<class ‘__main__.Foo‘> 表示,obj 对象由Foo类创建 print(type(Foo)) # 输出:<type ‘type‘>
5.1 什么是元类
元类就是类的类
type是python的一个内建元类,用来直接控制生成类,python中任何class定义的类都是type实例化的对象
5.2创建类的两种方式
1,使用class关键字
2, 手动模拟class创建类的过程:将创建类的步骤拆分开,手动去创建
概念理解:
类的三要素:1.类名----class_name = ‘chinses‘
2.类的父类----class_bases = (object,)
3.执行类体代码产生的名字---class_dic
class_body (类体代码使用字符串表示,调用exec方法,得到类体内的名称---没有指定都是局部名称)
""" country=‘China‘ def __init__(self,name,age): self.name=name self.age=age def talk(self): print(‘%s is talking‘ %self.name) """
步骤:1,处理类体代码得到名称空间
2,调用元类type(元类可以自定义)来产生类chinese
Foo=type(class_name,class_bases,class_dic)
#实例化type得到对象Foo,即我们用class定义的类Foo print(Foo) print(type(Foo)) print(isinstance(Foo,type)) ‘‘‘ <class ‘__main__.Chinese‘> <class ‘type‘> True ‘‘‘
5.3 自定义元类控制类的调用
知识储备:__call__,调用对象,会自动触发对象的绑定方法__call__的执行
class Foo: def __call__(self,*args,**keargs): print(‘__call__‘,args,kwargs) #调用对象,会自动触发对象下的绑定方法__call__的执行 #然后将对象本身当做第一个参数传给self,将调用对象时括号内的值传给*args和**kwargs
5.3.1 自定义元类:
步骤1,定义元类,控制类的创建
Foo=type(class_name,class_bases,class_dic) #实例化type得到对象Foo,即我们用class定义的类Foo #上述表达式 等价于 class Foo class Mymeta(type): #继承默认元类的属性 def __init__(self,class_name,class_bases,class_dic): #定制类的创建规则 if "__doc__" not in class_dic or not class_dic.get(‘__doc__‘): raise TypeError(‘必须为类指定文档注释‘) if not class_name.istitle(): raise TypeError(‘类首字母必须大写‘) super(Mymeta,self).__init__(class_name,class_bases,class_dic) #继承type的代码
步骤2,__call__方法的知识。
class People(object,metaclass=type): def __init__(self,name,age): self.name=name self.age=age def __call__(self, *args, **kwargs): print(self,args,kwargs) # 调用类People,并不会出发__call__ obj=People(‘egon‘,18) # 调用对象obj(1,2,3,a=1,b=2,c=3),才会触发对象的绑定方法obj.__call__(1,2,3,a=1,b=2,c=3) obj(1,2,3,a=1,b=2,c=3) #打印:<__main__.People object at 0x10076dd30> (1, 2, 3) {‘a‘: 1, ‘b‘: 2, ‘c‘: 3} #总结:如果说类People是元类type的实例,那么在元类type内肯定也有一个__call__,会在调用People(‘egon‘,18)时触发执行,然后返回一个初始化好了的对象obj
步骤3,自定义元类,控制类的调用(实例化)的过程
class Mymeta(type): #继承默认元类的属性 def __init__(self,class_name,class_bases,class_dic): #定制类的创建规则 if "__doc__" not in class_dic or not class_dic.get(‘__doc__‘): raise TypeError(‘必须为类指定文档注释‘) if not class_name.istitle(): raise TypeError(‘类首字母必须大写‘) super(Mymeta,self).__init__(class_name,class_bases,class_dic) #继承type的代码 def __call__(self, *args, **kwargs): #1,实例化People,产生空对象obj obj = object.__new__(self) #2,调用People下的函数__init__,初始化obj self.__init__(obj,*args,**kwargs) #3,返回初始化之后的obj return obj
单例模式
指的是同一个类实例多长的结果指向同一个对象,用于节省内存空间
如果我们从配置文件中读取配置来进行实例化,在配置相同的情况下,就没有必要重复产生对象浪费内存
#settings.py文件内容如下 HOST=‘1.1.1.1‘ PORT=3306 import setting class Mysql: __instance = None def __init__(self,host,port): self.host = host self.port = port @classmethod def singleton(cls): if not cls.__instance: cls.__instance = cls(setting.HOST,setting.PORT)#产生一个实例化对象 return cls.__instance obj1=Mysql(‘1.1.1.2‘,3306) obj2=Mysql(‘1.1.1.3‘,3307) print(obj1 is obj2) #False obj3=Mysql.singleton() obj4=Mysql.singleton() print(obj3 is obj4) #True
以上是关于python之路--day23--面向对象高级的主要内容,如果未能解决你的问题,请参考以下文章