魔术方法(五)
问题一:__init__有什么作用?
在创建对象的时候,自动调用对创建的对象进行初始化设置的
问题二:什么是魔术方法?
在python中像__init__这类以双下滑线开头和结尾的方法,我们把它统称为魔术方法,也有人叫作魔法方法、特殊方法。
注意点:
魔术方法都是Python内部定义的(内置的),自己不要去定义__init__这类双下划线开头的方法。
问题三:创建对象,调用的第一个方法是什么?
__new__方法
定义的类默认继承object,在object父类里有个__new__()方法,这个new方法创建并返回一个新的对象,如下图:

当我们调用类的时候,会自动触发这个__new__()方法,当我们定义类的时候,没有__new__()方法,就会去object父类去查找,创建一个对象并返回。
ps: python内置函数的看不到源码,只能看到一些相关说明,内置函数全部c语言实现
class Hero(object): def __init__(self, name): self.name = name print('这是init方法') def __new__(cls, *args, **kwargs): print('这是new方法') hero = Hero('sinder') print(hero)
执行结果:

为什么创建的对象是None呢?
自己定义__new__()方法,创建对象时,自动触发自定义的__new__()方法去创建对象,但是我们自己定义的__new__()方法里没有实现如何创建对象的代码 ,所以对象是None。
所以自己重写__new__()方法时,需要返回一个对象。
class Hero(object): def __init__(self, name): self.name = name print('这是init方法') def __new__(cls, *args, **kwargs): print('这是new方法') return super().__new__(cls) hero = Hero('sinder') print(hero)
参数cls:代表对象自身
执行结果:

对象创建后才会执行__new__()
new方法的应用场景:单例模式


2、代码实现:
class MyClass(object): """单例模式类""" count = 0 instance = None def __new__(cls, *args, **kwargs): if not cls.instance: #调用父类的new方法,创建一个对象 cls.instance = object.__new__(cls) return cls.instance else: return cls.instance h1 = MyClass() h2 = MyClass() print(id(h1), id(h2))
执行结果:

3、上下文管理器
上下文管理器是一个python对象,为操作提供了额外的上下文信息,这种额外的信息,在使用with语句初始化上下文,以及完成with块中的所有代码时,才用可调用的形式。
在一个类中,只要实现了__enter__和__exit__方法,那么该类就实现了上下文管理协议。
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): print('---这个是enter方法---') return self.f def __exit__(self, exc_type, exc_val, exc_tb): self.f.close() print('---这个是exit方法---') with MyOpen('test.py', 'r', encoding='utf8') as f: print(f.read()) print('---with的代码---')
执行结果:


5、__str__方法和__repr__方法

从上图看出,print()函数输出的内容与变量输出的内容不一样。
当我们使用print()这个内置函数之后,给它传入一个对象,那么这个时候实际上是触发了这个对象的__str__,将改方法返回的内容输出到控制台。
在交互环境中,输入对象,返回的是__repr__方法中所返回的
class Hero(object): def __init__(self, name): print('这个是init方法') self.name = name def __str__(self): print('___str___') h = Hero('sinder') print(h)
执行结果:返回结果类型错误,返回的是NoneType

注意:当我们定义__str__和__repr__方法时,必须设置返回值,而且返回值必须是字符串。
设置返回值之后的正确代码:
class Hero(object): def __init__(self, name): print('这个是init方法') self.name = name def __str__(self): print('___str___') return self.name h = Hero('sinder') print(h)
执行结果:

class Hero(object): def __init__(self, name): print('这个是init方法') self.name = name # # def __str__(self): # print('___str___') # return self.name def __repr__(self): print('___repr___') return '---repr---' h = Hero('sinder') print(h)
执行结果:

__str__和__repr__触发机制:

总结:
使用str函数或者print打印对象时会优先触发str方法,没定义str方法的情况下,会再去找repr方法,如果都没有,那么就会去找父类的str方法。
使用repr方法或者交互环境下输入对象,直接触发repr方法

浙公网安备 33010602011771号