zoukankan      html  css  js  c++  java
  • 面向对象进阶:反射以及内置方法

    一、反射

    反射:使用字符串数据类型的变量名来获取这个变量的值

      input:用户输入的如果是a,那么打印1。如果输入的是b那么就打印2.如果输入name,那么打印alex

      文件:从文件中读出的字符串,想转换成变量的名字

      网络:将网络传输的字符串转换成变量的名字

    1.反射类中的变量:静态属性,类方法

    # class Foo:
    #     School = 'oldboy'
    #     Country = 'China'
    #     language = 'Chinese'
    #     @classmethod
    #     def class_method(cls):
    #         print(cls.School)
    #     @staticmethod
    #     def static_method():
    #         print(Foo.School)
    # # 反射实现
    # while True:
    #     inp = input('>>>')
    #     if hasattr(Foo,inp):
    #         print(getattr(Foo,inp))
    #
    # getattr(Foo,'class_method')()
    # getattr(Foo, 'static_method')()
    

      

    解析getattr方法:

    # 解析getattr方法:
    # getattr(变量名: 命名空间, 字符串:属于一个命名空间内的变量名)
    # getattr(Foo, 'School')  # 相当于Foo.School
    # print(Foo.class_method)
    # print(getattr(Foo, 'class_method')) # 地址一样
    

    2.反射模块中的变量

      

    import os
    # so.rename('a', 'b')
    # getattr(os, 'rename')('a', 'b')
    

      

    3.反射本文件中的变量

    # a = 1
    # b = 2
    # name = 'alex'
    # def qqxing():
    #     print('qqxing')
    #
    #
    # import sys
    # print(sys.modules['__main__'])  # 本文件的命名空间
    # print(sys.modules['__main__'].a)
    # print([__name__]) # 变量,内置的变量
    分析过程
    # 反射本文件中的变量  结论
    # a = 1
    # b = 2
    # name = 'alex'
    # def qqxing():
    #     print('qqxing')
    # class Foo:pass
    #
    # import sys
    # print(sys.modules[__name__])     # 反射本文件中的变量 固定的使用这个命名空间
    # print(getattr(sys.modules[__name__],'a'))
    # print(getattr(sys.modules[__name__],'b'))
    # print(getattr(sys.modules[__name__],'name'))
    # getattr(sys.modules[__name__],'qqxing')()
    # print(getattr(sys.modules[__name__],'Foo'))
    # obj = getattr(sys.modules[__name__],'Foo')()
    # print(obj)
    结论

    4.setattr

    # class Foo:
    #     Country = 'China'
    #
    # def func():
    #     print('qqxing')
    # Foo.School = 'OLDBOY'
    # setattr(Foo,'School','OLDOBY')  # 接受三个参数 命名空间 ‘变量名’ 变量值
    # print(Foo.__dict__)
    # print(getattr(Foo,'School'))
    # print(Foo.School)
    # #
    # setattr(Foo,'func',func)  # 一般没人往空间中添加函数
    # print(Foo.__dict__)
    # print(Foo.func)
    

      

    5.delattr

    # delattr
    # del Foo.Country
    # print(Foo.__dict__)
    # delattr(Foo,'Country')
    # print(Foo.__dict__)
    

     

     

    二、内置方法

    定义:不需要程序员定义,本身就存在类中的方法就是内置方法

    内置方法的形式:__名字__

    名字又称为:双下方法,魔术方法,内置方法

    作用:不需要我们主动调用,而是实例化时内部自动调用的。

      所有的双下方法,都不需要我们直接区调用,都有另外一种自动触发他的语法。

    1.__str__ 和 __repr__

    # __str__ __repr__
    # class Course:
    #     def __init__(self,name,period,price,teacher):
    #         self.name= name
    #         self.period = period
    #         self.price = price
    #         self.teacher = teacher
    #
    #     def __str__(self):
    #         return 'str : %s %s %s %s' % (self.name, self.period, self.price, self.teacher)
    #
    #     def __repr__(self):
    #         return 'repr : %s %s %s %s' % (self.name, self.period, self.price, self.teacher)
    # course_lst = []
    # python = Course('python','6 month',29800,'boss jin')
    # course_lst.append(python)
    # linux = Course('linux','5 month',25800,'oldboy')
    # course_lst.append(linux)
    # for id,course in enumerate(course_lst,1):
        # print('%s %s %s %s %s'%(id,course.name,course.period,course.price,course.teacher))
        # print(id,course)
        # print('%s %s'%(id,course))
        # print(str(course))
        # print(repr(course))
        # print('%r'%course)
    

      

    区别

    __str__
    当你打印一个对象的时候 触发__str__
    当你使用%s格式化的时候 触发__str__
    str强转数据类型的时候  触发__str__
    
    __repr__
    repr是str的备胎
    有__str__的时候执行__str__,没有实现__str__的时候,执行__repr__
    repr(obj)内置函数对应的结果是 __repr__的返回值
    当你使用%r格式化的时候 触发__repr__
    

      

    顺序

    子类有__str__:Son.str
    子类没有__str__:找父类,Foo.str
    
    子类父类都没有__str__:Son.repr
    
    子类父类都没有str,子类有repr:Son.repr
    否则:Foo.repr
    

      

    class Foo:
        # def __str__(self):
        #     return 'Foo.str'
        def __repr__(self):
            return 'Foo.repr'
    
    
    class Son(Foo):
        pass
        # def __str__(self):
        #     return 'Son.str'
    
        # def __repr__(self):
        #     return 'Son.repr'
    
    s1 = Son()
    print(s1)
    

      

     2.构造方法__new__

    在init之前,实例化对象的第一步是 __new__创建了一个空间

    class Foo:
        def __init__(self):   # 初始化方法
            print('执行init')
        def __new__(cls, *args, **kwargs):   # 构造方法
            print('执行new')
            return object.__new__(cls)
    
    
    obj = Foo()
    

      

    # 单例模式
    # 一个类 只有一个实例的时候,单例模式
    class Foo:
        __instance = None
        def __init__(self, name, age):  # 初始化方法
            print('执行init')
            self.name = name
            self.age = age
    
        def __new__(cls, *args, **kwargs):  # 构造方法
            if cls.__instance is None:
                cls.__instance = object.__new__(cls)
            return cls.__instance
    
    obj1 = Foo('alex', 20)
    obj2 = Foo('egon', 22)
    
    print(obj1.name, obj2.name)
    单例模式

    3.析构方法__del__

    析构方法:在删除这个类创建的对象的时候会先从这个方法出发,再删除对象。做一些清理工作,比如说关闭文件,关闭网络的链接,数据库的链接。

    class Foo:
        def __init__(self, name, age):
            self.name = name
            self.age = age
            self.file = open('file', 'w')
        def write(self):
            self.file.write('jsjgjs')
        def __del__(self):   # 析构方法:在删除这个类创建的对象的时候会先出发这个方法,再删除对象。
            # 做一些清理工作,比如说关闭文件,关闭网络的链接,数据库的链接
            self.file.close()
            print('执行del了')
    
    f = Foo('alex', 20)
    del f.name
    

      

    4.__len__

    # len()  list dict set str
    
    print('__len__' in dir(list))
    print('__len__' in dir(dict))
    print('__len__' in dir(set))
    print('__len__' in dir(str))
    
    
    print('__len__' in dir(int))
    print('__len__' in dir(float))
    
    class Foo:
        def __len__(self):
            return 2
    obj = Foo()
    print(len(obj))  # 2
    
    
    class Team:
        def __init__(self, name, course):
            self.name = name
            self.course = course
            self.students = []
    
        def __len__(self):
            return len(self.students)
    
    s1 = Team('team', 'pirate')
    s1.students.append('luffy')
    s1.students.append('zoro')
    s1.students.append('sanji')
    print(len(s1))
    

      

    5.__eq__

    class Staff:
        def __init__(self, name, sex):
            self.name = name
            self.sex = sex
        def __eq__(self, other):
            return self.__dict__ == other.__dict__
            # return True
    luffy = Staff('luffy', 'male')
    luffy2 = Staff('luffy', 'male')
    zoro = Staff('zoro', 'male')
    
    print(luffy == luffy2)
    print(luffy == zoro)   # 正常是False, 如果return True 返回的是True。
    
    l1 = [1,2,3,4]
    l2 = [1,2,3,4]
    print(id(l1),id(l2))
    print(l1 == l2)
    print(l1 is l2)
    

      

    6.__hash__

    class Foo:
        pass
    
    obj1 = Foo()
    obj2 = Foo()
    
    print(hash(obj1))   # 116451029964
    print(hash(obj1))   # 116451029964
    print(hash(obj1))   # 116451029964
    print(hash(obj1))   # 116451029964
    print(hash(obj2))   # -9223371920403745862
    
    # 相同的值hash得到的值是一样的
    
    # 1.每次执行的hash值都会变
    # 2.在一次执行的过程中对同一个值的hash结果总是不变的  

    hash算法:

    1.对于相同的值在一次程序的运行中是不会变化的

    2.对于不同的值在一次程序的运行中总是不同的

    # set的去重机制
    # new_lst = [1,2,3,4,5,6,7,8,9,0,10,111,238579]
    # lst = [2,2,43,53,238579,14780]
    # for i in lst:
    #     if i in new_lst:
    #         pass
    #     else:
    #         new_lst.append(i)
    
    # set = {1,2,'abc',3,4,5,6,7,8,9,'bca'}
    # 不能通过逐个判断值相等这件事儿来做去重工作
    # hash算法也不是完全的靠谱
    
    # set 的去重机制
        # 1.对每一个元素进行hash计算出一个内存地址
        # 2.到这个内存地址上查看
            # 如果这块内存中没有值
                # 将这个元素存到对应的内存地址上
            # 如果这块内存中已经有值
                # 判断这两个值是否相等
                    # 如果相等 就舍弃后面的值
                    # 如果不相等 就二次寻址再找一个新的空间来存储这个值
    set的去重机制
    # 员工类
    # 姓名 年龄 性别 部门
    # 转岗位
    # 姓名 年龄变化了 性别 部门
    # 100个员工,去掉重复的
    # 员工的姓名 性别 是相同的,就认为是同一个员工
    
    class Staff:
        def __init__(self,name,age,sex,dep):
            self.name = name
            self.age = age
            self.sex = sex
            self.dep = dep
        def __hash__(self):
            return hash(self.name + self.sex)
        def __eq__(self, other):
            if self.name == other.name and self.sex == other.sex:
                return True
    
    name_lst = ['yuan','egon','nazha','peiqi']
    obj_lst = []
    for i in range(100):
        name = name_lst[i%4]
        obj = Staff(name,i,'male','python')
        obj_lst.append(obj)
    print(obj_lst)
    ret = set(obj_lst)
    print(ret)
    for i in ret:
        print(i.name,i.age)
    去除重复员工
  • 相关阅读:
    Algorithm Of Swift -- 4.合并两个有序数组
    Algorithm Of Swift -- 3.链表反转
    Algorithm Of Swift -- 2.字符串反转
    Algorithm Of Swift -- 1.两数之和
    1850984: Fix: crash when running am.jar without parameters
    微信公众号关联小程序,实现消息推送。
    NPOI根据Excel数据导入导出到Datatable中--帮助类
    OpenCvSharp+ZXing实现多个DataMatrix解析
    多数据源导致事务不生效
    android theme之Material的默认色和夜晚模式
  • 原文地址:https://www.cnblogs.com/eaoo/p/9567511.html
Copyright © 2011-2022 走看看