面向对象进阶(二)
1、__del__方法:删除一个对象时调用的方法
import time
class A:
def __init__(self):
self.f = open('userinfo','a')
def consume(self):
pass
def __del__(self):
'''在删除一个对象之前做一些收尾工作'''
self.f.close()
print('删除一个对象的时候调用我')
a = A()
time.sleep(1)
del a
# 删除一个对象的时候,如果内部存在__del__方法,
# 那么在删除一个对象之前先执行__del__方法中的代码
print(a)
2、__new__构造方法:构造一个新的对象
class A:
def __init__(self,name,age):
self.name = name
self.age = age
print('执行了__init__方法')
def __new__(cls, *args, **kwargs):
print('执行了__new__方法')
return object.__new__(cls) #创造对象,将对象返回
a = A('xxx','22')
print(type(a))
print(type(A))
先执行__new__方法,创造一个对象
然后把创造处的对象传递给__init__方法
会把self自动返回,被a接收
3、元类type():创造类的类 所有直接用class创建出来的类的元类都是type
# class 类名(B,classMeta=元类名) # class 类名(B,classMeat = type) #默认 # 元类 创造 类 所以 所有的类的type都是他的元类,默认他是type # 类 创造对 象 所以 具有创造对象的方法__init__的方法,所有的对象的type都是他的类 # class B(A): # pass # print(type(B))
4、单例模式:一个类 可以被多次实例化,但同一时间在python中,只能有一个实例
# class A:
# _instance = None
# def __init__(self,name):
# self.name = name
# def __new__(cls, *args, **kwargs):
# if not A._instance:
# A._instance = object.__new__(cls)
# return A._instance
# a1 = A('alex')
# # print(a1.name)
# a2 = A('egon')
# print(a1.name,a2.name)
#使用反射来实现
# class A:
# def __init__(self,name):
# self.name = name
# def __new__(cls, *args, **kwargs):
# if not hasattr(A,'_instance'):
# A._instance = object.__new__(cls)
# return A._instance
# a1 = A('alex')
# # print(a1.name)
# a2 = A('egon')
# print(a1.name,a2.name)
5、item系列:__getitem__\__setitem__\__delitem__
class A:
def __init__(self,name):
self.name = name
self.age = 21
def __getitem__(self, item):
return self.__dict__[item]
def __setitem__(self, key, value):
self.__dict__[key] = value
def __delitem__(self, key):
del self.__dict__[key]
a = A('dzf')
# print(a['name']) #对应了类中的一个方法
# print(a['age']) #对应了类中的一个方法
a['sex'] = 'boy' #对应 __setitem__方法,增加,修改一个对象
print(a.sex)
print(a['sex'])
# a['sex'] = 'girl'
# print(a.__dict__)
# del a['name'] #对应 __delitem__ 删除一个对象
# print(a.__dict__)
6、__call__:
对象后面加括号,触发执行。
注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
class Foo:
def __init__(self):
pass
def __call__(self, *args, **kwargs):
print('__call__')
obj = Foo() # 执行 __init__
obj() # 执行 __call__
7、__hash__方法:可哈希的数据类型都是不可变数据类型
# class A: # def __hash__(self): # return 666 # # a = A() # b = A() # print(hash(a)) #objet.__hash__() # print(hash(b)) #objet.__hash__() # dict 的 key set 的 元素 都必须是可哈希的 # hash(objet)函数,objet对象对应的类必然内部实现了__hash__方法 # hash的结果就是__hash__方法的返回值 # 且在一次成的执行过程中是不会发生变化的 # 且要想作为字典的key或者作为集合的元素,这个对象对应的类必须实现__hash__方法
8、面试题:
# 金融公司面试题
# 有一个类,对应这个类产生了100个对象
# 每个对象有三个属性 : 姓名 年龄 性别
# 请对这一百个对象进行去重,如果姓名和性别相同,即便年龄不同也是相同的对象
# 问最简便的方法?
class Person:
def __init__(self,name,sex,age):
self.name = name
self.sex = sex
self.age = age
def __hash__(self):
return hash('%s%s'%(self.name,self.sex))
def __eq__(self, other):
if self.name == other.name and self.sex == other.sex:
return True
l = []
for i in range(100):
l.append(Person('alex','man',i))
print(set(l))
# 去重在函数内部先执行了__hash__方法,判断hash值是否相等,然后执行了__eq__方法,判断值是否相等
9、纸牌例子:
from collections import namedtuple #每个可命名元组都是没有方法的类
Card =namedtuple('Card',['rank','suit'])
# card1 =Card(1,'方块')
# print(card1)
class FranchDeck:
ranks = [str(n) for n in range(2,11)] + list('JQKA')
suit = ['红心','方片','黑桃','梅花']
def __init__(self):
self._cards = [Card(rank,suit) for rank in FranchDeck.ranks
for suit in FranchDeck.suit] # 列表生成式
def __len__(self): #内置发方法
return len(self._cards)
def __getitem__(self, item): #内置发方法
return self._cards[item]
def __setitem__(self, key, value): #内置发方法
self._cards[key] = value
deak = FranchDeck()
# print(deak[:])
from random import choice #随机抽取一张拍
choice(deak)
print(deak[2])
from random import shuffle #洗牌
shuffle(deak)
print(deak[:]
浙公网安备 33010602011771号