文章目录
python魔术方法
参考文档:https://www.cnblogs.com/nmb-musen/p/10861536.html
1. 构造方法__new__
构造方法包括创建对象和初始化对象,在python当中,分为两步执行:先执行__new__方法,然后执行__init__方法。
+ __init__是当实例对象创建完成后被调用的,然后设置对象属性的一些初始值。
+ __new__是在实例创建之前被调用的,因为它的任务就是创建实例然后返回该实例,是个静态方法。
也就是,__new__在__init__之前被调用,__new__的返回值(实例)将传递给__init__方法的第一个参数,然后__init__给这个实例设置一些参数
class A:
def __new__(cls, *args, **kwargs): # 至少要有一个参数cls,由Python解释器自动提供
cls.instance = object.__new__(cls)
print('这是__new__方法')
print(cls)
return cls.instance # 必须要有返回值,返回实例化出来的实例
def __init__(self): # 有一个参数self,就是这个__new__返回的实例,__init__在__new__的基础上可以完成一些其它初始化的动作
print('这是__init__方法')
print(self) # 不需要返回值
a =A()
>
这是__new__方法
<class '__main__.A'>
这是__init__方法
<__main__.A object at 0x7fc74c95bac0>
2. 单例模式
单例模式就是确保一个类只有一个实例
# 同一个类多次实例化后会获取多个不同的实例
class Demo:
def __init__(self):
pass
def demo(self):
pass
a = Demo()
print(id(a))
b = Demo()
print(id(b))
>
140598884625520
140598884683936
单例模式实现一:__new__方法
class Singleton(object):
__instance = None # 设置一个类属性来标记这个类没有创建过
def __new__(cls, *args, **kwargs):
if not cls.__instance:
cls.__instance = object.__new__(cls)
return cls.__instance
c = Singleton()
c.token = '12345'
print(id(c))
d = Singleton()
print(id(d))
print(d.token)
>
140710293916352
140710293916352
12345
单例模式实现二:装饰器方式
def singleton(cls):
# 单下划线的作用是这个变量只能在当前模块里访问,仅仅是一种提示作用
# 创建一个字典用来保存类的实例对象
_instance = {}
def _singleton(*args, **kwargs):
# 先判断这个类有没有对象
if cls not in _instance:
_instance[cls] = cls(*args, **kwargs) # 创建一个对象,并保存到字典当中
# 将实例对象返回
return _instance[cls]
return _singleton
@singleton
class A(object):
a = 1
def __init__(self, x=0):
self.x = x
print('这是A的类的初始化方法')
a1 = A(2)
a2 = A(3)
print(id(a1), id(a2))
>
这是A的类的初始化方法
140683534546160 140683534546160
3. 方法__str__和__repr__
交互式运行时,print()方式调用的是__str__方法,直接输入变量调用的是__repr__方法
>>> a = '123'
>>> print(a) # 触发__str__方法
123
>>> a # 触发__repr__方法
'123'
__str__和__repr__方法必须返回str类型
print()、str()、format()方法均可调用__str__
repr()可调用__repr__方法
class DemoStr(object):
def __str__(self):
print('__str__方法')
return '__str__'
def __repr__(self):
# print('__repr__')
return '__repr__方法'
s = DemoStr()
print(s)
str(s)
format(s)
repr(s)
>
__str__方法
__str__
__str__方法
__str__方法
__repr__
当调用__str__方法不存在,调用的是__repr__方法
class DemoStr(object):
# def __str__(self):
# print('__str__方法')
# return '__str__'
def __repr__(self):
print('__repr__')
return '__repr__方法'
s = DemoStr()
print(s)
str(s)
format(s)
>
__repr__
__repr__方法
__repr__
__repr__
当调用时__repr__方法不存在,调用的是父类的__repr__方法
class DemoStr(object):
pass
s = DemoStr()
print(s)
>
<__main__.DemoStr object at 0x7f88ee7ba160>
总结:一般来说__str__的可读性更强,而__repr__的返回结果更具有准确性,更加的适合开发者
4. 方法__call__
python中万物皆对象。函数之所以可以被调用,是因为有__call__方法
class DemoStr(object):
pass
s = DemoStr()
s()
>
TypeError: 'DemoStr' object is not callable
class DemoStr(object):
def __call__(self):
print('__call__方法被调用了')
s = DemoStr()
s()
>
__call__方法被调用了
类装饰器实现
class Decorator(object):
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print('装饰器功能')
return self.func(*args, **kwargs)
@Decorator
def fun(a, b):
print('原函数功能')
return a + b
a = fun(2, 3)
print(a)
>
装饰器功能
原函数功能
5
5. 上下文管理器
上下文管理器
:在一个类里实现了__enter__和__exit__方法,这个类的实例就是一个上下文管理器
# 上下文管理器表达式标准语句体
with 上下文管理器 as f:
语句体
当with遇到上下文管理器,就会在执行语句体之前,先执行上下文管理器的__enter__方法,然后再执行语句体,执行完语句体后,最后执行__exit__方法
class Demo:
def __init__(self):
print('首先使用__init__实例化一个对象')
def __enter__(self):
print('执行语句体之前,先执行上下文管理器的__enter__方法进入')
def __exit__(self, exc_type, exc_val, exc_tb):
print('执行完语句体后,最后执行__exit__方法退出')
res_obj = Demo()
# with + 上下文管理器
with res_obj:
print('哈哈哈哈')
>
首先使用__init__实例化一个对象
执行语句体之前,先执行上下文管理器的__enter__方法进入
哈哈哈哈
执行完语句体后,最后执行__exit__方法退出
自定义Open上下文管理器
class Open:
def __init__(self, filename, mode , encoding='utf-8'):
self.filename = filename
self.mode = mode
self.encoding = encoding
def __enter__(self):
print('打开文件')
self.f = open(self.filename, self.mode, encoding=self.encoding)
return self.f
def __exit__(self, exc_type, exc_val, exc_tb):
print('关闭文件')
self.f.close()
with Open('mq.py', 'r') as f:
print(f)
>
打开文件
<_io.TextIOWrapper name='mq.py' mode='r' encoding='utf-8'>
关闭文件
- 上下文管理器实现mysql连接:https://blog.csdn.net/qq_25672165/article/details/111076772
6.算术方法
class SuanShu(object):
def __init__(self, num):
self.num = num
#运算符重载
def __add__(self, other): # self,other 都是对象
print(self.num)
print(other.num)
return SuanShu(self.num + other.num)
def __str__(self):
return "num = " + str(self.num)
res1 = SuanShu(1)
res2 = SuanShu(2)
print(res1 + res2) #res1 + res2 ==== res1.__add__(res2)
#print(res1.__add__(res2))
print(res1)
print(res2)
>
1
2
num = 3
num = 1
num = 2
7. 方法__dict__
__dict__可获取类和对象的所有成员
1. 子类比父类少了'__dict__'和'__weakref__'属性
2. 对象默认无成员,可自定义成员
class DemoA:
pass
class DemoB(DemoA):
pass
a = DemoA()
b = DemoB()
b.name ='123'
print(DemoA.__dict__)
print(DemoB.__dict__)
print(a.__dict__)
print(b.__dict__)
>
{'__module__': '__main__', '__dict__': <attribute '__dict__' of 'DemoA' objects>, '__weakref__': <attribute '__weakref__' of 'DemoA' objects>, '__doc__': None}
{'__module__': '__main__', '__doc__': None}
{}
{'name': '123'}
8. 方法__solts__
Python默认用一个字典来保存对象的实例属性,因此我们可以自定义新的实例属性。__solts__方法可用来限制属性,并节约内存(不会再自动生成__dict__等属性)
class DemoA:
__slots__ = ['name']
pass
a = DemoA()
a.age ='18'
>
Traceback (most recent call last):
File "/Users/whtest/Desktop/Hrunner/HrunDemo/demo.py", line 6, in <module>
a.age ='18'
AttributeError: 'DemoA' object has no attribute 'age'
9. 方法__*attr__
同时定义__getattribute__和__getattr__时,__getattr__方法不会再被调用,除非显示调用__getattr__方法或引发AttributeError异常
### 方法__*attr__
同时定义__getattribute__和__getattr__时,__getattr__方法不会再被调用,除非显示调用__getattr__方法或引发AttributeError异常
```python
class Demo:
def __getattribute__(self, item):
print('查找属性时触发__getattribute__')
return '调用__getattribute__方法获取属性'
def __getattr__(self, item):
# 存在__getattribute__方法时__getattr__方法永远不会被调用
print('属性不存在时触发__getattr__')
return '调用__getattr__方法获取属性,属性不存在'
def __setattr__(self, key, value):
print('设置属性时触发__setattr__')
def __delattr__(self, item):
print('删除属性时触发__delattr__')
a = Demo()
print(a.name)
a.name = 'zhangsan'
print(a.name)
del a.name
>
查找属性时触发__getattribute__
调用__getattribute__方法获取属性
设置属性时触发__setattr__
查找属性时触发__getattribute__
调用__getattribute__方法获取属性
删除属性时触发__delattr__