Python进阶-XVIV 类的内置方法:__str__ 、__repr__、析构函数(__del__)、双下的call,eq,new,hash 以及item相关的三个方法

类的内置方法
  它与内置函数有紧密的联系,有的内置函数就是调用的内置方法。
  在顶级父类obj中有:
  两个双下方法
    obj.__str__ str(obj)
    obj.__repr__ repr(obj)

1、__str__ 与 __repr__ 

 1 class Teacher:
 2     def __init__(self, name, salary):
 3         self.name = name
 4         self.salary = salary
 5 
 6     def __str__(self):
 7         return "Teacher's object :%s" % self.name
 8 
 9     def __repr__(self):
10         return str(self.__dict__)
11 
12     def func(self):
13         return 'wahaha'
14 
15 
16 nezha = Teacher('哪吒', 250)
17 print(nezha)  # 打印一个对象的时候,就是调用a.__str__
18 print(repr(nezha))
19 print('>>> %r' % nezha)
a.__str__ --> object
object 里有一个__str__,一旦被调用,就返回调用这个方法的对象的内存地址
l = [1,2,3,4,5] # 实例化 实例化了一个列表类的对象
print(l)
%s str() 直接打印 实际上都是走的__str__
%r repr() 实际上都是走的__repr__
repr 是str的备胎,但str不能做repr的备胎

print(obj)/'%s'%obj/str(obj)的时候,实际上是内部调用了obj.__str__方法,如果str方法有,那么他返回的必定是一个字符串
如果没有__str__方法,会先找本类中的__repr__方法,再没有再找父类中的__str__。
repr(),只会找__repr__,如果没有找父类的

内置的方法有很多,但是不一定全都在object中
 1 class Classes:
 2     def __init__(self, name):
 3         self.name = name
 4         self.student = [ ]
 5 
 6     def __len__(self):
 7         return len(self.student)  # obj中没有该方法,因为obj只存所有对象共有的!
 8 
 9     def __str__(self):
10         return 'classes'
11 
12 
13 py_s9 = Classes('九年级三班')
14 py_s9.student.append('董青')
15 py_s9.student.append('久美')
16 print(len(py_s9))
17 print(py_s9)
18 
19 # 1、__str__
20 print(str(12))  # 其实就是调用int类型的__str__方法
21 
22 
23 # 为了验证,可以来一个例子:
24 class StrDemo:
25     def __init__(self, name):
26         self.name = name
27 
28     # def __str__(self):
29     #     print('调用我的str双下方法了!')
30     #     return self.name
31     def __repr__(self):
32         print('调用我的repr双下方法了!')
33         return self.name
34 
35 
36 s = StrDemo("string")
37 print(str(s))
38 
39 # 2、__repr__
40 print(repr('1'))
41 print(repr(1))
42 # 我们将StrDemo类中的__str__方法注释掉,看看发生什么?
43 print(repr(s))
44 
45 
46 # 当一个类没有重写__str__方法,但是重写了__repr__方法,当使用str(本类实例)的时候,就调用了__repr__
47 # 即__repr__是__str__的备胎,但是反过来就不行!
View Code

 

 

2、析构函数(__del__)

功能是在回收内存中的对象,并在回收前做一些收尾工作,如打开的文件没关闭,将其关闭等!
 1 class A:
 2     def __init__(self, f):
 3         self.f = f
 4 
 5     def __del__(self):
 6         print('it deling')
 7         self.f.close()  # 析构函数: 在删除一个对象之前进行一些收尾工作
 8 
 9 
10 a = A(open('2_反射进阶.py'))
11 del a  # del 既执行了这个方法,又删除了变量
12 
13 
14 # del a   NameError: name 'a' is not defined
15 
16 # 引用计数中用到该内置方法
View Code

 

3、item相关方法:__getitem__    __setitem__    __delitem__

 1 class Person:
 2     def __init__(self, name,age,ginder):
 3         self.name = name
 4         self.age = age
 5         self.ginder = ginder
 6 
 7     def __getitem__(self, item):
 8         if hasattr(self, item):
 9             return self.__dict__[item]
10 
11     def __setitem__(self, key, value):
12         self.__dict__[key] = value
13 
14     def __delitem__(self, key):
15         print('it is calling me !')
16         self.__dict__.pop(key)
17 
18 tom = Person('tom', 22, 'male')
19 # 得到属性
20 print(tom['ginder'])  # __getitem__可以用访问字典中的元素一样访问对象的属性!
21 # 设置属性
22 tom['kind'] = 'superman'
23 print(tom.kind, tom['kind'])
24 #del tom.kind    # object 原生支持  __delattr__
25 del tom['kind']  # 通过自己实现的
26 print(tom.kind, tom['kind'])
View Code

4、__hash__        对应 hash()内置函数   

查看hash值,可以修改hash规则,是的本来有不同hash值的两个对象有一样的hash值

 1 lass Hash:
 2     def __init__(self, name):
 3         self.name = name
 4 
 5     def __hash__(self):
 6         return hash(self.name)
 7 
 8 
 9 ha_a = Hash('a_Hash')
10 hah = Hash('a_Hash')
11 print(hash(ha_a), hash(hah))  # 两个对象虽然名字一样,但是hash值不同:-9223371888545262739 148309513073
12 # 实现object中的__hash__方法,并只返回name的hash值,就相等了:-9184190014575666570 -9184190014575666570
View Code

5、__new__ 构造函数,在初始化函数前,将self构造出来。
  典型使用:单例模式(23种设计模式第一个)
  即:一个类在内存中,始终只有一个实例

  __init__ 初始化方法
  __new__ 构造方法 : 创建一个对象

 1 class Singleton():
 2     __instance = False
 3     def __init__(self, name):
 4         self.name = name
 5 
 6     def __new__(cls, *args, **kwargs):
 7         '''实现单例'''
 8         if cls.__instance:
 9             return cls.__instance
10         else:
11             cls.__instance = object.__new__(cls)
12             return cls.__instance
13 
14 a = Singleton('a')
15 a.nm = '单例'
16 b = Singleton('b')
17 print(b.nm)
18 print(id(a), id(b))  # 没有实现__new__方法前的结果是:2681905465888 2681905467232 地址不同,说明是两个对象
19 # __实现__new__方法后,即使不写具体操作,直接pass,也返回相同的地址:1760945392 1760945392
20 # 实现单例的操作后,地址变为:2491487242000 2491487242000 还是相同,即为同一对象!
View Code

6、 __eq__方法

 1 class Equal:
 2     def __init__(self, name):
 3         self.name = name
 4 
 5     def __eq__(self, other):
 6         if self.name == other.name:
 7             return True
 8 
 9 double_eq = Equal('双等于号')
10 eq = Equal('双等于号')
11 # 问:两个对象相等吗?
12 print(double_eq, eq, double_eq == eq)
13 #  <__main__.Equal object at 0x0000027726CA3828> <__main__.Equal object at 0x0000027726CA3860> False
14 # 内存地址不一样,是两个对象,所以不等,双下eq方法,是继承自顶级的object类,原来就是比较内存地址的!
15 # 实现该方法的其他类,如str,int等,改为值等就是相等了!
16 # 如何让两个相同的名字的Equal对象,变为相等了?只有重写eq方法了
17 print(double_eq == eq)
View Code

 

7、__call__ 方法

 1 class B:
 2     def __init__(self, name):
 3         self.name = name
 4 
 5     def __call__(self):
 6         for k in self.__dict__:
 7             print(k, self.__dict__[ k ])
 8 
 9 
10 B('sb')()  # 最后一个()就是在调用该类中的双下call方法!

你可能感兴趣的:(Python进阶-XVIV 类的内置方法:__str__ 、__repr__、析构函数(__del__)、双下的call,eq,new,hash 以及item相关的三个方法)