内置方法:__str__,__repr__,__del__,__call__
内置的类方法 和 内置的函数之间有着千丝万缕的联系
也称为双下方法
obj.__str__ /str(obj)
:object里有一个__str__
,一旦被调用,就返回调用这个方法的对象的内存地址;在类中有设置,打印一个实例化对象的时候,就是调用对象名.__str__
。
print(obj)/%s/str(obj)
:内部实际调用了__str__
%r/repr()
:内部实际调用了__repr__
(repr是str的备胎,如无__str__
则调用__repr__
,反过来则不行)
class Teacher:
def __init__(self,name,salary):
self.name = name
self.salary = salary
def __str__(self):
return "Teacher's object :%s"%self.name
def __repr__(self):
return str(self.__dict__)
def func(self):
return 'wahaha'
nezha = Teacher('哪吒',250)
print(nezha) # 打印一个对象的时候,就是调用a.__str__
print(repr(nezha))
print('>>> %r'%nezha)
#输出:
Teacher's object :哪吒
{'name': '哪吒', 'salary': 250}
>>> {'name': '哪吒', 'salary': 250}
str与rpr的关系
- print(obj)/’%s’%obj/str(obj)的时候,实际上是内部调用了obj.__str__方法,如果str方法有,那么他返回的必定是一个字符串。
- 如果没有__str__方法,会先找本类中的__repr__方法,再没有再找父类中的__str__。
- repr(),只会找__repr__,如果没有找父类的
内置的方法有很多
不一定全都在object中
class Classes:
def __init__(self,name):
self.name = name
self.student = []
def __len__(self):
return len(self.student)
def __str__(self):
return 'classes'
s= Classes('python')
s.student.append('jack')
s.student.append('david')
print(len(s))
print(s)
#输出:
2
classes
__del__方法
# class A:
# def __del__(self): # 析构函数: 在删除一个对象之前进行一些收尾工作
# self.f.close()
# a = A()
# a.f = open() # 打开文件 第一 在操作系统中打开了一个文件 拿到了文件操作符存在了内存中
# del a # a.f 拿到了的文件操作符消失在了内存中
# del a # del 既执行了这个方法,又删除了变量
# 引用计数
__call__方法
class A:
def __init__(self,name):
self.name = name
def __call__(self):
'''
打印这个对象中的所有属性
:return:
'''
for k in self.__dict__:
print(k,self.__dict__[k])
a = A('alex')()→输出:name alex
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):#增加属性→对象['']=value
self.__dict__[key] = value#删除→del 对象['']
def __delitem__(self, key):
del self.__dict__[key]
f = Foo('egon',38,'男')
print(f['name'])
f['hobby'] = '男'
print(f.hobby,f['hobby'])
#del f.hobby # object 原生支持 __delattr__
del f['hobby'] # 通过自己实现的
print(f.__dict__)
#输出:
egon
男 男
{'name': 'egon', 'sex': '男', 'age': 38}
__init__
:初始化方法,参数self是new构造出来的。
__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()
# a2 = A()
# a3 = A()
# print(a1)
# print(a2)
# print(a3)
# print(a.x)
#一个类始终只有一个实例
每次创建对象,都把前一对象的信息覆盖。
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
egon = A('egg',38)
egon.cloth = '小花袄'
nezha = A('nazha',25)
print(nezha)
print(egon)
print(nezha.name)
print(egon.name)
print(nezha.cloth)
#输出:
<__main__.A object at 0x000000000526DDD8>
<__main__.A object at 0x000000000526DDD8>
nazha
nazha
小花袄
__eq__方法: 当比较两对象时,正常情况下比较的是内存地址,但在类中定义:def __eq__():
之后可控制比较结果的输出,只要一比较两个对象,如ob1==ob2,就会自动触发__eq__方法。
class A:
def __init__(self,name):
self.name = name
def __eq__(self, other):
if self.__dict__ == other.__dict__:
return True
else:
return False
ob1 = A('egon')
ob2 = A('egg')
print(ob1 == ob2)
#输出:
False
__hash__方法:只要是可哈希的,内部都调用了__hash__
方法,比较两对象的哈希值是,正常情况下比较的是内存地址,在类中定义def __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('egon','男')
b = A('egon','nv')
print(hash(a))
print(hash(b))
应用举例:
构建扑克牌的类。
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') # 2-A
suits = ['红心','方板','梅花','黑桃']
def __init__(self):
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()
print(deck[10])
print('=======')
from random import choice
print(choice(deck))
print(choice(deck))
print('=======')
from random import shuffle
shuffle(deck)
print(deck[10])
#print(deck)
print(deck[:5])
#输出:
Card(rank='4', suit='梅花')
=======
Card(rank='10', suit='方板')
Card(rank='4', suit='方板')
=======
Card(rank='3', suit='红心')
[Card(rank='Q', suit='红心'), Card(rank='K', suit='梅花'), Card(rank='Q', suit='梅花'), Card(rank='10', suit='方板'), Card(rank='K', suit='红心')]
内置函数 内置的模块 内置的基础类型 < — >类的内置方法
== < — > __eq__
len() < — > __len__
名字 和 性别 年龄不同
set集合(筛选重复值):set 依赖对象的 hash eq
有eq函数时,内存地址只有一个;
无eq函数时,内存地址有两个。
class A:
def __init__(self,name,sex,age):
self.name = name
self.sex = sex
self.age = age
#def __eq__(self, other):
# if self.name == other.name and self.sex == other.sex:
# return True
# return False
def __hash__(self):
return hash(self.name + self.sex)
a = A('egg','男',38)
b = A('egg','男',37)
print(set((a,b))) # unhashable