python之路_面向对象进阶
一、内置函数isinstance和issubclass
1、isinstance()
isinstance(obj,cls)检查obj是否是类 cls 的对象,类似type()。
class Foo(object): pass obj = Foo() print(isinstance(obj, Foo)) #输出结果:True print(isinstance(10,int)) #输出结果:True
sinstance() 与 type() 区别:type() 不会认为子类是一种父类类型,不考虑继承关系。sinstance() 会认为子类是一种父类类型,考虑继承关系。
class A: pass class B(A): pass isinstance(A(), A) # returns True type(A()) == A # returns True isinstance(B(), A) # returns True type(B()) == A # returns False
(2)issubclass()
issubclass(sub, super)检查sub类是否是 super 类的派生类/子类
class Foo(object): pass class Bar(Foo): pass print(issubclass(Bar, Foo)) #输出结果:True
二、反射相关
python面向对象中的反射:通过字符串的形式操作对象相关的属性。如下为4个可以实现自省的函数:
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(hasattr(obj,'name')) #输出结果:True print(hasattr(obj,'say_hi')) #输出结果:True #获取属性 n=getattr(obj,'name') print(n) #输出结果:egon func=getattr(obj,'say_hi') func() #输出结果:hi,egon #设置属性 setattr(obj,'sb',True) setattr(obj,'show_name',lambda self:self.name+'sb') print(obj.__dict__) #输出结果:{'name': 'egon', 'age': 73, 'sb': True, 'show_name': <function <lambda> at 0x00000194A8817048>} print(obj.show_name(obj)) #删除属性 delattr(obj,'age') delattr(obj,'show_name') print(obj.__dict__) #输出结果:{'name': 'egon', 'sb': True}
三、类的内置方法
1、__str__和__repr__
改变对象的字符串显示__str__,__repr__,这俩方法的返回值必须是字符串,否则抛出异常。
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(str(cat)) #输出结果:str : cat : guolei print(repr(cat)) #输出结果:repr : cat : guolei print('%s'%cat) #输出结果:str : cat : guolei print('%r'%cat) #输出结果:repr : cat : guolei
2、__del__
析构方法,当对象在内存中被释放时,自动触发执行。注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。
class Foo: def __del__(self): print('执行我啦') f1=Foo() del f1 #输出结果:执行我啦
3、__getitem__\__setitem__\__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']=18 f1['age1']=19 del f1.age1 #输出结果:del obj.key时,我执行 del f1['age'] #输出结果:del obj[key]时,我执行 f1['name']='alex' print(f1.__dict__) #输出结果:{'name': 'alex'}
4、__new__
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)
单例模式:
无论实例化多少个对象,只有一个对象存在,且这个对象为最后实例化的那个对象。
#实例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) # True
class Teacher: __instance=None def __new__(cls, *args, **kwargs): if not cls.__instance: cls.__instance=object.__new__(cls) return cls.__instance def __init__(self,name,cloth): self.name=name self.cloth=cloth 刘老师=Teacher('liu','bai') 王老师=Teacher('wang','hei') print(刘老师.name) #输出结果:wang print(刘老师.cloth) #输出结果:cloth
5、__call__
对象后面加括号,触发执行。注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()。
class Foo: def __init__(self): pass def __call__(self, *args, **kwargs): print('__call__') obj = Foo() # 执行 __init__ obj() # 执行 __call__
6、__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
7、__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)) #输出结果:3429960989477292991
8、
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
四、相关例题
1、纸牌游戏1:抽牌
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] deck = FranchDeck() print(deck[0]) from random import choice print(choice(deck)) print(choice(deck))
2、纸牌游戏2:洗牌
class FranchDeck: ranks = [str(n) for n in range(2,11)] + list('JQKA') suits = ['红心','方板','梅花','黑桃'] def __init__(self): self._cards = [(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 shuffle shuffle(deck) print(deck[:5])
3、一道面试题
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))