day27

作者: 两分与桥 | 来源:发表于2018-04-17 21:06 被阅读2次

    isinstance(t, son) 检测 t 是否是 son 的实例
    issubclass(son, Earth) 检测 son 是否是 Earth 的子类

    class Earth:
        pass
    
    class son(Earth):
        pass
    
    t = son()
    print(isinstance(t, son))
    print(issubclass(son, Earth))
    
    输出结果:
    True
    True
    
    

    __getattribute__ 属性,可以防止程序奔溃

    class Earth:
        def __init__(self, name):
            self.name = name
    
        def __getattr__(self, item):
            print("getattr is work,get the ", item)
        
        #不管调用什么属性都会触发 __getattribute__ 属性,存在 __getattribute__ 属性就不会触发 __getattr__ 属性
        def __getattribute__(self, item): 
            print('getattribute is work, get the ', item)
            raise AttributeError("抛出异常了") # 模拟抛出异常,防止程序奔溃,raise 触发 __getattr__ 
    
    e = Earth('game')
    e.name
    e.none
    
    输出结果:
    getattribute is work, get the  name  #name 存在
    getattr is work,get the  name
    getattribute is work, get the  none  #none 不存在
    getattr is work,get the  none
    
    

    getitemsetitemdelitem,三个内置属性的使用方法

    class Earth:
        def __getitem__(self, item): #只有当特定方式 get 的时候才触发,就像 f['name']
            print('getitem', item)
            return self.__dict__[item]
    
        def __setitem__(self, key, value): #
            print('setitem %s %s '%(key,value))
            self.__dict__[key] = value
    
        def __delitem__(self, key):
            print('delitem',key)
            del self.__dict__[key]
    
    f = Earth()
    f.name = 'libai'
    f.age = 20
    
    print(f.__dict__)
    f['call'] = 1833  #触发 setitem
    print(f.__dict__)
    print('----------------------------------------')
    
    del f.name
    print(f.__dict__)
    del f['call']  #触发 delitem
    print(f.__dict__)
    
    print('----------------------------------------')
    print(f['age']) #触发 getitem
    print(f.__dict__['age'])
    
    输出结果:
    {'name': 'libai', 'age': 20}
    setitem call 1833 
    {'name': 'libai', 'age': 20, 'call': 1833}
    ----------------------------------------
    {'age': 20, 'call': 1833}
    delitem call
    {'age': 20}
    ----------------------------------------
    getitem age
    20
    20
    
    

    自定义 str ,控制返回,print() 函数触发的是系统 str 的执行

    class test:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def __str__(self):
            return '名字是 %s,年龄是 %s' %(self.name, self.age)
    
    t = test('libai', 20)
    print(t)
    print('---------------------------------')
    l = list('www.baidu.com')
    print(type(l))
    
    输出结果:
    名字是 libai,年龄是 20
    ---------------------------------
    <class 'list'>
    

    自定制 repr 方法,当 repr 与 str 同时存在时,会执行 str 方法,当没有 str 时,执行 repr
    print 调用的就是 str 方法,repr是交互式界面返回的值

    class test:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def __str__(self):
            return '名字是 %s,年龄是 %s' %(self.name, self.age)
    
        def __repr__(self):
            return "return repr"
    
    t = test('libai', 20)
    print(t)
    
    输出结果:
    名字是 libai,年龄是 20
    

    自定制 format 方法,格式化输出

    format_dict = {
        'ymd' : '{0.year} {0.mon} {0.day}',
        'y-m-d' : '{0.year}-{0.mon}-{0.day}',
        'y:m:d' : '{0.year}:{0.mon}:{0.day}'
    }
    class Date:
        def __init__(self, year, mon, day):
            self.year = year
            self.mon = mon
            self.day = day
        def __format__(self, format_spec):
            print("my format, format_spec = '%s'" %format_spec)
            if format_spec and format_spec in format_dict:
                return format_dict[format_spec].format(self)
            else:
                return format_dict['ymd'].format(self)
    d = Date(2018, 4, 18)
    print('{0.year} {0.mon} {0.day}'.format(d)) #一般的格式化输出
    
    print(format(d, 'none')) #自定义格式化输出
    print(format(d, 'y-m-d'))
    print(format(d, 'y:m:d'))
    
    输出结果:
    my format, format_spec = 'none'
    2018 4 18
    my format, format_spec = 'y-m-d'
    2018-4-18
    my format, format_spec = 'y:m:d'
    2018:4:18
    
    

    类实例化后都会建立一个各自的字典,公共的属性调用类的

    class Date:
        def __init__(self, name ,age):
            self.name = name
            self.age = age
        x = 1
    
    d1 = Date('libai', 20)
    d2 = Date('baicai', 12)
    
    print("d1.name = %s, id(d1.name) = %s " %(d1.name,id(d1.name)))
    print("d1.age = %s, id(d1.age) = %s " %(d1.age,id(d1.age)))
    print("d1.x = %s, id(d1.x) = %s " %(d1.x,id(d1.x)))  #d1.x 的id 等于 d2.x 的id
    print('-------------------------------------------')
    print("d2.name = %s, id(d2.name) = %s " %(d2.name,id(d2.name)))
    print("d2.age = %s, id(d2.age) = %s " %(d2.age,id(d2.age)))
    print("d2.x = %s, id(d2.x) = %s " %(d2.x,id(d2.x)))
    
    输出结果:
    d1.name = libai, id(d1.name) = 1733015461592 
    d1.age = 20, id(d1.age) = 1989374016 
    d1.x = 1, id(d1.x) = 1989373408 #=================
    -------------------------------------------
    d2.name = baicai, id(d2.name) = 1733015480112 
    d2.age = 12, id(d2.age) = 1989373760 
    d2.x = 1, id(d2.x) = 1989373408 #=================
    
    

    slots 属性可以优化内存(一般不会用到)

    class earth:  # 只能定义name 和 age 属性,优化内存
        __slots__ = ['name', 'age']
    
    d = earth()
    print(d.__slots__)
    d.name = 'libai'
    d.age = 20
    
    输出结果:
    ['name', 'age']
    

    doc 属性不能继承

    class earth:
        '描述信息'
        pass
    class son(earth): # __doc__ 属性不能继承
        pass
    
    d = earth()
    
    print(earth.__dict__)
    print(son.__dict__)
    print(d.__dict__)
    
    输出结果:
    {'__module__': '__main__', '__doc__': '描述信息', '__dict__': <attribute '__dict__' of 'earth' objects>, '__weakref__': <attribute '__weakref__' of 'earth' objects>}
    {'__module__': '__main__', '__doc__': None}
    {}
    

    moduleclass 模块
    module 查看在哪一个模块
    class 查看是由哪个类产生的

    # a 目录下的 test.py 文件
    class C:
        def __init__(self):
            self.name = 'libai'
    
    # 与 a 目录同级别的文件
    from a.test import C
    t = C()
    print(t.name)
    print(t.__module__)
    print(t.__class__)
    
    输出结果:
    libai
    a.test
    <class 'a.test.C'>
    
    

    析构函数 del,实例被系统回收时触发

    class earth:
        def __init__(self):
            self.name = 'libai'
        def __del__(self):
            print('del is work')
    e = earth()
    print(e.name)
    del e.name  #不会触发 __del__ 函数
    #程序结束时实例被系统回收,触发 __del__ 函数
    
    输出结果:
    libai
    del is work
    

    call 方法

    class earth:
        def __call__(self, *args, **kwargs):
            print('call is work')
    
    f= earth()
    f()  #调用类 earth 下的 __call__ 方法
    

    迭代器,iternext

    class Fib():
        def __init__(self):
            self.a = 1
            self.b = 1
            self.time = 0 #计算执行 __iter__ 次数
        def __iter__(self): #把对象变成可迭代,可以看到,只调用一次迭代器 __iter__ 方法
            self.time += 1
            return self
        def __next__(self):
            self.a, self.b = self.b, self.a+self.b
            if self.a > 20:
                raise StopIteration('终止了')
            return self.time,self.a
    
    f = Fib()
    print(next(f)) #只会向前,不会后退
    print(next(f))
    print(next(f))
    print('==========================')
    for i in f:
        print(i)
    print('==========================')
    print(next(f))
    
    输出结果:
    (0, 1)
    (0, 2)
    (0, 3)
    ==========================
    (1, 5)
    (1, 8)
    (1, 13)
    ========================== # 再次调用时引发 Stopiteration 异常
      File "C:/PycharmProjects/begin/begin", line 12, in __next__
        raise StopIteration('终止了')
    StopIteration: 终止了
    

    优先级

    1. 类属性
    2. 数据描述符
    3. 实例属性
    4. 非数据描述符
    5. 找不到的属性触发 getattr()

    用pickle 序列化输入输出

    #a.py 文件
    import pickle
    
    class earth:
        pass
    e = earth()
    
    with open('a.txt', 'wb') as f:
        pickle.dump(e, f)
    
    # b.py 文件
    import pickle
    
    class earth:
        pass
    
    with open('a.txt', 'rb') as f:
        pickle.load(f)
    

    在 pycharm 中导入同个项目下的文件时 pycharm 会自动在环境变量中添加路径,但是一旦离开了 pycharm 就不能导入了,所以我们要手动添加可变环境变量

    # 在 a 目录下的 test.py 文件中写了这个
    def hello():
        print('你好啊')
    
    #与 a 目录同级别的目录
    import sys, os
    
    BASE_DIR = os.path.dirname(os.path.dirname(__file__))
    sys.path.append(BASE_DIR)
    
    print(os.path.dirname(__file__))  # os.path.dirname() 的作用就是返回到上级目录
    print(os.path.dirname(os.path.dirname(__file__)))
    print(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
    
    from a import test
    test.hello()
    
    输出结果:
    C:/Users/libai/PycharmProjects/begin
    C:/Users/libai/PycharmProjects
    C:/Users/libai
    你好啊
    

    相关文章

      网友评论

          本文标题:day27

          本文链接:https://www.haomeiwen.com/subject/owopkftx.html