面向对象进阶
isinstance和issubclass
isinstance() :判断一个对象是不是这个类的实例,如果这个类有父类,那么这个对象也是其父类的对象
issubclass() : 判断两个类是不是父子关系,接受两个参数(子类,父类)
isinstance(obj,cls)检查是否obj是否是类 cls 的对象
class Foo: pass s=Foo() print(isinstance(s,Foo)) #True
issubclass(sub, super)检查sub类是否是 super 类的派生类
class Foo(object): pass class Bar(Foo): pass print(issubclass(Bar, Foo)) #True
反射
反射: 把一个字符串数据类型的变量变成一个真实存在在这个程序中的变量名,并且能够使用它
python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
下列方法适用于类和对象(一切皆对象,类本身也是一个对象)
#-对象中的反射
class Foo: f = '类的静态变量' def __init__(self,name,age): self.name=name self.age=age def say_hi(self): print('hi,%s'%self.name) obj=Foo('egon',73) #检测是否含有某属性和方法 print(obj.__dict__) # 查看对象中的方法和属性 {'name': 'egon', 'age': 73} print(hasattr(obj,'name')) #True print(hasattr(obj,'say_hi')) #True print(hasattr(obj,'aaa')) #False #获取属性 n=getattr(obj,'name') # = obj.name print(n) # egon n= obj.name print(n) # egon func=getattr(obj,'say_hi') print(func) # <bound method Foo.say_hi of <__main__.Foo object at 0x0000000001E805F8>> func() # hi,egon func=getattr(obj,'aaa','bbb') print(func) # bbb #设置属性 setattr(obj,'sb',True) #obj.sb=True print(obj.sb) #True print(obj.__dict__) # 查看对象中的方法和属性 {'name': 'egon', 'age': 73, 'sb': True} setattr(obj,'show_name',lambda self:self.name+'sb') # obj.show_name() print(obj.show_name(obj)) # egonsb print(obj.__dict__) # {'name': 'egon', 'age': 73, 'sb': True, 'show_name': <function <lambda> at 0x0000000001D13E18>} #删除属性 delattr(obj,'age') delattr(obj,'show_name') delattr(obj,'show_name111')#不存在,则报错
#-类中的反射
class Foo: f = '类的静态变量' def __init__(self,name,age): self.name=name self.age=age def say_hi(self): print('hi,%s'%self.name) obj=Foo('egon',73) print(Foo.__dict__) #{'__module__': '__main__', 'f': '类的静态变量', '__init__': <function Foo.__init__ at 0x00000000029D5BF8>, # 'say_hi': <function Foo.say_hi at 0x00000000029D5C80>, '__dict__': <attribute '__dict__' of 'Foo' objects>, # '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None} print(hasattr(Foo,'f')) # True print(getattr(Foo,'say_hi')) # <function Foo.say_hi at 0x00000000029D5C80> getattr(Foo,'say_hi')() #会报错 如果传个实例化对象就不会 getattr(Foo,'say_hi')(obj) # hi,egon setattr(Foo,'a','abc') # Foo.a='abc' print(Foo.__dict__) # 最后多了一个 'a': 'abc' print(Foo.a) # abc delattr(Foo,'a') delattr(Foo,'say_hi') delattr(Foo,'f') print(Foo.__dict__) # {'__module__': '__main__', '__init__': <function Foo.__init__ at 0x00000000029E5BF8>, # '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}
#-类中的反射与类方法,静态方法结合使用
class Foo(object): staticField = "old boy" def __init__(self): self.name = 'wupeiqi' @classmethod def func(cls): return cls.staticField @classmethod def func1(cls,a): return a+cls.staticField @staticmethod def bar(): return 'bar' a='a' print(Foo.staticField) # old boy print(getattr(Foo, 'staticField')) # old boy print(getattr(Foo, 'bar')()) # bar 调用静态方法 print(getattr(Foo, 'func')()) # old boy 调用类中方法 print(getattr(Foo, 'func1')(a)) # aold boy 调用类方法,并往其中传参
#-当前模块的反射
import sys def s1(): print ('s1') def s2(): print ('s2')
xiaoxuanxuan = 2222
this_module = sys.modules[__name__] # 在自己文件中__name__会变成__main__ 自身文件的模块名 用模块名.属性或方法查看
print(getattr(this_module, 'xiaoxuanxuan')) #22222
print(hasattr(this_module, 's1')) # True
getattr(this_module, 's2')() # s2
#导入其他模块,利用反射查找该模块是否存在某个方法 # module_test.py与index.py在同一目录下 # 在module_test.py中 def test(): print('from the test') # 在index.py中 import module_test as obj print(hasattr(obj,'test')) # True getattr(obj,'test')() # from the test
__str__和__repr__
改变对象的字符串显示__str__,__repr__
自定制格式化字符串__format__
''' str函数或者print函数--->obj.__str__() repr或者交互式解释器--->obj.__repr__() 如果__str__没有被定义,那么就会使用__repr__来代替输出 注意:这俩方法的返回值必须是字符串,否则抛出异常 ''' 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) s1=School('oldboy1','北京','私立') print('from repr: ',repr(s1)) # from repr: School(oldboy1,北京) print('from str: ',str(s1)) # from repr: School(oldboy1,北京) print(s1) # School(oldboy1,北京)
class B: def __str__(self): return 'str : class B' def __repr__(self): return 'repr : class B' b=B() print('%s'%b) # str : class B
print('%r'%b) # repr : class B
class Animal: def __init__(self,kind,name): self.kind = kind self.name = name def __str__(self): return 'str : %s : %s'%(self.kind,self.name) def __repr__(self): return 'repr : %s : %s'%(self.kind,self.name) cat = Animal('cat','guolei') print('%s'%cat) # str : cat : guolei print('%r'%cat) # repr : cat : guolei print(str(cat)) # str : cat : guolei print(repr(cat)) # repr : cat : guolei
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] # obj=self return fmt.format(obj=self) s1=School('oldboy1','北京','私立') print(format(s1,'nat')) # oldboy1-北京-私立
__del__
析构方法,当对象在内存中被释放时,自动触发执行。 或者使用 del 对象 自动触发类中__del__
class Foo: def __del__(self): print('执行我啦') f1=Foo() del f1 print('------->') #输出结果 执行我啦 ------->
class A: def __del__(self): print('aaa') class B: def __del__(self): print('bbb') a=A() b = B() print('ccc') #输出
ccc
aaa
bbb
item系列
__getitem__\__setitem__\__delitem__
class Animal: def __init__(self,name): self.name = name def __getitem__(self, item): return getattr(self,item) def __setitem__(self, key, value): setattr(self,key,value) def __delitem__(self, key): delattr(self,key) cat = Animal('guolei') print(cat['name']) #去类中找getitem方法 guolei
cat['sex'] = '公' #去类中找setitem方法
print(cat.sex) #公
print(cat['sex']) #公
print(cat.__dict__) #{'name': 'guolei', 'sex': '公'}
del cat['name'] # 去类中找delattr方法
print(cat.__dict__) #{'sex': '公'}
__new__
单例模式 实例始终只有一个 他的属性可以随着你的改变而改变
#正常情况下,示例化后先进行__new__方法,在父类object方法中new出一个新对象,给予__init__方法中的self,这就是正常情况下实例化对象的步骤
#即先去元祖那里,创建一个人(裸体的人),再为这个人穿衣服(在__init__方法中的self实例化)
class A: def __init__(self): self.x = 1 print('in init function') def __new__(cls, *args, **kwargs): print('in new function') return object.__new__(A, *args, **kwargs) a = A() print(a.x)
#输出:
in new function
in init function
1
class Singleton: def __new__(cls, *args, **kw): if not hasattr(cls, '_instance'): orig = super(Singleton, cls) cls._instance = orig.__new__(cls, *args, **kw) return cls._instance one = Singleton() two = Singleton() two.a = 3 print(one.a) # 3 # one和two完全相同,可以用id(), ==, is检测 print(id(one)) # 29097904 print(id(two)) # 29097904 print(one == two) # True print(one is two)
class Teacher: #创建一个老师类 __isinstance = None #创建一个私有静态变量来装裸着的对象 def __new__(cls, *args, **kwargs): #创建一个裸着的对象 if not cls.__isinstance: #如果__isinstance属性为None cls.__isinstance = object.__new__(cls) #用object.__new__创建一个裸着的对象 return cls.__isinstance #返回一个对象 def __init__(self,name,cloth): #self就是cls.__isinstance返回的对象 self.name = name #给self的name属性赋值 self.cloth = cloth #给self的cloth属性赋值 刘老师 = Teacher('刘永熹','白色') print(刘老师.name,刘老师.cloth) # 刘永熹 白色 王老师 = Teacher('王庆帅','黑色') print(刘老师.name,刘老师.cloth) # 王庆帅 黑色 print(王老师.name,王老师.cloth) # 王庆帅 黑色 print(刘老师,王老师) #<__main__.Teacher object at 0x00000000027C0630> <__main__.Teacher object at 0x00000000027C0630>
__call__
对象后面加括号,触发执行。
注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
class Foo: def __init__(self): pass def __call__(self, *args, **kwargs): print('__call__') obj = Foo() # 执行 __init__ obj() # 执行 __call__
__len__
对于 __len__ 方法的执行是由len(对象)后触发的,即:len(对象)
class A: def __init__(self): self.a = 1 self.b = 2 def __len__(self): return len(self.__dict__) a = A() print(len(a)) # 2
print(a.__dict__) # {'a': 1, 'b': 2}
__hash__
对于 __hash__ 方法的执行是由hash(对象)后触发的,即: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)) # -7422275419112235454 每次运行都不相同
__eq__
对于 __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
class FranchDeck: ranks = [str(n) for n in range(2,11)] + list('JQKA') suits = ['红心','方板','梅花','黑桃'] def __init__(self): self._cards = [Card(rank,suit) for rank in FranchDeck.ranks for suit in FranchDeck.suits] def __len__(self): return len(self._cards) def __getitem__(self, item): return self._cards[item] def __setitem__(self, key, value): self._cards[key] = value deck = FranchDeck() print(deck[0]) from random import choice print(choice(deck)) print(choice(deck)) from random import shuffle shuffle(deck) print(deck[:5])
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from collections import namedtuple Card = namedtuple('Card',['rank','suit']) class FranchDeck: ranks = [str(n) for n in range(2,11)] + list('JQKA') suits = ['红心','方板','梅花','黑桃'] def __init__(self): self._cards = [Card(rank,suit) for rank in FranchDeck.ranks for suit in FranchDeck.suits] def __len__(self): return len(self._cards) def __getitem__(self, item): return self._cards[item] def __setitem__(self, key, value): self._cards[key] = value deck = FranchDeck() print(deck[0]) # 第一张 Card(rank='2', suit='红心') from random import choice print(choice(deck)) #随机抽一张 Card(rank='2', suit='黑桃') print(choice(deck)) #随机抽一张 Card(rank='A', suit='梅花') from random import shuffle shuffle(deck) print(deck[:5]) # 抽五张
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Person: def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex def __hash__(self): return hash(self.name+self.sex) def __eq__(self, other): if self.name == other.name and self.sex == other.sex:return True p_lst = [] for i in range(84): p_lst.append(Person('egon',i,'male')) print(p_lst) # 一百个对象的列表 print(set(p_lst)) # 只有一个对象,set()方法运行了类中的__hash__与__eq__方法