• python魔法方法


    在学习面向对象的时候,我们知道在 python 中有一类特殊的方法,叫做魔法方法,这种方法的特点如下:

    1. 方法定义的时候以两个下划线开头和两个下划线结尾:如__init____str____repr__
    2. 这类方法一般不需要我们手动调用,在满足某个条件的时候会自动调用,这个满足的条件我们可以成为调用时机

    __str__()方法

    这个类方法(str())主要的作用是在print(实例)的时候返回你指定的字符串,一般来说在定义类的时候不用重写这个方法的,但是在一些注重交互的模块类的编写上,可能会重写这个类。下面直接进入例子。

    class Car():
        def __init__(self,name):
            self.name = name
    

    接下来我们实例化这个类,并打印这个实例。

    A = Car('BNW')
    print(A)
    

    我们一般就能看到这样的结果:
    <__main__.Car object at 0x000002B249DD4E20>
    这个结果主要是告诉我们这个A是哪一个类(Car类),还有所在内存位置(0x000002B249DD4E20)
    下面我们在Car类中重写__str__方法,再打印这个A,看看会有什么差别。

    class Car():
        def __init__(self, name):
            self.name = name
    
        def __str__(self) -> str:
            text = f'这是一辆车,名字是{self.name}'
            return text
    
    
    A = Car('BNW')
    print(A)
    
    这是一辆车,名字是BNW
    

    可以看到,这个时候print(实例),将会出现我们指定好的str内容。这就是__str__()方法的用处,不过要注意,这个方法必须要保证返回的是一个str。

    对一个对象打印时,自动执行 str 方法

    class A:
    
        def __init__(self, name, age):
            self.name = name
            self.age = age
            self.sex = "男"
    
        def __str__(self):
            print(555)
            return "abc"
    
    a1 = A("尘世风", 18)
    # 对一个对象打印时,自动执行 __str__ 方法
    print(a1)
    # 运行结果:
    # 555
    # abc
    

    __len__()方法

    len()可以检测对象中某个数据得信息,只有一个参数self,用于接收当前对象,它必须有返回值,返回值必须是整数;
    当我们不使用__len__()方法检测对象时,会报TypeError: object of type ‘UseLen’ has no len()错误

    class UseLen(object):
        def __init__(self, age):
            self.age = age
            self.li = ['a', 'v', 's']
    
    U = UseLen(12)
    print(len(U))
    
    Traceback (most recent call last):
      File "D:\code\xmczapitest\test.py", line 7, in <module>
        print(len(U))
    TypeError: object of type 'UseLen' has no len()
    

    当我们使用__len__方法检测对象时,需要注意的是必须有返回值,方法中只有一个self参数

    class UseLen(object):
        def __init__(self, age):
            self.age = age
            self.li = ['a', 'v', 's']
    
        def __len__(self):
            return len(self.__dict__)
    
    U = UseLen(12)
    print(len(U))     # 2
    

    __call__ 方法

    __call__可以使得方法变成可被调用对象

    class Foo:
    
        def __init__(self):
            print("实例化一个对象时自动执行 __init__ 方法")
    
        def __call__(self, *args, **kwargs):
            print('调用实例化对象时自动触发 __call__ 方法')
    
    
    obj = Foo()     # 实例化一个对象时自动执行 __init__ 方法
    obj()           # 调用实例化对象时自动触发 __call__ 方法
    

    new() 方法

    当Python实例化一个对象时,首先调用__new__()方法构造一个类的实例,并为其分配对应类型的内存空间,该实例的内存地址就是它的唯一标识符。然后再调用__init__()方法对实例进行初始化,通常是对该实例的属性进行初始化
    以下用几个实例来说明:
    实例1:先调用__new__()方法再调用__init__()方法

    class Person(object):
    
        def __new__(cls):
            print("__new__ called")
            return super().__new__(cls)
    
        def __init__(self):
            print("__init__ called")
    
    
    a = Person()
    

    结果

    __new__ called
    __init__ called
    

    实例2:new()方法构造一个类实例,并将该实例传递给自身的__init__()方法,即__init__()方法的self参数。

    class Person(object):
    
        def __new__(cls):
            print("__new__ called")
            instance = super().__new__(cls)
            print(type(instance))
            print(instance)
            print(id(instance))
            return instance
    
        def __init__(self):
            print("__init__ called")
            print(id(self))
    
    
    b = Person()
    

    结果

    __new__ called
    <class '__main__.Person'>
    <__main__.Person object at 0x0000026D76844DC0>
    2669163072960
    __init__ called
    2669163072960
    

    实例3:如果__new__()方法不返回任何实例的话,init()方法将不会被调用。

    class Person(object):
    
        def __new__(cls):
            print("__new__ called")
    
        def __init__(self):
            print("__init__ called")
    
    
    c = Person()
    

    结果:

    __new__ called
    

    实例4:如果__new__()方法返回一个其他类的实例的话,那它自身的__init__()方法将不会被调用。而且,new()方法将会初始化一个其他类的对象。

    class Animal(object):
    
        def __init__(self):
            pass
    
    
    class Person(object):
    
        def __new__(cls):
            print("__new__ called")
            return Animal()
    
        def __init__(self):
            print("__init__ called")
    
    
    d = Person()
    print(type(d))
    print(d)
    

    结果:

    __new__ called
    <class '__main__.Animal'>
    <__main__.Animal object at 0x0000022BDDEEF400>
    

    实例5:如果重写__new__()方法时,除了cls参数外不再设置其他参数的话,将无法用__init__()方法来设置初始化参数。

    class Person(object):
    
        def __new__(cls):
            print("__new__ called")
            instance = super().__new__(cls)
            return instance
    
        def __init__(self, name):
            print("__init__ called")
            self.name = name
    
    
    e = Person("Alice")
    print(e.name)  # TypeError: Person.__new__() takes 1 positional argument but 2 were given
    

    实例6:在重写__new__()方法时,需要在参数中加入*args,**kwargs,或者显式地加入对应的参数,才能通过__init__()方法初始化参数。

    class Person(object):
    
        def __new__(cls, *args,**kwargs):  # Or def __new__(cls, name)
            print("__new__ called")
            instance = super().__new__(cls)
            return instance
    
        def __init__(self, name):
            print("__init__ called")
            self.name = name
    
    
    e = Person("Alice")
    print(e.name)
    

    结果:

    __new__ called
    __init__ called
    Alice
    
  • 相关阅读:
    PHP 使用 header()实现重定向
    PHP抑制符号 @
    PHP自动加载spl_autoload_register
    打开PHP错误提示
    通过htaccess使用伪静态
    用反引号(``)标注表明或者字段名,防止跟 mysql关键字冲突
    Bootstrap 弹出框(Popover)插件
    jQuery 的 validator 验证,以及添加自定义验证规则。
    线程与并发(一) 多线程基础
    SpringCloud入门
  • 原文地址:https://www.cnblogs.com/feng0815/p/16456029.html
Copyright © 2020-2023  润新知