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