• Python之面向对象四


    面向对象进阶

    一、关于面向对象的两个内置函数

    isinstance   判断类与对象的关系    isinstance(obj,cls)检查obj是否是类 cls 的对象,返回值是bool值

    issubclass     判断类与类的关系             issubclass(sub, super)检查sub类是否是 super 类的派生类,返回值是bool值

    class A:
        pass
    class B(A):
        pass
    a = A()
    print(isinstance(a,A))
    print(issubclass(B,A))
    print(issubclass(A,B))
    
    
    
    
    >>>
    True
    True
    False
    关于类的内置函数

    二、反射

    什么是反射?

    反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的

    提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。

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

    ps:

      eval  的功能和反射有点类似,但是 eval 在操作字符串时有很大的安全隐患,反射没有安全隐患。

    四个可以实现自省的函数

    下列方法适用于类和对象(一切皆对象,类本身也是一个对象)

    1、getattr(object, name[,default])
    获取对象object的属性或者方法,如果存在打印出来,如果不存在,打印出默认值,默认值可选。
    需要注意的是,如果是返回的对象的方法,返回的是方法的内存地址,如果需要运行这个方法,
    可以在后面添加一对括号。

    class A:
        def func(self):
            print('in func')
    
    a = A()
    a.name = 'alex'
    a.age = 63
    
    ret = getattr(a,'name')  # 通过变量名的字符串形式取到的值
    print(ret)
    print(a.__dict__)
    
    变量名 = input('>>>')   # func
    print(getattr(a,变量名))
    print(a.__dict__[变量名])
    
    
    》》》
    alex
    {'name': 'alex', 'age': 63}
    >>>age
    63
    63
    反射对象的属性
    class A:
        def func(self):
            print('in func')
    
    a = A()
    
    a.func()
    ret = getattr(a,'func')
    print(ret)                      #不加括号只能打印一个内存地址
    ret()
    
    
    》》》
    in func
    <bound method A.func of <__main__.A object at 0x00000250C461E668>>
    in func
    反射对象的方法
    class A:
        price = 20
        @classmethod
        def func(cls):
            print('in func')
    
    
    print(getattr(A,'price'))
    
    
    》》》
    20
    反射类的属性
    #需要使用到装饰器    classmethod     staticmethod
    
    class A:
        price = 20
        @classmethod
        def func(cls):
            print('in func')
    
    
    if hasattr(A,'func'):
        getattr(A,'func')()
    
    
    》》》
    in func
    反射类的方法
    #新建一个my.py
    #内容
    day = 'Monday'  # 周一
    
    def wahaha():
        print('wahahaha')
    
    
    class C:
        pass
    
    
    
    
    #在另一个py文件里运行
    import my
    print(my.day)
    print(getattr(my,'day'))
    
    》》》
    Monday
    Monday
    反射模块的属性
    #新建一个my.py
    #内容
    day = 'Monday'  # 周一
    
    def wahaha():
        print('wahahaha')
    
    
    class C:
        pass
    
    
    
    #在另一个py文件里运行
    
    getattr(my,'wahaha')()
    
    
    》》》
    wahahaha
    反射模块的方法
    #新建一个my.py
    #内容
    day = 'Monday'  # 周一
    
    def wahaha():
        print('wahahaha')
    
    
    class C:
        pass
    
    
    
    
    #在另一个py文件中运行
    
    import my
    print(getattr(my,'C')())
    
    
    》》》
    <my.C object at 0x0000029F28E9E080>
    反射模块里的类
    # time
    # asctime
    import time
    print(getattr(time,'time')())
    print(getattr(time,'asctime')())
    
    
    
    
    》》》
    1516608195.0811734
    Mon Jan 22 16:03:15 2018
    内置模块也能反射
    def qqxing():
        print('qqxing')
    year = 2018
    import sys
    print(sys.modules['__main__'].year)
    print(getattr(sys.modules['__main__'],'year'))
    
    
    》》》
    2018
    2018
    反射自己模块中的变量
    def qqxing():
        print('qqxing')
    year = 2018
    import sys
    
    getattr(sys.modules['__main__'],'qqxing')()
    变量名 = input('>>>')
    print(getattr(sys.modules[__name__],变量名))
    
    
    》》》
    qqxing
    >>>year
    2018
    反射自己模块中的函数
    import time
    print(time.strftime('%Y-%m-%d %H:%M:S'))
    print(getattr(time,'strftime')('%Y-%m-%d %H:%M:S'))
    
    
    》》》
    2018-01-22 16:08:S
    2018-01-22 16:08:S
    要反射的函数可以有参数

     2、hasattr(object, name)
    判断一个对象里面是否有name属性或者name方法,返回BOOL值,有name特性返回True, 否则返回False。
    需要注意的是name要用括号括起来

    class A:
        name = 'xiaoming'
        def run(self):
            return 'gogogo'
    a = A()
    print(a.run())
    print(hasattr(a,'name'))     #判断对象是否有  name  属性
    print(hasattr(a,'run'))      #判断对象是否有  run  方法
    print(hasattr(A,'run'))      #判断类是否有  run  属性
    print(hasattr(A,'rn')) 
    
    
    
    》》》
    gogogo
    True
    True
    True
    False
    View Code

    3、setattr(object, name, values)
    给对象的属性赋值,若属性不存在,先创建再赋值。

    class A:
        pass
    a = A()
    setattr(a,'name','nezha')
    setattr(A,'name','alex')
    print(A.name)
    print(a.name)
    View Code

    4、delattr(object, name)

    删除一个变量,删除指定对象的指定名称的属性,和setattr函数作用相反,当属性不存在的时候,会报错,不能删除对象的方法。

    class A:
        pass
    a = A()
    setattr(a,'name','nezha')
    setattr(A,'name','alex')
    
    delattr(a,'name')
    print(a.name)
    delattr(A,'name')
    print(a.name)
    
    》》》
    alex
    Traceback (most recent call last):
      File "D:/Python学习/Python/学习资料/学习视频/day27/2.反射.py", line 122, in <module>
        print(a.name)
    AttributeError: 'A' object has no attribute 'name'
    View Code

    在删除时,注意作用域。对象的属性里没有可以去找类的属性,但不能去object这个父类找

    三、双下方法

    内置的类方法 和 内置的函数之间有着千丝万缕的联系

    __str__和__repr__

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

    自定制格式化字符串__format__

    #_*_coding:utf-8_*_
    
    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)
    
    '''
    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'))
    View Code
    class B:
    
         def __str__(self):
             return 'str : class B'
    
         def __repr__(self):
             return 'repr : class B'
    
    
    b=B()
    print('%s'%b)
    print('%r'%b)
    
    %s和%r
    View Code
    # obj.__str__  str(obj)
    # obj.__repr__ repr(obj)
    
    class Teacher:
        def __init__(self,name,salary):
            self.name = name
            self.salary = salary
        def __str__(self):
            return "Teacher's object :%s"%self.name
        def __repr__(self):
            return str(self.__dict__)
        def func(self):
            return 'wahaha'
    nezha = Teacher('哪吒',250)
    print(nezha)  # 打印一个对象的时候,就是调用a.__str__
    print(repr(nezha))
    print('>>> %r'%nezha)
    
    #a.__str__ --> object
    # object  里有一个__str__,一旦被调用,就返回调用这个方法的对象的内存地址
    # l = [1,2,3,4,5]   # 实例化 实例化了一个列表类的对象
    # print(l)
    # %s str()  直接打印 实际上都是走的__str__
    # %r repr()  实际上都是走的__repr__
    # repr 是str的备胎,但str不能做repr的备胎
    
    # print(obj)/'%s'%obj/str(obj)的时候,实际上是内部调用了obj.__str__方法,如果str方法有,那么他返回的必定是一个字符串
    # 如果没有__str__方法,会先找本类中的__repr__方法,再没有再找父类中的__str__。
    # repr(),只会找__repr__,如果没有找父类的

     ps:

     内建函数str()和repr() (representation,表达,表示)或反引号操作符(``)可以方便地以字符串的方式获取对象的内容、类型、数值属性等信息。str()函数得到的字符串可读性好(故被print调用),而repr()函数得到的字符串通常可以用来重新获得该对象,通常情况下 obj==eval(repr(obj)) 这个等式是成立的。这两个函数接受一个对象作为其参数,返回适当的字符串。

    事实上repr()和``做一样的事情,返回一个对象的“官方”字符串表示。其结果绝大多数情况下(不是所有)可以通过求值运算(内建函数eval())重新得到该对象。

    str()则不同,它生成一个对象的可读性好的字符串表示,结果通常无法用eval()求值,但适合print输出。

    __del__

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

    注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,

    所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。

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

    __call__

    Python中的__call__允许程序员创建可调用的对象(实例),默认情况下, __call__()方法是没有实现的,这意味着大多数实例是不可调用的。然而,如果在类定义中覆盖了这个方法,那么这个类的实例就成为可调用的。

    class A:
        def __init__(self,name):
            self.name = name
        def __call__(self):
            '''
            打印这个对象中的所有属性
            :return:
            '''
            for k in self.__dict__:
                print(k,self.__dict__[k])
    a = A('alex')()    #后面的括号可以直接让__call__(self)函数执行
    
    
    》》》
    name alex
    View Code

     __len__

    在执行len()时会自动触发内部的__len__方法

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

    item系列

    __getitem__         __setitem__           __delitem__

    类似字典的用法

    class Foo:
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
    
        def __getitem__(self, item):
            if hasattr(self,item):
                return self.__dict__[item]
    
        def __setitem__(self, key, value):
            self.__dict__[key] = value
    
        def __delitem__(self, key):
            del self.__dict__[key]
    
    f = Foo('wangming',38,'')
    print(f['name'])
    f['hobby'] = ''
    print(f.hobby,f['hobby'])
    del f.hobby      # object 原生支持  __delattr__
    del f['hobby']   # 通过自己实现的
    print(f.__dict__)
    View Code

    __new__

    构造方法 : 创建一个对象

    class A:
        def __init__(self):
            self.x = 1
            print('in init function')
        def __new__(cls, *args, **kwargs):
            print('in new function')
            return object.__new__(A, *args, **kwargs)
    
    a = A()
    print(a.x)
    
    
    
    》》》
    in new function
    in init function
    1
    View Code
    #单例模式
    #一个类 始终 只有 一个 实例
    #当你第一次实例化这个类的时候 就创建一个实例化的对象
    #当你之后再来实例化的时候 就用之前创建的对象
    
    class Singleton:
        def __new__(cls, *args, **kw):
            if not hasattr(cls, '_instance'):
                cls._instance = object.__new__(cls, *args, **kw)
            return cls._instance
    
    one = Singleton()
    two = Singleton()
    
    two.a = 3
    print(one.a)
    # 3
    # one和two完全相同,可以用id(), ==, is检测
    print(id(one))
    # 29097904
    print(id(two))
    # 29097904
    print(one == two)
    # True
    print(one is two)
    
    单例模式
    
    单例模式
    View Code

    __eq__

    __eq__ 定义了类的等号(==)行为

    可以去重

    class A:
        def __init__(self):
            self.a = 5
            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.a)
    print(a.b)
    print(b.a)
    print(b.b)
    print(a == b)
    
    》》》
    5
    2
    5
    2
    True
    View Code

    __hash__

    摘要算法:密码密文加密

    摘要算法只能加密,没有解密功能

    # 摘要算法
    # import hashlib   # 提供摘要算法的模块
    # 不管算法多么不同,摘要的功能始终不变
    # 对于相同的字符串使用同一个算法进行摘要,得到的值总是不变的
    # 使用不同算法对相同的字符串进行摘要,得到的值应该不同
    # 不管使用什么算法,hashlib的方式永远不变
    
    # import hashlib   # 提供摘要算法的模块
    # sha = hashlib.md5()
    # sha.update(b'这是密码区')
    # print(sha.hexdigest())
    
    # sha 算法 随着 算法复杂程度的增加 摘要的时间成本空间成本都会增加
    
    # 摘要算法
    # 密码的密文存储
    # 文件的一致性验证
        # 在下载的时候 检查我们下载的文件和远程服务器上的文件是否一致
        # 两台机器上的两个文件 你想检查这两个文件是否相等
    # 用户注册
    # 用户 输入用户名
    # 用户输入 密码
    # 明文的密码进行摘要 拿到一个密文的密码
    # 写入文件
    
    # 用户的登录
    
    import hashlib
    usr = input('username :')
    pwd = input('password : ')
    with open('userinfo') as f:
        for line in f:
            user,passwd,role = line.split('|')
            md5 = hashlib.md5()
            md5.update(bytes(pwd,encoding='utf-8'))
            md5_pwd = md5.hexdigest()
            if usr == user and md5_pwd == passwd:
                print('登录成功')
    # 加盐    提高密码的安全等级
    import hashlib   # 提供摘要算法的模块
    md5 = hashlib.md5(bytes('',encoding='utf-8'))    #加盐区可以是任意字符
    # md5 = hashlib.md5()
    md5.update(b'123456')
    print(md5.hexdigest())
    # 动态加盐   提高密码的安全等级
    # 用户名 密码
    # 使用用户名的一部分或者 直接使用整个用户名作为盐
    import hashlib   # 提供摘要算法的模块
    md5 = hashlib.md5(bytes('',encoding='utf-8')+b'')
    # md5 = hashlib.md5()
    md5.update(b'123456')
    print(md5.hexdigest())
    # 文件的一致性校验
    # 文件的一致性校验这里不需要加盐
  • 相关阅读:
    Rigidbody和Collider
    Unity官方实例教程 Roll-a-Ball
    unity还原three之旋转
    unity还原three——顶点,三角面,uv
    unity还原three导出的json——基本模型,位移,旋转,缩放
    【struts2基础】配置详解
    【深入Struts2】获取ServletAPI的三种方式
    JDBC事务与事务隔离级别详解
    【GOF23设计模式】--工厂模式
    【GOF23设计模式】--单例模式
  • 原文地址:https://www.cnblogs.com/DI-DIAO/p/8329073.html
Copyright © 2020-2023  润新知