__init__
:在创建对象的时候,自动调用对 创建的对象 进行初始化设置的 魔术方法:以双下划线开头,双下划线结尾的方法
@staticmethod # known case of __new__
def __new__(cls, *more): # known special case of object.__new__
""" Create and return a new object. See help(type) for accurate signature. """
pass
从源码可以看出,__new__
方法的作用是创建然后返回一个对象
class Hero(object):
def __init__(self, name):
print('这个是init方法')
self.name = name
def __new__(cls, *args, **kwargs):
# 创建对象时第一步做的就是__new__方法
print('这个是new方法')
return super().__new__(cls)
h1 = Hero('zx')
print(h1)
print(h1.name)
"""
这个是new方法
这个是init方法
<__main__.Hero object at 0x1033b1f60>
zx
"""
类每次实例化的时候都会创建一个新的对象,如果要求类只能被实例化一次该怎么做?
普通模式:
class Hero(object):
def __init__(self):
print('这个是init方法')
h1 = Hero()
h2 = Hero()
print(id(h1), id(h2)) # 4328290400 4340056528
单例模式:
第一次创建对象存起来,之后创建对象的时候直接返回第一次创建的对象
实现思路:
new
方法中class MyClass(object):
count = 0
instance = None
def __new__(cls, *args, **kwargs):
if cls.count == 0:
# 调用父类的__new__方法创建一个对象
cls.instance = object.__new__(cls)
cls.count += 1
return cls.instance
h = MyClass()
h1 = MyClass()
h2 = MyClass()
h3 = MyClass()
print(id(h), id(h1), id(h2), id(h3)) # 4349229152 4349229152 4349229152 4349229152
# 精简
class MyClass(object):
instance = None
def __new__(cls, *args, **kwargs):
if not cls.instance:
# 调用父类的__new__方法创建一个对象
cls.instance = object.__new__(cls)
return cls.instance
上下文管理器:上下文管理器是一个python对象,为操作提供额外的上下文信息。这种额外的信息,使用with语句初始化上下文,以及完成with块中的所有代码时,采用可调用的形式 with关键字:启动对象的上下文管理器
object.enter(self)
输入与次对象相关的运行时上下文。如果存在的话,with语句将绑定该方法的返回值到该语句的as子语句中指定的目标
object.exit(self, exc_type, exc_val, exc_tb)
with open('0814.py', 'r', encoding='utf8') as f:
content = f.read()
print(content)
class MyOpen(object):
def __enter__(self):
print('enter') # 1
def __exit__(self, exc_type, exc_val, exc_tb):
print('exit') # 3
with MyOpen() as f:
print(f) # 2
"""
enter 1
None 2
exit 3
"""
class MyOpen(object):
def __enter__(self):
print('enter') # 1
return 999 # 2
def __exit__(self, exc_type, exc_val, exc_tb):
print('exit') # 3
with MyOpen() as f:
print(f) # 2
"""
enter 1
999 2
exit 3
"""
自己实现的文件操作上下文管理器
class MyOpen(object):
def __init__(self, file_name, method, encoding):
self.file_name = file_name
self.method = method
self.encoding = encoding
self.f = open(self.file_name, self.method, encoding=self.encoding)
def __enter__(self):
return self.f
def __exit__(self, exc_type, exc_val, exc_tb):
self.f.close()
with MyOpen('0814.py', 'r', encoding='utf8') as f:
print(f.read())
exc_type # 异常类型
exc_val # 异常值
exc_tb # 异常回溯追踪
class MyOpen(object):
def __init__(self, file_name, method, encoding):
self.file_name = file_name
self.method = method
self.encoding = encoding
self.f = open(self.file_name, self.method, encoding=self.encoding)
def __enter__(self):
return self.f
def __exit__(self, exc_type, exc_val, exc_tb):
self.f.close()
print(exc_type) # <class 'NameError'>
time.sleep(0.5)
print(exc_val) # name 'a' is not defined
time.sleep(0.5)
print(exc_tb)
"""
Traceback (most recent call last):
File "/Users/zhongxin/Desktop/py/zx/05/0814_2.py", line 34, in <module>
print(a)
NameError: name 'a' is not defined
"""
with MyOpen('0814.py', 'r', encoding='utf8') as f:
print(a)
执行顺序:实例化(__init__
)----> 执行__enter__
---->执行with中的代码----->执行__exit__
>>> a = 'abc'
>>> print(a)
abc
>>> a
'abc'
当我们使用print()这个内置函数之后,给他传入一个对象,实际上是触发了它的
__str__
方法,将方法返回的内容输出到控制台
class Hero(object):
def __init__(self, name):
self.name = name
h = Hero('zx')
print(h) # <__main__.Hero object at 0x103295908>
class Hero(object):
def __init__(self, name):
self.name = name
def __str__(self):
print('STR') # 1
return '666' # 2
h = Hero('zx')
print(h)
"""
STR 1
666 2
"""
在交互环境中,输入对象,返回的是
__repr__
方法中所返回的内容
str
方法str
方法repr
方法class Hero(object):
def __init__(self, name):
self.name = name
def __str__(self):
return self.name
h = Hero('zx')
print(h) # zx
print(str(h)) # zx
print(repr(h)) # <__main__.Hero object at 0x1031c7860>
__repr__
是__str__
的备胎,当没有__str__
的时候调用__repr__
,反过来不会
__add__
:相加sub
:减法mul
:乘法stuediv
:除法floordiv
:整除mod
:取余class MyStr():
def __init__(self, value):
self.value = value
def __str__(self):
return self.value
def __add__(self, other):
return f'{self}{other}'
def __sub__(self, other):
return f'{self}-{other}'
v1 = MyStr('aaa')
v2 = MyStr('bbb')
print(v1 + v2) # aaabbb
print(v1 - v2) # aaa-bbb
多个连续相加
class MyStr():
def __init__(self, value):
self.value = value
def __str__(self):
return self.value
def __add__(self, other):
return MyStr(f'{self}{other}')#⚠️
v1 = MyStr('aaa')
v2 = MyStr('bbb')
v3 = MyStr('ccc')
print(v1 + v2 + v3) # aaabbbccc
一个没啥用的减法实现
class MyStr():
def __init__(self, value):
self.value = value
def __str__(self):
return self.value
def __add__(self, other):
return MyStr(f'{self}{other}')
def __sub__(self, other):
return MyStr(self.value.replace(other.value, ''))
v1 = MyStr('aaa')
v2 = MyStr('bbb')
v12 = v1 + v2
print(v12)
print(v12 - v1)