zoukankan      html  css  js  c++  java
  • 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__方法

      面向对象进阶

  • 相关阅读:
    UVA 10600 ACM Contest and Blackout(次小生成树)
    UVA 10369
    UVA Live 6437 Power Plant 最小生成树
    UVA 1151 Buy or Build MST(最小生成树)
    UVA 1395 Slim Span 最小生成树
    POJ 1679 The Unique MST 次小生成树
    POJ 1789 Truck History 最小生成树
    POJ 1258 Agri-Net 最小生成树
    ubuntu 用法
    ubuntu 搭建ftp服务器,可以通过浏览器访问,filezilla上传文件等功能
  • 原文地址:https://www.cnblogs.com/python-Arvin/p/11889446.html
Copyright © 2011-2022 走看看