• python类的学习笔记(二)


    isinstance和issubclass
    
    反射setattr、delattr、getattr、hasattr
    __str__和__repr__
    
    
    item系列__getitem__、__setitem____delitem__
    
    
    __del____new____call__
    
    with和__enter__、__exit__
    
    __len__

    isinstance(obj,cls)检查是否obj是否是类 cls 的对象

        class Foo(object):
            pass
    
        obj = Foo()
        print(isinstance(obj, Foo))

    issubclass(sub, super) 检查sub类是否是 super 类的子类

    class Foo(object):
        pass
    class Bar(Foo):
        pass
    print(issubclass(Bar, Foo))

    反射

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

    class People:
        f = '类的静态变量'
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        def say_hi(self):
            print('hi,%s'%(self.name))
    
    obj = People('wy',22)
    
    # 检测是否含有某属性 hasattr
    print(hasattr(obj,'name'))
    print(hasattr(obj,'say_hi'))
    # 获取属性 getattr
    n = getattr(obj,'name')
    print(n)
    s = getattr(obj,'say_hi')
    s()
    print(getattr(obj,'aaa','不存在'))
    # 设置属性 setattr
    print(obj.__dict__)
    setattr(obj,'sex','male')
    print(obj.__dict__)
    # 删除属性 delattr
    delattr(obj,'name')
    print(obj.__dict__)
    # delattr(obj,'nn')  不存在则报错

    __str__和__repr__方法

    __str__是在str()函数被使用,或是在print函数打印一个对象的时候才被调用的,并且它返回的字符串对终端用户更友好。

    如果只想实现这两个特殊方法中的一个,__repr__是更好的选择,因为如果一个对象没有__str__函数,而Python又需要调用它的时候,解释器会用__repr__作为替代。

    __repr__和__str__这两个方法都是用于显示的,__str__是面向用户的,而__repr__面向程序员。

    打印操作会首先尝试__str__和str内置函数(print运行的内部等价形式),它通常应该返回一个友好的显示。

    __repr__用于所有其他的环境中:用于交互模式下提示回应以及repr函数,如果没有使用__str__,会使用print和str。它通常应该返回一个编码字符串,可以用来重新创建对象,或者给开发者详细的显示。

    当我们想所有环境下都统一显示的话,可以重构__repr__方法;当我们想在不同环境下支持不同的显示,例如终端用户显示使用__str__,而程序员在开发期间则使用底层的__repr__来显示,实际上__str__只是覆盖了__repr__以得到更友好的用户显示。

    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('qinghua','北京','私立')
    print(s1)
    # 这里直接打印s1,如果有__str__,则打印__str__方法,没有则会打印__repr__方法
    ''' 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'))
    class B:
    
         def __str__(self):
             return 'str : class B'
    
         def __repr__(self):
             return 'repr : class B'
    
    
    b=B()
    print('%s'%b)
    print('%r'%b)

    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__)

    __getitem__

    #如果类把某个属性定义为序列,可以使用__getitem__()输出序列属性中的某个元素.
    class
    FruitShop(): def __getitem__(self,i): return self.fruits[i]#可迭代对象 if __name__ == "__main__": shop = FruitShop() print(shop) #__main__.FruitShop instance shop.fruits = ["apple", "banana"] print(shop[1]) #banana for item in shop: print(item)

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

    __new__ :

    1.创建类时先执行type的__init__方法,
    2.当一个类实例化时(创建一个对象)执行type的__call__方法,__call__方法的返回值就是实例化的对象
        __call__内部调用
          -类.__new__方法,创建一个对象
          -类.__init__方法,初始化对象

    实例化对象是谁取决于__new__方法,__new__返回什么就是什么

     __new__() 方法的特性:
    • __new__() 方法是在类准备将自身实例化时调用。
    • __new__() 方法始终都是类的静态方法,即使没有被加上静态方法装饰器
    class Foo(object):
        pass
    
    obj=Foo()  #默认是调用该类的直接父类的__new__()方法来构造该类的实例
    print(obj) #打印结果:<__main__.Foo object at 0x000002636FEAA208>
    
    事实上如果(新式)类中没有重写__new__()方法,即在定义新式类时没有重新定义__new__()时,Python默认是调用该类的直接父类的__new__()方法来构造该类的实例,
    如果该类的父类也没有重写__new__(),那么将一直按此规矩追溯至object的__new__()方法,因为object是所有新式类的基类。
    
    class F1(object):
      #重写__new__方法,返回这个重写的__new__方法
        def __new__(cls, *args, **kwargs):
            return 123
    
    obj=F1() #实例化对象是谁取决于__new__方法,__new__返回什么就是什么
    print(obj,type(obj))  #打印结果:123 <class 'int'>
    
    
    class F2(object):
        pass
    
    class F3(object):
        def __new__(cls, *args, **kwargs):
            return F2()
    
    obj=F3()    #实例化对象是谁取决于__new__方法,__new__返回什么就是什么
    print(obj)  #<__main__.F2 object at 0x00000210119BA4A8>
    
    
    
    如果要得到当前类的实例,应当在当前类中的 __new__() 方法语句中调用当前类的父类的 __new__() 方法。
    例如,如果当前类是直接继承自 object,那当前类的 __new__() 方法返回的对象应该为:
    
    
    def __new__(cls, *args, **kwargs):
        ...
        return object.__new__(cls)
    
    
    
    __new__至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供
    
    
    __new__必须要有返回值,返回实例化出来的实例,这点在自己实现__new__时要特别注意,可以return父类__new__出来的实例,或者直接是object的__new__出来的实例
    
    
    __init__有一个参数self,就是这个__new__返回的实例,__init__在__new__的基础上可以完成一些其它初始化的动作__init__不需要返回值

    __new__实现单例模式

    class Singleton:
        def __new__(cls, *args, **kw):
            if not hasattr(cls, '_instance'):
                cls._instance = object.__new__(cls)
            return cls._instance
    

    __call__

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

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

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

    with和__enter__,__exit__

    class A:
        def __enter__(self):
            print('before')
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print('after')
    
    
    with A() as a:
        print('123')

    class A:
        def __init__(self):
            print('init')
    
        def __enter__(self):
            print('before')
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print('after')
    
    
    with A() as a:
        print('123')

    pickle模块

    用于序列化的两个模块
      json:用于字符串和Python数据类型间进行转换
      pickle: 用于python特有的类型和python的数据类型间进行转换
      json提供四个功能:dumps,dump,loads,load
      pickle提供四个功能:dumps,dump,loads,load

    pickle可以存储什么类型的数据呢?

    1. 所有python支持的原生类型:布尔值,整数,浮点数,复数,字符串,字节,None。
    2. 由任何原生类型组成的列表,元组,字典和集合。
    3. 函数,类,类的实例

     pickle模块可能出现三种异常:

        1. PickleError:封装和拆封时出现的异常类,继承自Exception

        2. PicklingError: 遇到不可封装的对象时出现的异常,继承自PickleError

        3. UnPicklingError: 拆封对象过程中出现的异常,继承自PickleError

    import pickle
    class A:
        def __init__(self,name):
            self.name = name
        def test(self):
            print('%s是帅逼!'%(self.name))
    
    obj = A('wy')
    print(obj.name)
    with open('test','wb') as f:
        obj_d = pickle.dumps(obj)
        print(obj_d)
        f.write(obj_d)
    
    with open('test','rb') as f:
        obj_a = f.read()
        print(obj_a)
    
        obj_l = pickle.loads(obj_a)
        print(obj_l.name)
        print(obj_l.test())

    __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

     

    参考文献:

      python中的__new__方法

      面向对象进阶

  • 相关阅读:
    马云演讲稿
    马云演讲稿
    使用命令行+代理更新Android SDK
    GitHub 中国区前100 名技术专家
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
  • 原文地址:https://www.cnblogs.com/python-Arvin/p/11889446.html
Copyright © 2020-2023  润新知