zoukankan      html  css  js  c++  java
  • Python笔记7(面向对象进阶)

    一、反射

    1、什么是反射

    反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。

    2 、python面向对象中的反射

    通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)。

    类名 ——反射 静态属性
    对象名 ——反射 对象属性 和 方法
    模块  ——反射模块中的名字
    反射 ——自己所在文件中的名字

    3、使用说明

    首先 使用getattr取获取一个名字,如果在这个对象的命名空间中没有这个名字 会报错;
    getattr的反射好伴侣 hasattr 判断在这个对象的命名空间中没有这个名字 存在返回True 否则False;
    如果使用getattr取获取一个方法,那么只能拿到这个方法的内存地址 加上括号就是执行,当然,括号里的参数可以照传不误;
    如果getattr获取一个属性,那么直接使用反射就可以获取到值。

    模块就是一个py文件,pyi代表是内置模块;
    所谓的模块导入 就是执行了这个文件而已。

    4、四个可以实现自省的函数:hasattr、getattr、setattr、delattr

    # 1)四个方法的使用示例
    class Foo:
        f = '类的静态变量'
    
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def say_hi(self):
            print('hi,%s' % self.name)
    
    
    obj = Foo('egon', 73)
    
    # 检测是否含有某属性
    print(hasattr(obj, 'name'))  # >>>True
    print(hasattr(obj, 'say_hi'))  # >>>True
    
    # 获取属性
    n = getattr(obj, 'name')
    print(n)  # >>>egon
    func = getattr(obj, 'say_hi')
    func()  # >>>hi,egon
    
    # print(getattr(obj,'aaaaaaaa','不存在啊')) #报错
    
    # 设置属性
    setattr(obj, 'sb', True)
    setattr(obj, 'show_name', lambda self: self.name + 'sb')
    print(
        obj.__dict__)  # >>>{'name': 'egon', 'age': 73, 'sb': True, 'show_name': <function <lambda> at 0x00000292BAE05F28>}
    print(obj.show_name(obj))  # >>>egonsb
    
    # 删除属性
    delattr(obj, 'age')
    delattr(obj, 'show_name')
    # delattr(obj,'show_name111')#不存在,则报错
    
    print(obj.__dict__)  # >>>{'name': 'egon', 'sb': True}
    #2)类也是对象
    class Foo(object):
        staticField = "old boy"
    
        def __init__(self):
            self.name = 'wupeiqi'
    
        def func(self):
            return 'func'
    
        @staticmethod
        def bar():
            return 'bar'
    
    
    print(getattr(Foo, 'staticField'))
    print(getattr(Foo, 'func'))
    print(getattr(Foo, 'bar'))
    
    # 执行结果
    # old boy
    # <function Foo.func at 0x000001A8F4739378>
    # <function Foo.bar at 0x000001A8F4739400>
    # 3)反射当前模块的成员
    import sys
    
    def s1():
        print('s1')
    
    def s2():
        print('s2')
    
    this_module = sys.modules[__name__]
    
    print(hasattr(this_module, 's1'))#>>>True
    getattr(this_module, 's2')()#>>>s2
    # 4)示例
    class Person:
        role = 'Person'  # 静态属性
    
        def __init__(self, name):
            self.name = name  # 对象属性
    
        def eat(self): print('eating')
    
        def drink(self): print('drinking')
    
        def play(self): print('playing')
    
        def sleep(self): print('sleepping')
    
    
    alex = Person('alex')
    alex.name
    print(getattr(alex, 'name'))  # >>>alex
    print(getattr(Person, 'role'))  # >>>Person
    
    while True:
        inp = input('>>>')
        if hasattr(alex, inp):
            getattr(alex, inp)()
    # 执行结果:
    # >>>eat
    # eating
    # >>>drink
    # drinking
    # >>>play
    # playing
    # >>>sleep
    # sleepping
    # >>>111
    # >>>
    # 5)反射当前模块成员
    # mymodule.py
    # money = 100
    # def func1():
    #     print('func1')
    #
    # def func2():
    #     print('func2')
    #
    # class Manager:
    #     def eat(self):
    #         print('eating')
    
    import mymodule
    import time
    
    mymodule.func1()#>>>func1
    time.sleep(0.5)
    print(mymodule.money)#>>>100
    getattr(mymodule,'func1')()#>>>func1
    print(getattr(mymodule,'money'))#>>>100
    getattr(time,'sleep')(1)
    
    Manager = getattr(mymodule,'Manager')#拿到一个类的内存地址
    a = Manager()
    a.eat()#>>>eating
    
    value = '123'
    import sys
    print(sys.modules)
    #>>>{'builtins': <module 'builtins' (built-in)>, 'sys': <module 'sys' (built-in)>, '_frozen_importlib': <module '_frozen_importlib' (frozen)>, '_imp': <module '_imp' (built-in)>, '_warnings': <module '_warnings' (built-in)>, '_thread': <module '_thread' (built-in)>, '_weakref': <module '_weakref' (built-in)>, '_frozen_importlib_external': <module '_frozen_importlib_external' (frozen)>, '_io': <module 'io' (built-in)>, 'marshal': <module 'marshal' (built-in)>, 'nt': <module 'nt' (built-in)>, 'winreg': <module 'winreg' (built-in)>, 'zipimport': <module 'zipimport' (built-in)>, 'encodings': <module 'encodings' from 'C:\Users\28163\AppData\Local\Programs\Python\Python36\lib\encodings\__init__.py'>, 'codecs': <module 'codecs' from 'C:\Users\28163\AppData\Local\Programs\Python\Python36\lib\codecs.py'>, '_codecs': <module '_codecs' (built-in)>, 'encodings.aliases': <module 'encodings.aliases' from 'C:\Users\28163\AppData\Local\Programs\Python\Python36\lib\encodings\aliases.py'>, 'encodings.utf_8': <module 'encodings.utf_8' from 'C:\Users\28163\AppData\Local\Programs\Python\Python36\lib\encodings\utf_8.py'>, '_signal': <module '_signal' (built-in)>, '__main__': <module '__main__' from 'C:/Users/28163/Desktop/老男孩教育-Python21期/day07/day7视频与笔记/day7笔记/9.反射.py'>, 'encodings.latin_1': <module 'encodings.latin_1' from 'C:\Users\28163\AppData\Local\Programs\Python\Python36\lib\encodings\latin_1.py'>, 'io': <module 'io' from 'C:\Users\28163\AppData\Local\Programs\Python\Python36\lib\io.py'>, 'abc': <module 'abc' from 'C:\Users\28163\AppData\Local\Programs\Python\Python36\lib\abc.py'>, '_weakrefset': <module '_weakrefset' from 'C:\Users\28163\AppData\Local\Programs\Python\Python36\lib\_weakrefset.py'>, 'site': <module 'site' from 'C:\Users\28163\AppData\Local\Programs\Python\Python36\lib\site.py'>, 'os': <module 'os' from 'C:\Users\28163\AppData\Local\Programs\Python\Python36\lib\os.py'>, 'errno': <module 'errno' (built-in)>, 'stat': <module 'stat' from 'C:\Users\28163\AppData\Local\Programs\Python\Python36\lib\stat.py'>, '_stat': <module '_stat' (built-in)>, 'ntpath': <module 'ntpath' from 'C:\Users\28163\AppData\Local\Programs\Python\Python36\lib\ntpath.py'>, 'genericpath': <module 'genericpath' from 'C:\Users\28163\AppData\Local\Programs\Python\Python36\lib\genericpath.py'>, 'os.path': <module 'ntpath' from 'C:\Users\28163\AppData\Local\Programs\Python\Python36\lib\ntpath.py'>, '_collections_abc': <module '_collections_abc' from 'C:\Users\28163\AppData\Local\Programs\Python\Python36\lib\_collections_abc.py'>, '_sitebuiltins': <module '_sitebuiltins' from 'C:\Users\28163\AppData\Local\Programs\Python\Python36\lib\_sitebuiltins.py'>, '_bootlocale': <module '_bootlocale' from 'C:\Users\28163\AppData\Local\Programs\Python\Python36\lib\_bootlocale.py'>, '_locale': <module '_locale' (built-in)>, 'encodings.gbk': <module 'encodings.gbk' from 'C:\Users\28163\AppData\Local\Programs\Python\Python36\lib\encodings\gbk.py'>, '_codecs_cn': <module '_codecs_cn' (built-in)>, '_multibytecodec': <module '_multibytecodec' (built-in)>, 'sysconfig': <module 'sysconfig' from 'C:\Users\28163\AppData\Local\Programs\Python\Python36\lib\sysconfig.py'>, 'encodings.cp437': <module 'encodings.cp437' from 'C:\Users\28163\AppData\Local\Programs\Python\Python36\lib\encodings\cp437.py'>, 'sitecustomize': <module 'sitecustomize' from 'C:\Program Files\JetBrains\PyCharm 2017.3.4\helpers\pycharm_matplotlib_backend\sitecustomize.py'>, 'mymodule': <module 'mymodule' from 'C:\Users\28163\Desktop\老男孩教育-Python21期\day07\day7视频与笔记\day7笔记\mymodule.py'>, 'time': <module 'time' (built-in)>}
    print(sys.modules['__main__'])
    #>>><module '__main__' from 'C:/Users/28163/Desktop/老男孩教育-Python21期/day07/day7视频与笔记/day7笔记/9.反射.py'>
    print(getattr(sys.modules['__main__'],'value'))#>>>123   反射自己模块当中的名字
    # 6)示例
    class Manager:
        def __init__(self, name):
            self.name = name
    
        def create_course(self):
            pass
    
    class Teacher:
        def __init__(self, name):
            self.name = name
    
        def list_student(self):
            pass
    
    class Student:
        def __init__(self, name):
            self.name = name
    
        def create_course(self):
            pass
    
    
    a = Student('a')
    a.age = 19
    setattr(a, 'age', 25)
    print(a.__dict__)  # >>>{'name': 'a', 'age': 25}
    print(a.age)  # >>>25
    import sys
    
    # login 先进行登录
    # 输入name,pwd 与文件内容比对,然后找到对应身份的类
    
    id = 'Manager'
    if hasattr(sys.modules['__main__'], id):
        obj = getattr(sys.modules['__main__'], id)(name, pwd)

     二、面向对象进阶

    1、isinstance和issubclass

    # 1)isinstance(obj,cls)检查是否obj是否是类 cls 的对象
    class Foo(object):
        pass
    
    obj = Foo()
    
    print(isinstance(obj, Foo))  # >>>True
    
    # 2)issubclass(sub, super)检查sub类是否是 super 类的派生类
    class Foo(object):
        pass
    
    class Bar(Foo):
        pass
    
    print(issubclass(Bar, Foo))  # >>>True

    2、__new__

    1)__new__、__init__

    # __new__    构造方法 创建一个对象
    # __init__   初始化方法
    # 先执行new方法,object.new()   再执行init
    class Foo:
        def __new__(cls, *args, **kwargs):
            print('执行我啦')
            obj = object.__new__(cls)
            print(obj)
            return obj
    
        def __init__(self):
            print('222222222', self)
    
    Foo()
    
    # 执行结果:
    # >>>执行我啦
    # >>><__main__.Foo object at 0x000002C2FB913A90>
    # >>>222222222 <__main__.Foo object at 0x000002C2FB913A90>
    
    # 执行过程:
    # Foo()  --> python解释器接收到你的python代码
    # python解释器替你去做了很多操作(翻译成C语言的字节码,将C语言的字节码解释成 机器码 让CPU去执行)
    # 包括 主动帮助你 调用 new方法 去创造一个对象 —— 开辟内存空间 —— python语言封装了开辟内存的工作
    # object的new方法里 —— 帮你创造了对象
    # 调用init用到的self参数 就是new帮你创造的对象

    2)单例模式

    # 单例模式 : 是一种设计模式  某一个类 只有一个实例
    class Person:
        __isinstance = None
    
        def __new__(cls, *args, **kwargs):
            if not cls.__isinstance:
                obj = object.__new__(cls)
                cls.__isinstance = obj
            return cls.__isinstance
    
        def __init__(self, name):
            self.name = name
    
    alex = Person('alex')
    alex.age = 18
    egon = Person('egon')
    print(egon.age)
    print(id(alex))
    print(id(egon))
    print(alex.name)
    print(egon.name)
    
    # 执行结果:
    # 18
    # 2669030687800
    # 2669030687800
    # egon
    # egon

    3、__str__、__repr__、__format__

    改变对象的字符串显示__str__,__repr__

    自定制格式化字符串__format__

    format_dict = {
        'nat': '{obj.name}-{obj.addr}-{obj.type}',  # 学校名-学校地址-学校类型
        'tna': '{obj.type}:{obj.name}:{obj.addr}',  # 学校类型:学校名:学校地址
        'tan': '{obj.type}/{obj.addr}/{obj.name}',  # 学校类型/学校地址/学校名
    }
    
    class School:
        def __init__(self, name, addr, type):
            self.name = name
            self.addr = addr
            self.type = type
    
        def __repr__(self):
            return 'School(%s,%s)' % (self.name, self.addr)
    
        def __str__(self):
            return '(%s,%s)' % (self.name, self.addr)
    
        def __format__(self, format_spec):
            # if format_spec
            if not format_spec or format_spec not in format_dict:
                format_spec = 'nat'
            fmt = format_dict[format_spec]
            return fmt.format(obj=self)
    
    s1 = School('oldboy1', '北京', '私立')
    print('from repr: ', repr(s1))
    print('from str: ', str(s1))
    print(s1)
    
    # 执行结果
    # >>>from repr:  School(oldboy1,北京)
    # >>>from str:  (oldboy1,北京)
    # >>>(oldboy1,北京)
    
    '''
    str函数或者print函数--->obj.__str__()
    repr或者交互式解释器--->obj.__repr__()
    如果__str__没有被定义,那么就会使用__repr__来代替输出
    注意:这俩方法的返回值必须是字符串,否则抛出异常
    '''
    print(format(s1, 'nat'))
    print(format(s1, 'tna'))
    print(format(s1, 'tan'))
    print(format(s1, 'asfdasdffd'))
    
    # 执行结果
    # >>>oldboy1-北京-私立
    # >>>私立:oldboy1:北京
    # >>>私立/北京/oldboy1
    # >>>oldboy1-北京-私立
    class B:
        def __str__(self):
            return 'str : class B'
    
        def __repr__(self):
            return 'repr : class B'
    
    b = B()
    print('%s' % b)
    print('%r' % b)
    
    # 执行结果
    # >>>ostr : class B
    # >>>orepr : class B

    4、__del__

    析构方法,当对象在内存中被释放时,自动触发执行。

    注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。

    class Foo:
    
        def __del__(self):
            print('执行我啦')
    
    f1 = Foo()
    del f1
    print('------->')
    
    # 输出结果
    # >>>执行我啦
    # >>>------->

    5、item系列(__getitem__、__setitem__、__delitem__)

    class Foo:
        def __init__(self, name):
            self.name = name
    
        def __getitem__(self, item):
            print(self.__dict__[item])
    
        def __setitem__(self, key, value):
            self.__dict__[key] = value
    
        def __delitem__(self, key):
            print('del obj[key]时,我执行')
            self.__dict__.pop(key)
    
        def __delattr__(self, item):
            print('del obj.key时,我执行')
            self.__dict__.pop(item)
    
    f1 = Foo('sb')
    f1['age'] = 18
    f1['age1'] = 19
    del f1.age1  # >>>del obj.key时,我执行
    del f1['age']  # >>>del obj[key]时,我执行
    f1['name'] = 'alex'
    print(f1.__dict__)  # >>>{'name': 'alex'}

    6、__call__

    对象后面加括号,触发执行。

    注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()

    class Foo:
    
        def __init__(self):
            pass
    
        def __call__(self, *args, **kwargs):
            print('__call__')
    
    obj = Foo()  # 执行 __init__
    obj()  # 执行 __call__
    # 输出结果>>>__call__

    7、__len__

    class A:
        def __init__(self):
            self.a = 1
            self.b = 2
    
        def __len__(self):
            return len(self.__dict__)
    
    a = A()
    print(len(a))  # >>>2

    8、__hash__

    class A:
        def __init__(self):
            self.a = 1
            self.b = 2
    
        def __hash__(self):
            return hash(str(self.a) + str(self.b))
    
    a = A()
    print(hash(a))  # >>>1060108502313640553

    9、__eq__

    class A:
        def __init__(self):
            self.a = 1
            self.b = 2
    
        def __eq__(self, obj):
            if self.a == obj.a and self.b == obj.b:
                return True
    
    a = A()
    b = A()
    print(a == b)  # >>>True

    面试题:

    #实例化n个对象 84 个
    #对84个对象进行去重
    # 如果两个对象的姓名和性别相同,我就认为是相同的对象
    
    class Person:
        def __init__(self, name, age, sex):
            self.name = name
            self.age = age
            self.sex = sex
    
        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
    
    
    p_lst = []
    for i in range(84):
        p_lst.append(Person('egon', i, 'male'))
    
    print(p_lst)
    print(set(p_lst))
  • 相关阅读:
    每日日报7月15日
    每日日报7月14日
    ecplise下 java问题处理
    Visual Studio Code for .Net Framework
    Go语言操作MySQL数据库
    Go语言Gin-4中间件
    Go语言Gin-2.数据传输
    Go语言Gin-1.路由
    13.Go语言-并发编程
    12.Go语言-网络编程
  • 原文地址:https://www.cnblogs.com/xingye-mdd/p/9080341.html
Copyright © 2011-2022 走看看