Python之魔术方法


什么是魔术方法

Python中,所有以两个下划线开头并以两个下划线结尾的方法,都统称“Magic Method”,中文称为魔术方法或魔法方法。魔术方法会在对类的某个操作时自动调用,而不需要编码人员操作调用。

魔术方法都是python内部定义的,自己是不可以定义__plscript__这类双下划线包裹的方法的。

常用的魔术方法

__init__

通常把__init__方法称为构造函数或初始化方法,只要实例化一个对象,这个方法就会在对象被初始化时自动调用。初始化对象时是可以传入参数的,这些参数会自动传入__init__方法中,可以通过重写这个方法来自定义对象的初始化操作。

class MyClass(object):

    def __init__(self):
        print("init 方法")

    def myfunc(self):
        print("func")


MyClass()

执行上面的代码

init 方法

上面代码只是初始化了MyClass并没有调用任何方法,但执行结果,输出了__init__方法的内容。这里就说明了,在进行类初始化时会自动执行__init__方法,这里在MyClass中进行了定义。而实际上MyClass的父类object是定义了__init__方法的。(所有类都继承于object类,可以省略不写)

自己定义的类中,定义了__init__即相当于重写了父类的__init__方法。若自已定义的类中没有,则执行父类的__init__方法。

在定义__init__时还可以传递参数,进行初始化。

class MyClass(object):

    def __init__(self, name, age):
        print("init 方法")
        self.name = name
        self.age = age
        print("{},{}".format(name, age))

    def myfunc(self):
        print("func")

MyClass('laobai', 18)

执行代码

init 方法
laobai,18

__new__

__new__是一个由object类提供的内置的静态方法,它的作用是调用类时创建对象及分配内存空间。也就是在类进行调用时,先通过__new__创建并返回对象,再执行__init__进行对象的初始化。

class MyClass(object):

    def __init__(self):
        print("init 方法")

    def myfunc(self):
        print("func")


obj = MyClass()
print(obj)

执行结果:

init 方法
<__main__.MyClass object at 0x10317f070>

这个例子中没有__new__方法,会直接调用父类的__new__创建对象分配内存空间并返回对象,再执行自己定义的__init__方法。

下面自己定义一个__new__方法

class MyClass(object):

    def __new__(cls):
        print("new 方法")

    def __init__(self):
        print("init 方法")

    def myfunc(self):
        print("func")


obj = MyClass()
print(obj)

执行代码

new 方法
None

结果只执行了__new__方法,没有执行__init__方法,且实例化的对象结果为None。这是因为__new__方法还需要返回创建的对象,有了对象,__init__才能进行初始化。

class MyClass(object):

    def __new__(cls):
        print("new 方法")
        return super().__new__(cls)

    def __init__(self):
        print("init 方法")

    def myfunc(self):
        print("func")


obj = MyClass()
print(obj)

再次执行

new 方法
init 方法
<__main__.MyClass object at 0x105080eb0>

即先执行自定义的__new__方法并返回父类的__new__进行对象的创建,然后执行自定义的__init__方法,最后打印输出对象。

__new__方法很少需要进行重写,若重写,返回父类的__new__语法比较固定return super().__new__(cls)

单例模式

单例模式是通过__new__方法的一个特殊应用。通常情况下,一个类可以实例化无限多个对象,而单例模式,就是这个类只能实例化一个对象。大概思路就是创建对象(调用__new__)时,判断是否创建过对象,没有创建过就返回object类的__new__方法,若已经创建过对象,那么返回前一次创建的对象。保证创建的对象只有一个。

通常情况下:

class MyClass:

    def __new__(cls, *args, **kwargs):
        return super().__new__(cls)

a = MyClass()
b = MyClass()
c = MyClass()

print(a, b, c)

执行

<__main__.MyClass object at 0x1013bd0a0> <__main__.MyClass object at 0x1013bdd90> <__main__.MyClass object at 0x1013bd580>

可以看到,3个对象的内存地址不一样,即完全不同的3个对象。

单例模式:

class MyClass:
    __instance = None

    def __new__(cls, *args, **kwargs):
        # 判断类是否实例化过对象
        if not cls.__instance:
            cls.__instance = super().__new__(cls)
        return cls.__instance


a = MyClass()
b = MyClass()
c = MyClass()

print(a, b, c)

执行

<__main__.MyClass object at 0x10e364f10> <__main__.MyClass object at 0x10e364f10> <__main__.MyClass object at 0x10e364f10>

可以看到,3个对象的内存地址都是0x10e364f10,即为一个对象。


文章作者: 老百
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 老百 !
 上一篇
Python单元测试框架——unittest(一) Python单元测试框架——unittest(一)
unittest单元测试框架是受到JUnit的启发,与其他语言中的主流单元测试框架有着相似的风格。其支持测试自动化,配置共享和关机代码测试。支持将测试样例聚合到测试集中,并将测试与报告框架独立。
2022-11-19
下一篇 
JSONPath使用介绍 JSONPath使用介绍
JSONPath是一种简单的方法来提取给定JSON文档的部分内容。JSONPath是跨语言的,很多语言都可以使用jsonpath,如Javascript,Python和PHP,Java等。
2022-11-13
  目录