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))
  • 相关阅读:
    Win10 UWP Tile Generator
    Win10 BackgroundTask
    UWP Tiles
    UWP Ad
    Win10 build package error collections
    Win10 八步打通 Nuget 发布打包
    Win10 UI入门 pivot multiable DataTemplate
    Win10 UI入门 导航滑动条 求UWP工作
    UWP Control Toolkit Collections 求UWP工作
    Win10 UI入门 SliderRectangle
  • 原文地址:https://www.cnblogs.com/xingye-mdd/p/9080341.html
Copyright © 2011-2022 走看看