面向对象进阶
一、isinstance和issubclass内置方法
1、isinstance(obj,cls)
作用:检查是否obj是否是类cls的对象
2、issubclass(sub, super)
作用:检查sub类是否是super类的派生类
二、★反射(自省)
1、定义:
反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。
2、python中的反射:
通过字符串的形式操作对象相关的属性,python中的一切事物都是对象(都可以使用反射)。
3、四个可以实现自省的函数
①hasattr(obj,name):返回obj对象是否具有name所描述的属性
②getattr(obj,name):从obj对象中获取到name所描述的属性
③setattr(obj,name,value):给obj对象设置一个名为name的属性,属性值为value
④delattr(obj,name):从obj对象中删除名为name的属性
⑤反射的应用举例:
class Foo :
static_var = '类的静态变量'
def __init__ (self, name, age) :
self.name = name
self.age = age
def say_hi (self) :
print('hello,%s' % self.name)
foo_obj = Foo('Yang' ,66 )
print(hasattr(foo_obj,'name' ))
print(hasattr(foo_obj,'say_hi' ))
print(getattr(foo_obj,'name' ))
func=getattr(foo_obj,'say_hi' )
func()
print(getattr(foo_obj,'x' ,'不存在啊' ))
setattr(foo_obj,'yo' ,True )
setattr(foo_obj,'show_name' ,lambda self:self.name+'yoyoyo' )
print(foo_obj.__dict__)
print(foo_obj.show_name(foo_obj))
delattr(foo_obj,'age' )
delattr(foo_obj,'show_name' )
delattr(foo_obj,'not_exist_func' )
print(foo_obj.__dict__)
class Foo (object) :
static_var = "类的静态属性"
def __init__ (self) :
self.name = '人身苦短'
def func (self) :
return '我用python'
@staticmethod
def bar () :
return 'bar func...'
print(getattr(Foo, 'static_var' ))
print(getattr(Foo, 'func' ))
print(getattr(Foo, 'bar' ))
'''
程序目录:
module_test.py
index.py
当前文件:
index.py
'''
import module_test as obj
print(hasattr(obj, 'test' ))
print(getattr(obj, 'test' ))
import sys
def s1 () :
print('s1' )
def s2 () :
print('s2' )
this_module = sys.modules[__name__]
print(hasattr(this_module, 's1' ))
print(getattr(this_module, 's2' ))
三、类的内置方法
1、__str__、__repr__
①注意:内置的类方法与内置函数之前的关系
②__str__方法
object类中实现了__str__,object中的__str__方法返回调用这个方法对象的内存地址 %s、str()、print()实际上都是执行内置方法__str__ 如果自定义类重写了__str__方法,则必须返回字符串 如果类中没有__str__方法,会先找本类中的__repr__方法,若再没有则再找默认object类中的__str__ 如果类继承了自定义的父类,则如果没有__str__,则会继续找自定义父类中的__str__,若没有则找自己的__repr__,如果找不到则找自定义父类中的__repr__(repr是str的备胎,但str不是repr的备胎)
③__repr__方法
object类中实现了__repr__,object中的__repr__方法返回调用这个方法对象的内存地址 %r、repr() 实际上都是执行内置方法__repr__ 如果自定义类重写了__repr__方法,则必须返回字符串 如果类中没有__repr__方法,则会找父类中的__repr__
2、__del__
①定义:析构方法,当对象在内存中被释放时,自动触发执行
②注意:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。
③如果重写了__del__方法会先执行__del__中的代码,但最终仍会将对象在内存中释放
④应用举例:
class Foo :
def __del__ (self) :
print('执行了__del__中的内容....' )
f1 = Foo()
del f1
print(f1)
>>> 执行了__del__中的内容....
>>> Traceback (most recent call last):
File "D:/practice.py" , line 18 , in <module>
print(f1)
NameError: name 'f1' is not defined
3、__call__
①定义:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
②应用举例:
class Foo :
def __init__ (self) :
pass
def __call__ (self, *args, **kwargs) :
print('调用__call__~~~' )
obj = Foo()
obj()
4、__new__
①定义:python中对象的创建首先执行new 内置方法,或者可以理解成python中类的构造函数
②应用实例:
class Foo :
def __init__ (self) :
print('in __init__' )
def __new__ (cls, *args, **kwargs) :
print('in __new__' )
return object.__new__(Foo)
f = Foo()
>>> in __new__
>>> in __init__
单例模式举例:单例模式即所有创建的对象都是指向同一个对象,对任何对象的修改操作实际上都是对同一个对象的操作
class Single :
__instance = False
def __init__ (self) :
pass
def __new__ (cls, *args, **kw) :
if not hasattr(cls, '_instance' ):
cls._instance = object.__new__(cls)
return cls._instance
s1 = Single()
s2 = Single()
print(s1)
print(s2)
>>> <__main__.Single object at 0x00000000011B1B38 >
>>> <__main__.Single object at 0x00000000011B1B38 >
2、__hash__
①应用实例:
class A :
def __init__ (self) :
self.a = 1
self.b = 2
def __hash__ (self) :
return hash(str(self.a)+str(self.b))
a = A()
print(hash(a))
3、__eq__
①默认判断两个对象的内存地址是否相同
class A :
def __init__ (self) :
self.a = 1
self.b = 2
def __eq__ (self,obj) :
if self.a == obj.a and self.b == obj.b:
return True
a = A()
b = A()
print(a == b)
>>> True
4、item系列—默认object类中没有包括item系列方法
①__getitem__
class Foo :
def __init__ (self,attr1,attr2) :
self.attr1 = attr1
self.attr2 = attr2
def __getitem__ (self, item) :
return self.attr1
f = Foo('属性1' ,'属性2' )
print(f['atr1' ])
②__setitem__
class Foo :
def __init__ (self,attr1,attr2) :
self.attr1 = attr1
self.attr2 = attr2
def __setitem__ (self, key, value) :
return self.__setattr__(key,value)
f = Foo('属性1' ,'属性2' )
f['atr3' ] = '属性3'
print(f.__dict__)
>>> {'attr1' : '属性1' , 'atr3' : '属性3' , 'attr2' : '属性2' }
③__del__
定义:调用del 类.属性的时候会执行该方法 实例:
class Foo :
def __init__ (self,attr1,attr2) :
self.attr1 = attr1
self.attr2 = attr2
def __delitem__ (self, key) :
del key
f = Foo('属性1' ,'属性2' )
del f['attr1' ]
print(f.__dict__)
>>> {'attr2' : '属性2' , 'attr1' : '属性1' }