反射
几个反射相关的函数可参考python基础(10)-匿名函数&内置函数中2.2.4反射相关
类的一些内置函数
__str__()&__repr__()
重写__str__()函数类似重写java中的toString()函数.当没有重写__str__()但重写了__repr__()函数时,__repr__()函数会充当一个__str__函数的替代函数执行
1 class Person1: 2 def __init__(self, name, age): 3 self.name = name 4 self.age = age 5 6 def __str__(self): 7 return "name:{} age:{}".format(self.name, self.age) 8 9 10 p1 = Person1('张三', 18) 11 print(p1) # name:张三 age:18 12 13 14 class Person2: 15 def __init__(self, name, age): 16 self.name = name 17 self.age = age 18 19 def __repr__(self): 20 return "name:{} age:{}".format(self.name, self.age) 21 22 p2 = Person2('张三', 18) 23 print(p1) # name:张三 age:18
__del__()
销毁一个对象的时候执行,类似java中的析构函数
1 class A: 2 def __del__(self): 3 print("from del") 4 5 a = A() 6 del a # from del
__getitem__()&__setitem__()&__delitem__()
以'[]'的形式访问属性
1 class Person: 2 def __init__(self, name, age): 3 self.name = name 4 self.age = age 5 6 def __getitem__(self, item): 7 print("from __getitem__:{}".format(item)) 8 return self.__dict__[item] 9 10 def __setitem__(self, key, value): 11 print("from __setitem__:{} = {}".format(key, value)) 12 self.__dict__[key] = value 13 14 def __delitem__(self, key): 15 print("from __delitem__:{}".format(key)) 16 17 18 p = Person('张三', 18) 19 name = p['name'] # from __getitem__:name 20 print(name) # 张三 21 print(p.age) # 18 22 p['age'] = 20 # from __setitem__:age = 20 23 print(p.age) # 20 24 # 和@property.deleter相似 del时只是触发对应方法 并不是真的删除 25 del p['age'] # from __delitem__:age 26 print(p.age) # 20
__new__()
创建对象(self),类似java中的构造函数,在__init__()函数之前执行
1 class Person: 2 def __init__(self, name, age): 3 print('from __init__()') 4 self.name = name 5 self.age = age 6 7 def __new__(cls, *args, **kwargs): 8 print('from __new__()') 9 return object.__new__(cls) 10 11 p = Person('张三', 18) 12 13 # result: 14 # from __new__() 15 # from __init__()
__call__()
让一个类的实例成为一个callable对象
1 class Person: 2 def __init__(self, name, age): 3 self.name = name 4 self.age = age 5 6 def __call__(self, *args, **kwargs): 7 print('name:{} age:{}'.format(self.name, self.age)) 8 9 p = Person('张三', 18) 10 print(callable(p)) # True 11 p() # name:张三 age:18
__len__()
对len()函数传入一个对象实际上就是调用这个对象的__len__()函数
1 class Person: 2 def __init__(self, name, age): 3 self.name = name 4 self.age = age 5 6 def __len__(self): 7 return len(self.name) 8 9 10 print(len(Person('张三', 18))) # 2
__hash__()
对hash()函数传入一个对象实际上就是调用这个对象的__hash__()函数
1 class Person: 2 def __init__(self, no, name, age): 3 self.no = no 4 self.name = name 5 self.age = age 6 7 def __hash__(self): 8 return self.no 9 10 11 p = Person(1, '张三', 18) 12 print(hash(p)) # 1
__eq__()
使用'=='判断两个对象是否相等时,依据__eq__()函数返回的值.类似java中的equals()函数
1 class Person: 2 def __init__(self, name, age): 3 self.name = name 4 self.age = age 5 6 def __eq__(self, other): 7 return self.name == other.name 8 9 10 p1 = Person('张三', 19) 11 p2 = Person('张三', 18) 12 print(p1 == p2) # True
扩展
单例模式
1 class Single: 2 instance = None 3 4 def __new__(cls, *args, **kwargs): 5 if cls.instance: 6 return cls.instance 7 cls.instance = object.__new__(cls) 8 return cls.instance 9 10 o1 = Single() 11 o2 = Single() 12 print(o1) # <__main__.Single object at 0x00000000021EDAC8> 13 print(o2) # <__main__.Single object at 0x00000000021EDAC8>
扑克牌
1 from collections import namedtuple 2 from random import choice, shuffle 3 4 CardTuple = namedtuple('Card', ['suit', 'rank']) 5 6 7 class Card: 8 def __init__(self): 9 suit_list = ['红桃', '黑桃', '梅花', '方块'] 10 rank_list = [str(i) for i in range(2, 11)] + ['J', 'Q', 'K', 'A'] 11 self.card_list = [CardTuple(suit, rank) for rank in rank_list for suit in suit_list] 12 13 def __str__(self): 14 return str(self.card_list) 15 16 def __len__(self): 17 return len(self.card_list) 18 19 def __getitem__(self, item): 20 return self.card_list[item] 21 22 def __setitem__(self, key, value): 23 self.card_list[key] = value 24 25 26 # 一幅扑克牌 27 card = Card() 28 print( 29 card) # [Card(suit='红桃', rank='2'), Card(suit='黑桃', rank='2'), Card(suit='梅花', rank='2'), Card(suit='方块', rank='2'), Card(suit='红桃', rank='3'), Card(suit='黑桃', rank='3'), Card(suit='梅花', rank='3'), Card(suit='方块', rank='3'), Card(suit='红桃', rank='4'), Card(suit='黑桃', rank='4'), Card(suit='梅花', rank='4'), Card(suit='方块', rank='4'), Card(suit='红桃', rank='5'), Card(suit='黑桃', rank='5'), Card(suit='梅花', rank='5'), Card(suit='方块', rank='5'), Card(suit='红桃', rank='6'), Card(suit='黑桃', rank='6'), Card(suit='梅花', rank='6'), Card(suit='方块', rank='6'), Card(suit='红桃', rank='7'), Card(suit='黑桃', rank='7'), Card(suit='梅花', rank='7'), Card(suit='方块', rank='7'), Card(suit='红桃', rank='8'), Card(suit='黑桃', rank='8'), Card(suit='梅花', rank='8'), Card(suit='方块', rank='8'), Card(suit='红桃', rank='9'), Card(suit='黑桃', rank='9'), Card(suit='梅花', rank='9'), Card(suit='方块', rank='9'), Card(suit='红桃', rank='10'), Card(suit='黑桃', rank='10'), Card(suit='梅花', rank='10'), Card(suit='方块', rank='10'), Card(suit='红桃', rank='J'), Card(suit='黑桃', rank='J'), Card(suit='梅花', rank='J'), Card(suit='方块', rank='J'), Card(suit='红桃', rank='Q'), Card(suit='黑桃', rank='Q'), Card(suit='梅花', rank='Q'), Card(suit='方块', rank='Q'), Card(suit='红桃', rank='K'), Card(suit='黑桃', rank='K'), Card(suit='梅花', rank='K'), Card(suit='方块', rank='K'), Card(suit='红桃', rank='A'), Card(suit='黑桃', rank='A'), Card(suit='梅花', rank='A'), Card(suit='方块', rank='A')] 30 # 扑克牌张数 31 print(len(card)) # 52 32 # 取第十张 33 print(card[10 - 1]) # Card(suit='黑桃', rank='4') 34 # 随机抽取一张 35 print(choice(card)) # Card(suit='方块', rank='7') 36 # 洗牌 37 shuffle(card) 38 print( 39 card) # [Card(suit='黑桃', rank='8'), Card(suit='梅花', rank='6'), Card(suit='黑桃', rank='2'), Card(suit='红桃', rank='4'), Card(suit='梅花', rank='4'), Card(suit='红桃', rank='K'), Card(suit='方块', rank='9'), Card(suit='梅花', rank='7'), Card(suit='梅花', rank='9'), Card(suit='方块', rank='4'), Card(suit='红桃', rank='7'), Card(suit='黑桃', rank='J'), Card(suit='红桃', rank='8'), Card(suit='梅花', rank='K'), Card(suit='红桃', rank='J'), Card(suit='黑桃', rank='6'), Card(suit='红桃', rank='A'), Card(suit='红桃', rank='10'), Card(suit='梅花', rank='5'), Card(suit='方块', rank='6'), Card(suit='方块', rank='10'), Card(suit='方块', rank='8'), Card(suit='方块', rank='7'), Card(suit='黑桃', rank='Q'), Card(suit='方块', rank='A'), Card(suit='红桃', rank='6'), Card(suit='梅花', rank='8'), Card(suit='梅花', rank='J'), Card(suit='梅花', rank='3'), Card(suit='方块', rank='J'), Card(suit='方块', rank='5'), Card(suit='梅花', rank='2'), Card(suit='黑桃', rank='4'), Card(suit='梅花', rank='A'), Card(suit='黑桃', rank='3'), Card(suit='黑桃', rank='5'), Card(suit='方块', rank='K'), Card(suit='红桃', rank='Q'), Card(suit='方块', rank='3'), Card(suit='方块', rank='2'), Card(suit='黑桃', rank='A'), Card(suit='黑桃', rank='7'), Card(suit='方块', rank='Q'), Card(suit='黑桃', rank='9'), Card(suit='红桃', rank='2'), Card(suit='红桃', rank='9'), Card(suit='黑桃', rank='10'), Card(suit='梅花', rank='10'), Card(suit='红桃', rank='3'), Card(suit='红桃', rank='5'), Card(suit='黑桃', rank='K'), Card(suit='梅花', rank='Q')]
对象去重
1 class Person: 2 def __init__(self, name, age): 3 self.name = name 4 self.age = age 5 6 7 p1 = Person('张三', 18) 8 p2 = Person('张三', 18) 9 print(set([p1, p2])) # {<__main__.Person object at 0x000000000273DBA8>, <__main__.Person object at 0x000000000273DAC8>} 10 11 12 class Person: 13 def __init__(self, name, age): 14 self.name = name 15 self.age = age 16 17 def __eq__(self, other): 18 return self.name == other.name and self.age == other.age 19 20 def __hash__(self): 21 return hash(self.name + str(self.age)) 22 23 24 p1 = Person('张三', 18) 25 p2 = Person('张三', 18) 26 print(set([p1, p2])) # {<__main__.Person object at 0x0000000002702860>}
结论:使用set()给对象的去重是同时依赖对象的__hash__()和__eq__()函数的