类的内置方法
目录
item:__getitem__() __setitem__() __delitem__()
__str__() __repr__()
print(obj) /'%s'%obj /str(obj)的时候,实际上是内部调用了obj.__str__方法
如果有__str__方法,那么他返回的必定是一个字符串
如果没有__str__方法,会先找本类中的__repr__方法,再没有再找父类中的__str__方法
object里有一个__str__,一旦被调用,就返回调用这个方法的对象的内存地址
repr(),只会找__repr__,如果没有找父类的
class A:
def __init__(self,name):
self.name = name
def __str__(self):
return 'aaaa'
a = A('yuki')
print(a.__str__())
print(a) # 打印一个对象的时候,就是调用a.__str__
print('%s'%a)
'''
aaaa
aaaa
aaaa
'''
repr 是str的备胎,但str不能做repr的备胎
#没有__str__方法,但偶__repr__方法,依旧可以正常调用
class A:
def __init__(self,name):
self.name = name
def __repr__(self):
return 'aaaa'
a = A('yuki')
print(a.__str__())
print(a)
print('%s'%a)
'''
aaaa
aaaa
aaaa
''''
#调用__repr__方法
print(a.__repr__())
print(repr(a))
print('%r'%a)
item:__getitem__() __setitem__() __delitem__()
class Foo:
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
def __getitem__(self, item):
if hasattr(self,item):
return self.__dict__[item]
def __setitem__(self, key, value):
self.__dict__[key] = value
def __delitem__(self, key):
del self.__dict__[key]
f = Foo('yuki',8,'女')
print(f['name'])
f['hobby'] = '玩'
print(f.hobby,f['hobby']) #两种方式调用对象属性
# del f.hobby # object 原生支持 __delattr__
del f['hobby'] # 通过自己实现的
print(f.__dict__)
'''
yuki
玩 玩
{'name': 'yuki', 'age': 8, 'sex': '女'}
__del__()
del a 就调用了A中的__del__方法
class A:
def __del__(self):
print('aaa')
a = A()
del a
#aaaa
class A:
def __del__(self): # 析构函数: 在删除一个对象之前进行一些收尾工作
self.f.close()
a = A()
a.f = open() # 打开文件 第一 在操作系统中打开了一个文件 拿到了文件操作符存在了内存中
del a # a.f 拿到了文件操作符消失在了内存中
del a # del 既执行了这个方法,又删除了变量
__new__()
#先执行__new__方法,在执行__init__方法
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)
a1 = A()
print(a1.x)
'''
in new function
in init function
1
'''
单例模式:一个类,始终只有一个实例 ,当你第一次实例化这个类的时候,就创建一个实例化的对象,当你之后再来实例化的时候,就用之前创建的对象。
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('a',12)
b = A('b',21)
print(a)
print(b)
print(a.name)
print(b.name)
'''
<__main__.A object at 0x000001A9E3972278>
<__main__.A object at 0x000001A9E3972278>
b
b
'''
__call__()
对象()就是调用类的__call__方法
class A:
def __init__(self,name):
self.name = name
def __call__(self):
print('aaaa')
a = A('yuki')()
#aaaa
with和__enter__,__exit__
class A:
def __init__(self):
print('init')
def __enter__(self):
print('before')
def __exit__(self, exc_type, exc_val, exc_tb):
print('after')
with A() as a:
print('123')
'''
init
before
123
after
'''
class Myfile:
def __init__(self,path,mode='r',encoding = 'utf-8'):
self.path = path
self.mode = mode
self.encoding = encoding
def __enter__(self):
self.f = open(self.path, mode=self.mode, encoding=self.encoding)
return self.f
def __exit__(self, exc_type, exc_val, exc_tb):
self.f.close()
with Myfile('file',mode='w') as f: #完成写入,并关闭文件
f.write('aaaa')
#withhepickle
import pickle
class MyPickledump:
def __init__(self,path):
self.path = path
def __enter__(self):
self.f = open(self.path, mode='ab')
return self
def dump(self,content):
pickle.dump(content,self.f)
def __exit__(self, exc_type, exc_val, exc_tb):
self.f.close()
class Mypickleload:
def __init__(self,path):
self.path = path
def __enter__(self):
self.f = open(self.path, mode='rb')
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.f.close()
def load(self):
return pickle.load(self.f)
def loaditer(self):
while True:
try:
yield self.load()
except EOFError:
break
# with MyPickledump('file') as f: #先写进文件
# f.dump({1,2,3,4})
with Mypickleload('file') as f: #在读文件
for item in f.loaditer():
print(item)
#with和pickle和iter
import pickle
class MyPickledump:
def __init__(self,path):
self.path = path
def __enter__(self):
self.f = open(self.path, mode='ab')
return self
def dump(self,content):
pickle.dump(content,self.f)
def __exit__(self, exc_type, exc_val, exc_tb):
self.f.close()
class Mypickleload:
def __init__(self,path):
self.path = path
def __enter__(self):
self.f = open(self.path, mode='rb')
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.f.close()
def __iter__(self):
while True:
try:
yield pickle.load(self.f)
except EOFError:
break
# with MyPickledump('file') as f:
# f.dump({1,2,3,4})
with Mypickleload('file') as f:
for item in f:
print(item)
__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
__hash__()
class A:
def __init__(self,name,sex):
self.name = name
self.sex = sex
def __hash__(self):
return hash(self.name+self.sex)
a = A('a','男')
b = A('a','男')
print(hash(a))
print(hash(b))
'''
-3344918677095476175
-3344918677095476175
'''
__eq__()
class A:
def __init__(self,name):
self.name = name
def __eq__(self, other): #判断对象的值是否相等
if self.__dict__ == other.__dict__:
return True
else:
return False
ret1 = A('a')
ret2 = A('a')
print(ret1 == ret2)
#True
纸牌游戏
from collections import namedtuple
Card = namedtuple('Card',['rank','suit']) # rank 牌面的大小 suit牌面的花色
c =Card(3,'红桃')
print(c)
print(c.suit)
'''
Card(rank=3, suit='红桃')
红桃
'''
import json
from collections import namedtuple
Card = namedtuple('Card',['rank','suit']) # rank 牌面的大小 suit牌面的花色
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] #双层循环 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
def __str__(self):
return json.dumps(self._cards,ensure_ascii=False)
deck = FranchDeck()
print(deck[0]) #Card(rank='4', suit='梅花')
from random import choice
print(choice(deck)) #随机抽排
print(choice(deck))
from random import shuffle #洗牌
shuffle(deck)
print(deck[10])
print(deck)
print(deck[:5])