在该篇章中所说的 对象 都是 类所返回的对象
1. __str__
- 一定要有返回值,且返回值一定要是字符串
- 当打印一个对象 或者 使用 str() 内置函数且所传入的值是一个对象的时候 就会执行 __str__ 方法
- 执行顺序: 首先在类中找看有没有 __str__ 方法,如果没有再找 __repr__ 方法执行,最后才在 object 中找 __str__ 且 object 中的 __str__ 方法返回的是对象的内存地址
class Tearch:
def __str__(self):
print('__str__函数被执行了')
return '这是一个教师类'
t = Tearch()
str(t) # __str__函数被执行了
print(t) # 这是一个教师类
# 如果类中没有 __str__ 方法打印出来的是 <__main__.Tearch object at 0x000001750C651C88>
2.__unicode__
- 和 __str__ 的功能是一样的,只不过 __unicode__ 是在 Python2 中使用
class Tearch:
def __unicode__(self):
print('__unicode__函数被执行了')
return '这是一个教师类'
t = Tearch()
str(t) # __unicode__函数被执行了
print(t) # 这是一个教师类
# 如果类中没有 __unicode__ 方法打印出来的是 <__main__.Tearch object at 0x000001750C651C88>
3.__repr__
- 一定要有返回值,且返回值一定要是字符串
- 当使用了 repr() 内置函数且所传入的值是一个对象的时候就会执行 __repr__
- 当打印一个对象 或者 使用 str() 内置函数且所传入的值是一个对象的时候 如果类中没有 __str__ 方法就会执行 __repr__ 方法
- 当使用了 repr() 内置函数且所传入的值是一个对象的时候,如果类中没有 __repr__ 方法,只有 __str__ 方法且不会执行 __str__ 方法
class Tearch:
def __repr__(self):
print('__repr__函数被执行了')
return '这是一个教师类'
t = Tearch()
str(t) # __repr__函数被执行了
repr(t) # __repr__函数被执行了
print(t) # 这是一个教师类 -> 当打印一个对象的时候如果类中没有 __str__ 方法就会执行 __repr__ 方法
print(repr(t)) # 这是一个教师类 -> 当打印一个对象且执行了 repr() 内置函数的时候就会执行 __repr__
4. __len__
- 当使用 len() 内置函数且所传入的值是一个对象的时候就会执行 __len__
# 使用场景: 如果有一个教室类,且当我想打印类所返回的对象长度的时候,我想知道该对象中有多少个学生
class Classes:
def __init__(self):
self.student = ['Kevin', 'Yeung', 'Amy']
def __len__(self):
return len(self.student)
c = Classes()
print(len(c))
5. __del__
- 在删除一个对象之前执行 __del__ 方法
class File:
def __init__(self):
self.f = open('log.txt', encoding='utf-8')
def __del__(self):
print('__del__函数被执行')
self.f.close()
f = File()
del f
print(f) # 报错,对象已被删除
6. __call__ -> 常用(很多 Python 源码都会用到它)
- 在对象后面加上 () 就会执行 __call__ 方法
class Dic:
def __init__(self):
self.name = 'Kevin'
self.age = 18
self.height = 175
def __call__(self, data):
'''
打印这个对象的所有属性
:param data:
:return:
'''
print(data)
for k in self.__dict__:
print(self.__dict__[k])
# 写法一
d = Dic()('接收外部传入的数据')
# 写法二
d1 = Dic()
d1('接收外部传入的数据')
7. item 系列 -> 以操作字典的方式去操作类中的属性
- __getitem__ -> 以获取字典值得形式去获取类中的值
class Foo:
def __init__(self, name, age):
self.name = name
self.age = age
def __getitem__(self, item):
if hasattr(self, item):
# return self.__dict__[item] # 写法一
return getattr(self, item) # 写法二
f = Foo('Kevin', 22)
print(f['name']) # Kevin -> 当以调用字典的方式去调用类中的属性的时候就会执行 __getitem__
- __setitem__ -> 以修改字典的方式去修改类中的属性
class Foo:
def __init__(self, name, age):
self.name = name
self.age = age
def __getitem__(self, item):
if hasattr(self, item):
return self.__dict__[item]
def __setitem__(self, key, value):
# self.__dict__[key] = value # 写法一
setattr(self, key, value) # 写法二
f = Foo('Kevin', 22)
f['name'] = 'Yeung' # 当以修改字典的方式去修改类中的属性的时候就会执行 __setitem__
print(f['name']) # Yeung
- __delitem__ -> 以删除字典中的值的方式去删除类中的属性
class Foo:
def __init__(self, name, age):
self.name = name
self.age = age
def __delitem__(self, key):
# del self.__dict__[key] # 写法一
delattr(self, key) # 写法二
f = Foo('Kevin', 22)
del f['name'] # 当以删除字典中的值的方式去删除类中的属性的时候就会执行 __delitem__
print(f.__dict__) # {'age': 22}
8. __new__ -> 常用
- 构造函数
- 作用: 创建 self 对象
- 在执行__init__之前先会执行__new__
class Foo:
def __new__(cls, *args, **kwargs):
print('in __new__ fn')
return object.__new__(cls)
def __init__(self, name):
self.name = name
f = Foo('Kevin') # 打印了 in __new__ fn -> 在实例化的时候首先会进入 __new__ 方法创建 self 对象
print(f.name)
- __new__ 一般用在设计模式
- 单例模式
- 一个类始终只有一个实例
- 当你第一次实例化这个类的时候 就创建一个实例化的对象,当你之后再来实例化的时候 就用之前创建的对象
class Person:
__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
k = Person('Kevin', 22)
y = Person('Yeung', 18)
print(k.name) # Yeung
print(y.name) # Yeung
print(k) # <__main__.Person object at 0x0000028763FC1FD0>
print(y) # <__main__.Person object at 0x0000028763FC1FD0>
print(k == y) # True
- __new__ 方法的返回值决定了实例化出来的对象是什么
- 通俗理解: __new__ 返回了什么那么实例化出来的就是什么
class Foo:
def __new__(cls, *args, **kwargs):
return 123
obj = Foo()
print(obj) # 123
class Bar:
pass
class Foo:
def __new__(cls, *args, **kwargs):
return Bar()
obj = Foo() # 实际上得到的是 Bar 类的实例化对象
print(obj) # <__main__.Bar object at 0x000001A9FCFEFB00>
9. __getattr__
- 当调用类中不存在的属性和方法的时候就会执行 __getattr__ 方法
class Foo:
def __init__(self):
self.name = 'Kevin'
def __getattr__(self, item):
print(item) # age -> 属性名
return '类中不存在该属性'
k = Foo()
print(k.name) # Kevin
print(k.age) # 类中不存在该属性
10. __setattr__
- 不要轻易的使用该方法,使用不当会导致设置了该方法的类无法设置属性值,因为当设置了__setattr__方法,就代表已经覆盖了object的__setattr__方法了
- 当添加或修改对象属性的时候就会触发 __setattr__ 方法
class Foo:
def __init__(self):
self.name = 'Kevin'
def __setattr__(self, key, value):
print(key, value)
"""
执行结果:
name Kevin
age 10
"""
k = Foo()
k.age = 10
- 注意: 在 __setattr__ 方法中是无法获取 __init__ 中的属性值,因为此时 __init__ 还没有执行 __setattr__(因为: 当设置了__setattr__方法,就代表已经覆盖了object的__setattr__方法了)
class Foo:
def __init__(self):
self.name = 'Kevin'
def __setattr__(self, key, value):
print(self.name) # 无法获取报错,因为此时 __init__ 还没有执行 __setattr__
print(key, value)
k = Foo()
k.age = 10
- 在 __setattr__ 中获取 __init__ 中属性值的解决方法
class Foo(object):
def __init__(self):
object.__setattr__(self, 'name', 'Kevin') # 调用父类object类中的__setattr__方法设置值
def __setattr__(self, key, value):
print(self.name) # Kevin
print(key, value) # age 10
k = Foo()
k.age = 10
11. __delattr__
- 当删除类中属性的时候就会执行 __delattr__ 方法
class Foo(object):
def __init__(self):
self.name = 'Kevin'
self.age = 18
def __delattr__(self, item):
print(item) # age
print("你正在删除一个属性")
return super().__delattr__(item) # 调用父类的 __delattr__ 方法删除属性
k = Foo()
del k.age
12. __eq__
- 当判断两个对象是否相等的时候就会执行 __eq__ 方法
# 使用场景:
# 一般情况下比较两个相同属性的对象的时候返回值是 False,因为在比较两个对象是否相等的时候是比较它们的内存地址,
# 如果想比较当两个对象的属性都相等的时候比较的结果返回 True 的时候就要使用 __eq__ 实现
class Foo:
def __init__(self, name, age):
self.name = name
self.age = age
def __eq__(self, other): # self 代表第一对象,other 代表第二对象
if self.__dict__ == other.__dict__:
return True
else:
return False
k = Foo('Kevin', 22)
y = Foo('Kevin', 22)
print(k == y) # True
# 如果不使用 __eq__ 返回值是 False
13. __hash__
- 当使用 hash() 内置函数且所传入的值是一个对象的时候就会执行 __hash__
class Foo:
def __init__(self, name, age):
self.name = name
self.age = age
def __hash__(self):
print('in __hash__')
return hash(str(self.name) + str(self.age))
k = Foo('Kevin', 22)
y = Foo('Kevin', 22)
print(hash(k))
print(hash(y))
# 面试题:有84个对象且对这84个对象中的 name 和 sex 相同的对象进行去重
# 使用 set() 方法去重 且 set() 方法的执行机制是 __hash__ __eq__
class Person:
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
else:
return False
def __hash__(self):
return hash(self.name + self.sex)
p_lst = []
for i in range(84):
p_lst.append(Person('Kevin', '男', i))
s = set(p_lst)
print(s) # {<__main__.Person object at 0x000001618E2D1FD0>}
14. __class__
- 获取/查看该对象所在的类
class Foo:
def __init__(self):
self.name = 'Kevin'
def fn(self):
print(self.__class__) # <class '__main__.Foo'>
k = Foo()
k.fn()
print(k.__class__) # <class '__main__.Foo'>
15. __mro__
- 查看类的继承顺序
class A(object):
pass
class B(A):
pass
class C(B):
pass
print(C.__mro__) # (<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
16. __dict__
- 查看类中的所有属性和方法
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def class_fn(self, other_data):
print(self.name)
print(self.age)
print(other_data)
print('类的方法')
p = Person('Kevin', 22)
print(Person.__dict__) # {'__module__': '__main__', '__init__': <function Person.__init__ at 0x000002439FA29D08>, 'class_fn': <function Person.class_fn at 0x000002439FA29C80>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None}
- 查看类中的所有属性
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def class_fn(self, other_data):
print(self.name)
print(self.age)
print(other_data)
print('类的方法')
p = Person('Kevin', 22)
print(p.__dict__) # {'name': 'Kevin', 'age': 22}
- 通过 __dict__ 对类的属性进行增删改查
- 增
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
p = Person('Kevin', 22)
print(p.__dict__) # {'name': 'Kevin', 'age': 22}
p.__dict__['height'] = 175
print(p.__dict__) # {'name': 'Kevin', 'age': 22, 'height': 175}
- 删
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
p = Person('Kevin', 22)
print(p.__dict__) # {'name': 'Kevin', 'age': 22}
p.__dict__.pop('age')
print(p.__dict__) # {'name': 'Kevin'}
- 改
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
p = Person('Kevin', 22)
print(p.__dict__) # {'name': 'Kevin', 'age': 22}
p.__dict__['age'] = 18
print(p.__dict__) # {'name': 'Kevin', 'age': 18}
- 查
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
p = Person('Kevin', 22)
print(p.__dict__['name']) # Kevin
17. __slots__
- 设置当前对象能访问到的属性
- 当定义了__slots__后,__slots__中定义的变量变成了类的描述符,相当于java,c++中的成员变量声明
- 注意
- 类的实例只能拥有__slots__中定义的变量,不能再增加新的变量
- 定义了__slots__后,就不再有__dict__
class Foo:
__slots__ = ['name', 'age']
def __init__(self):
self.name = 'Kevin'
self.age = 22
obj = Foo()
print(obj.name) # Kevin
print(obj.age) # 22
- 错误示范
class Foo:
__slots__ = ['name']
def __init__(self):
self.name = 'Kevin'
self.age = 22
obj = Foo()
print(obj.name)
print(obj.age)
print(obj.__dict__)
18. __iter__
- 当对象被循环的时候就会执行 __iter__ 方法,且必须返回一个迭代器或生成器
- 将实例化的对象变成一个可迭代对象
- 返回值: 迭代器 或 生成器
class Foo:
def __iter__(self):
return iter([1, 2, 3]) # 必须返回一个迭代器或生成器
iterable_obj = Foo() # 实例化可迭代对象
# 循环可迭代对象
for num in iterable_obj:
print(num)
class Foo:
def __iter__(self):
# 必须返回一个迭代器或生成器
yield 1
yield 2
yield 3
iterable_obj = Foo() # 实例化可迭代对象
# 循环可迭代对象
for num in iterable_obj:
print(num)
19. __add__
- 当对象进行加法运算的时候就会执行 __add__ 方法
class Foo:
def __add__(self, other):
print(other) # 5
return other + 10
obj = Foo()
num = obj + 5
print(num) # 15
20. __sub__
- 当对象进行减法运算的时候就会执行 __sub__ 方法
class Foo:
def __sub__(self, other):
print(other) # 5
return 20 - other
obj = Foo()
num = obj - 5
print(num) # 15
21.__enter__ 和 __exit__
- 当 with 一个对象的时候就会执行 __enter__ 和 __exit__
- __enter__ : 在执行 with 代码块里面的代码之前执行
- __exit__ : 在执行完 with 代码块里面的代码后执行
class Foo:
def __enter__(self):
print('enter')
def __exit__(self, exc_type, exc_val, exc_tb):
print('exit')
obj = Foo()
with obj:
print(123)
"""
执行结果:
enter
123
exit
"""