面向对象进阶
一、isinstance和issubclass
isinstance(obj,cls)检查是否obj是否是类 cls 的对象
class Foo(object): pass obj = Foo() isinstance(obj, Foo)
issubclass(sub, super)检查sub类是否是 super 类的派生类
class Foo(object): pass class Bar(Foo): pass issubclass(Bar, Foo)
二、反射
setattr:设置类或对象的属性
class Cdemo: dic = "静态属性" @classmethod def func1(cls): print('这个是个类方法') def func2(self): print('这是个对象方法') obj = Cdemo() setattr(obj,'sb',True) setattr(obj,'new_func',lambda self:print('新建的方法')) print(obj.__dict__) print(obj.new_func(obj))
delattr:删除类或对象的属性
class Cdemo: dic = "静态属性" @classmethod def func1(cls): print('这个是个类方法') def func2(self): print('这是个对象方法') obj = Cdemo() #删除属性 delattr(Cdemo,'dic') delattr(Cdemo,'func1') delattr(Cdemo,'func3')#不存在,则报错
getattr:获取类或对象的属性
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
oss = '123456' import sys print(sys.modules['__main__']) # <module '__main__' from 'H:/PythonDemo/Demo_PythonBook/python_class/s10.py'> local_models = getattr(sys.modules['__main__'],'oss') print(local_models) # 123456
class Cdemo: dic = "静态属性" @classmethod def func1(cls): print('这个是个类方法') def func2(self): print('这是个对象方法') # 静态属性的getattr()操作 ret = getattr(Cdemo,'dic') print(ret) # 类方法的getattr()操作 ret1 = getattr(Cdemo,'func1') print(ret1()) # 类对象的getattr()操作 c = Cdemo() ret2 = getattr(c,'func2') print(ret2())
hasattr:检查类或对象是否有该属性
class Cdemo: dic = "静态属性" @classmethod def func1(cls): print('这个是个类方法') def func2(self): print('这是个对象方法') ret = hasattr(Cdemo,'dic') # 是否有静态属性,返回True或False print(ret) ret = hasattr(Cdemo,'func1') # 是否有类方法,返回True或False print(ret) obj = Cdemo() ret = hasattr(obj,'func1') # 是否有对象方法,返回True或False print(ret)
三、内置方法
1)__str__,__repr__:改变对象的字符串显示__str__,__repr__
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# __str__和__repr__ class A: def __str__(self): """ 可用于对象说明 :return: """ return 'A' a = A() # 打印一个对象的时候就是调用__str__() # __str__() 默认返回内存地址的字符串,可以使用此方法重新定义返回值 print(a) class B: def __str__(self): return 'str : class B' def __repr__(self): return 'repr : class B' b = B() # 如果__str__没有被定义,那么就会使用__repr__来代替输出 # 注意:这俩方法的返回值必须是字符串,否则抛出异常 print('%s' % b) print('%r' % b)
2)__del__:析构方法,当对象在内存中被释放时,自动触发执行。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Foo: def __init__(self,filepath): self.filepath = filepath self.f = open(self.filepath, 'w') # 在删除一个对象前进行剩余的收尾工作 # 比如当打开一个文件,删除了对象,内存消失了,但是文本依然打开着,所以需要进行收尾来及时释放内存 def __del__(self): print("执行关闭") self.f.close() def open_file(self): self.f.write("1111") f1=Foo('ceshi.txt') print(f1.open_file())
3)__len__:计算长度
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: def __init__(self): self.a = 1 self.b = 2 def __len__(self): return len(self.__dict__) a = A() print(len(a))
4)__call__:一个对象+()则执行__call__方法,可以给对象设置一些功能
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: def __init__(self,name): pass def __call__(self, *args, **kwargs): print("执行我了") # 一个对象+()相当于执行__call__方法 a = A('alex') a()
5)__new__,__init__:__new__构造方法,创建一个对象self;__init__初始化方法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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) # 执行顺序:__new__ --- __init__ --- print(a.x) # 输出结果: ''' in new function in init function 1 ''' a = A() print(a.x)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#单例模式是23种设计模式中的一种,只依靠修改对象属性来实现一个类只能创建一个对象的更多实用操作 class A: __instance = False def __init__(self,name,age): self.name = name self.age = age def __new__(cls,*args,**kwargs): if cls.__instance: return cls.__instance cls.__instance = object.__new__(cls) return cls.__instance a = A('aaa',18) b = A('bbb',28) print(a) print(b) print(a.name) print(b.name)
6)__eq__:判断对象是否相等
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: def __init__(self,name): self.name = name def __eq__(self, other): # self, other默认这两个参数为内存地址 if self.name == other.name: return True return False a1 = A('jack') a2 = A('jack') print(a1 == a2)
7)__hash__:自定义hash值
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class A: def __init__(self,a,b): self.a = a self.b = b def __hash__(self): return hash(self.a + self.b) a1 = A('111','222') a2 = A('111','222') # 如果没有写__hash__()默认使用内存地址进行hash,hash值肯定不同 print(hash(a1)) #-7735806094895007429 print(hash(a2)) #-7735806094895007429
四、补充
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import json from collections import namedtuple Card = namedtuple('Card',['rank','suit']) # rank牌面大小 suit牌面花色 # c1 = Card(rank=2,suit='红心') class FranchDeck: ranks = [str(n) for n in range(2,11)] + list('JQKA') suits = ['红心','方板','梅花','黑桃'] def __init__(self): ''' for suit in FranchDeck.suits for rank in FranchDeck.ranks Card(suit,rank) ''' 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 def __str__(self): return json.dumps(self._cards,ensure_ascii=False) deck = FranchDeck() # 随机抽两张牌 from random import choice # 依赖内置__len__()方法 print(choice(deck)) print(choice(deck)) # 洗牌 from random import shuffle # 依赖内置__setitem__()方法 shuffle(deck) print(deck[:5]) # __str__查看对象内容 print(deck)
![](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__