• 【python基础】魔术方法


      魔术方法:就是类中的方法(预定义的方法),在某个特定的时机会被自动的调用。

      1、__del__():销毁对象时,被自动的调用

     1 class Person:
     2     def __init__(self, name):
     3         self.name = name
     4         print('%s 被初始化' % self.name)
     5 
     6     def __del__(self):
     7         print("%s 被删除 " % self.name)
     8 
     9 
    10 p1 = Person("奶茶")
    11 p2 = Person("蛋糕")
    12 
    13 print('xixi')
    14 del p1
    15 print('haha')
    16 
    17 # 奶茶 被初始化
    18 # 蛋糕 被初始化
    19 # xixi
    20 # 奶茶 被删除
    21 # haha
    22 # 蛋糕 被删除

      2、__call__():

        功能:让类的实例具有类似有函数(方法)的功能。让对象可以被调用, 调用时执行的就是__call__中的函数体

        触发时机:调用对象的时候——对象()

     1 class Person:
     2     def __init__(self, name, sex, age, sister=None, brother=None):
     3         self.name = name
     4         self.sex = sex
     5         self.age = age
     6         self.sister = sister
     7         self.brother = brother
     8 
     9     def __call__(self):  # 获取....
    10         if self.sex == "boy":
    11             print(self.sister)
    12         else:
    13             print(self.brother)
    14 
    15     def get_age(self):
    16         print(self.age)
    17 
    18 
    19 p1 = Person("xixi", "boy", 18, "haha")
    20 print(p1.name)  # xixi
    21 p1.get_age()  # 18
    22 p1()  # haha

      3、__repr__():print(对象) 打印对象时会被调用

        __str__():print(对象) 打印对象时会被调用
       

        print(对象)默认情况下打印结果是,对象的内存地址
        重写__str__()方法,返回什么,print(对象)打印的结果就是什么

        区别与联系:

          1、TypeError:__repr__ returned non-string (type NoneType)
            以上两个函数都必须有返回值,且返回值类型为str类型;

          2、打印对象时, 如果使用%s占位符, 默认调用的是__str__()方法
            如果使用%r占位符, 默认调用的是__repr__()方法

          3、有repr, 没有str时,%s、%r 都可调用repr方法;
             没有repr, 有str时, %s 调用的是str的方法,%r 打印的是对象的地址(默认的)

          4、print(repr(对象)) 默认调用__repr__()方法
             print(str(对象)) 默认调用__str__()方法

     1 class Person:
     2     def __init__(self, name):
     3         self.name = name
     4 
     5     def __str__(self):
     6         return "我是str"
     7 
     8     def __repr__(self):
     9         return "我是repr"
    10 
    11 
    12 p1 = Person("xixi")
    13 # repr&str方法都没有
    14 # print(p1)  # <__main__.Person object at 0x000000000214D198>
    15 
    16 # repr&str方法都有
    17 # print("%s" % p1)  # 我是str
    18 # print("%r" % p1)  # 我是repr
    19 
    20 # 只有repr方法:
    21 # print("%s" % p1)  # 我是repr
    22 # print("%r" % p1)  # 我是repr
    23 
    24 # 只有str方法
    25 # print("%s" % p1)  # 我是str
    26 # print("%r" % p1)  # <__main__.Person object at 0x00000000026BD198>
    27 
    28 print(repr(p1))
    29 print(str(p1))

      4、__new__(cls):类方法

        功能:实例化一个对象

        触发时机:当实例化对象的时候,会被自动调用

        返回值:实例化的那个对象;

        __new__(cls)方法将实例化的对象传递给__init__(self)方法的第一个参数;

        __new__()是object类底层的实现——单例

     1 class Person:
     2     def __new__(cls, *args, **kwargs):  # 必须有返回值: 创建好的对象,类的实例
     3         print("我是new")
     4         return super().__new__(cls)
     5 
     6     def __init__(self):
     7         print("我是init")
     8 
     9 
    10 p = Person()  # 创建对象
    11 # 我是new
    12 # 我是init
    13 print(p)  # <__main__.Person object at 0x0000000001EA8358>

      5、__eq__:   

        只要俩对象的属性值都相等, 我们就认为这俩对象相等
        通过__eq__()方法去实现,必须有返回值bool用来代表是否相等
        使用__eq__()方法定义比较的规则,对象进行比较时需要使用 == 关系运算符进行比较

     

        对象.__dict__ 获取当前对象的属性, 包括私有(字典{"属性名": "属性值", ...})

     

        (1)基础数据类型的对象
          is : 比较的是对象的地址
          == : 比较的是对象的内容

     

          cmd 对于小整数 [-5, 256] 之间的数字进行了缓存,所以可以在缓存中重复使用
          pycharm做了优化,他把不可变数据类型中的很大范围的数据都做了缓存,所以在缓存中可以重复使用
          在pycharm中对某些即使很大的整数进行地址的比较 is 都是相等的

     

        (2)自定义类的对象
          is 和 == 比较的都是对象的地址

     

     1 a = "12345"
     2 b = "12345"
     3 
     4 print(a == b)  # True
     5 print(a is b)  # True
     6 print(id(a))  # 4772224
     7 print(id(b))  # 4772224
     8 
     9 
    10 list1 = [1, 2, 3, 4]
    11 list2 = [1, 2, 3, 4]
    12 print(list1 == list2)  # True
    13 print(list1 is list2)  # False
    14 print(id(list1))  # 63488968
    15 print(id(list2))  # 63184328
    16 
    17 
    18 class Person:
    19     def __init__(self, name, age):
    20         self.name = name
    21         self.age = age
    22 
    23     def __eq__(self, other):  # other, 另外一个要进行比较的对象
    24         if self.__dict__ == other.__dict__:  # 如果当前对象和被比较对象的所有属性值相等, 我们就认为这俩对象相等
    25             return True
    26         else:
    27             return False
    28 
    29 
    30 p1 = Person('xixi', 6)
    31 p2 = Person('xixi', 6)
    32 print(p1 == p2)  # True
    33 print(p1 is p2)  # False
    34 print(id(p1))  # 43097840
    35 print(id(p2))  # 43101544

     

      6、__hash__() : 当获取对象的哈希值时,调用该魔术方法

        hash(对象)

        set, list, dict 没有__hash__()方法, hash(列表对象):报错,不可被哈希
        列表对象.__hash__ ——> None

        如果只定义了__eq__()方法, 而没有定义__hash__(), 默认会将__hash__方法设置为None

     1 # 设计二维坐标类Point判断2个坐标是否相等,
     2 # 并能根据hash函数计算坐标的哈希值;
     3 
     4 class Point:
     5     def __init__(self, x, y):
     6         self.x = x
     7         self.y = y
     8 
     9     def __eq__(self, other):
    10         if self.x == other.x and self.y == other.y:
    11             return True
    12         else:
    13             return False
    14 
    15     def __hash__(self):
    16         return hash((self.x, self.y))
    17 
    18 point1 = Point(3, 4)
    19 point2 = Point(3, 4)
    20 
    21 print(point1 == point2)  # True
    22 
    23 print(hash(point1))  # 3713083796997400956
    24 print(hash(point2))  # 3713083796997400956
  • 相关阅读:
    js 对象数组 排序
    sql 时间条件查询
    idea和Pycharm 等系列产品激活激活方法和激活码 100 年
    开源协议简介
    面试题
    VIM|基础命令
    git|基础命令
    VIM|复制
    lua|基础教程
    Printf格式输出详解
  • 原文地址:https://www.cnblogs.com/Tree0108/p/12112896.html
Copyright © 2020-2023  润新知