• Python开发——10.面向对象编程进阶


    一、isinstance(obj,cls)和issubclass(sub,super)

    1.isinstance(obj,cls)

      判断obj是不是由cls产生的类

    2.issubclass(sub,super)

      判断sub是否是super的子类

    3.代码

    class Foo:
        def __init__(self,name):
            self.name = name
    class Son(Foo):
        # pass
        def __init__(self,name):
            self.name = name
    f1 =Foo("dazui")
    f2 = Son("zuizui")
    print(isinstance(f1,Foo))#True,判断对象是否由类实例化而来的
    print(isinstance(f2,Foo))#True
    print(isinstance(f2,Son))#True
    
    print(issubclass(Son,Foo))#True
    print(issubclass(Foo,Son))#False
    print(type(f1),type(f2))#<class '__main__.Foo'> <class '__main__.Son'>

    二、反射

    1.定义

      通过字符串的形式操作对象相关的属性。

    2.四个函数

    class Intermedia:
        def __init__(self,name,addr):
            self.name = name
            self.addr = addr
        def rent_house(self):
            print("%s正在租房子"%(self.name))
    i1 = Intermedia("自如","翠屏山")
    #hasattr:判断对象是否包含指定的数据属性,也可以判断类是否包含指定的函数属性
    print(hasattr(i1,"name"))#True
    print(hasattr(Intermedia,"rent_house"))#True
    #getattr:传入三个参数,如果数据属性存在,则返回该数据属性的值,不存在则返回指定的内容
    print(getattr(i1,"name","自定义的内容"))#i1没有nam22e这个属性,打印“自定义内容”
    #setattr:设置数据属性和函数属性
    setattr(i1,"price",1600)
    print(i1.__dict__)#{'price': 1600, 'name': '自如', 'addr': '翠屏山'}
    #删除属性
    delattr(i1,"price")
    print(i1.__dict__)#{'name': '自如', 'addr': '翠屏山'}
    delattr(Intermedia,"rent_house")

    3.优点

    (1)实现可插拔机制

    class FtpClient:
        "Ftp客户端,但具体功能还没实现"
        def __init__(self,addr):
            self.addr = addr
        def put(self):
            print("正在上传文件")
    from ftp_client import FtpClient
    
    f1 = FtpClient("1.1.1.1")
    if hasattr(f1,"put"):
        func_get = getattr(f1,"put")
        func_get()
    else:
        print("执行其他功能")

    (2)动态导入模块

    import  importlib
    module_t = importlib.import_module("m1.test")
    print(module_t)#<module 'm1.test' from 'D:\python_s3\day27\m1\test.py'>
    module_t.test1()
    module_t._test2()
    from m1 import test
    test.test1()
    test._test2()
    
    module_t = __import__("m1.test")
    print(module_t)#<module 'm1' from 'D:\python_s3\day27\m1\__init__.py'>
    module_t.test.test1()
    module_t.test._test2()
    
    from m1.test import *
    test1()
    _test2()#用*的方式导入找不到_test2()
    from m1.test import test1,_test2
    test1()
    _test2()

    三、__setattr__、__delattr__和__getattr__

    class Foo:
        y = 24
        def __init__(self,x):
            self.x = x
        def __getattr__(self, item):
            print("执行__getattr__")
        def __delattr__(self, item):
            print("执行__delattr__")
        def __setattr__(self, key, value):
            print("执行__setattr__")
            self.__dict__[key] = value
    f1 = Foo(8)
    
    #__getattr__,当要找的属性不存在时,执行__getattr__
    getattr(f1,"不存在")#执行__getattr__
    #__delattr__:当实例删除属性时,执行
    del f1.y#执行__delattr__
    del Foo.y#不执行__delattr__
    #设置属性时执行__setattr__
    f1 = Foo(8)#执行__setattr__
    f1.z = 6#执行__setattr__

    四、二次加工标准类型

    1.包装

      利用继承和派生知识,基于标准的数据类型来定制需求的数据类型,新增或改写方法。包装一个类型通常是对已存在的类型的一些定制,可以新建、修改或删除原有功能,其他保持不变

    class List(list):
        def append(self, p_object):
            if type(p_object)==str:
                # list.append(self,p_object)
                super().append(p_object)
            else:
                print("输入的不是字符串类型")
        def show_middle(self):
            return self[int(len(self)/2)]
    l = List("hello world!")
    print(l)
    l.append(123)#输入的不是字符串类型

    2.授权

      授权是包装的一个特性,授权的过程是所以更新的功能都由新类的某部分来处理,已存在的功能设为对象的默认属性

    import time
    class Open:
        def __init__(self,filename,mode,encoding="utf-8"):
            # self.filename = filename
            self.file = open(filename,mode,encoding=encoding)
            self.mode = mode
            self.encoding = encoding
        def write(self,line):
            t = time.strftime("%Y-%m-%D %X")
            self.file.write("%s %s" %(t,line))
        def __getattr__(self, item):
            return getattr(self.file,item)
    f1 = Open("a.txt","w")
    f1.write("111111
    ")
    f1.write("222222
    ")

    五、__getattribute__  

    class Foo:
        def __init__(self,name):
            self.name = name
        def __getattr__(self, item):
            print("执行getattr")
        def __getattribute__(self, item):#无论能否找到都执行__getattribute__,只有抛出AttributeError时会执行__getattr__        print("执行getattribute")
            raise AttributeError("抛出异常")#会去执行__getattr__
            # raise TabError("抛出异常")#不会去执行__getattr__
    
    f1 = Foo("大嘴")
    f1.age

    六、__setitem__、__getitem__和__delitem__

    class Foo:
        def __init__(self,name):
            self.name = name
        def __getitem__(self, item):
            print("执行__getitem__")
            return self.__dict__[item]
        def __setitem__(self, key, value):
            print("执行__setitem__")
        def __delitem__(self, key):
            print("执行__delitem__")
    
    f1 = Foo("dazui")
    
    print(f1["name"])#执行__getitem__
    f1["age"]=18#执行__setitem__
    del f1["name"]#执行__delitem__

    七、__str__、__repr__和__format__

    1.利用__str__或__repr__改变对象的字符串显示

    class Foo:
        def __init__(self,name,age):
            self.name = name
            self.age = age
        def __str__(self):
            return "这是str的返回结果  name:%s age: %s" %(self.name,self.age)
        def __repr__(self):
            return "这是repr的返回结果  name:%s age: %s" %(self.name,self.age)
    f1 = Foo("大嘴",80)
    print(f1)#<__main__.Foo object at 0x001D5F30>默认显示,
    # 定义__str__时,显示str的返回值;没有__str__,定义了__repr__,显示repr的返回值

    2.利用__format__定制格式化字符串

    format_dic={
        "ymd":"{0.y} {0.m} {0.d}",
        "y:m:d":"{0.y}:{0.m}:{0.d}",
        "d-m-y":"{0.d}-{0.m}-{0.y}"
    }
    class Data:
        def __init__(self,y,m,d):
            self.y = y
            self.m = m
            self.d = d
        def __format__(self, format_spec):
            print("执行__format__")
            print(format_spec)
            if not format_spec or format_spec not in format_dic:
                format_spec = "ymd"
            fm = format_dic[format_spec]
            return fm.format(self)
    
    d1 = Data(2018,5,18)
    print(format(d1,"yaaaaaaaaa"))

    八、__slots__

    # 节省内存,对象不能新建数据属性
    class Foo:
        __slots__ = ["name","age"]
    f1=Foo()
    print(Foo.__slots__)
    print(f1.__slots__)
    f1.name = "dazui"
    f1.age = 80
    print(f1.name,f1.age)
    f1.gender = "female"#'Foo' object has no attribute 'gender'

    九、__next__和__iter__实现迭代器协议

    1.代码

    class Foo:
        def __init__(self,x):
            self.x = x
        def __iter__(self):
            return self
        def __next__(self):
            if self.x == 15:
                raise StopIteration("迭代器中止")
            self.x += 1
            return self.x
    f1 = Foo(10)
    print(f1.__next__())
    print(next(f1))
    for i in f1:#从13开始循环
        print(i)

    2.实现菲波那切数列

    class Fib:
        def __init__(self,a,b):
            self._a = a
            self._b = b
        def __iter__(self):
            return self
        def __next__(self):
            if self._a>200:
                raise StopIteration
            self._a,self._b = self._b,self._a+self._b
            return self._a
    f1 = Fib(1,2)
    print(next(f1))
    print(f1.__next__)
    print("<><><><><><><><><><><><><><><><>")
    for i in f1:
        print(i)

    十、__doc__

    #描述信息不会被继承
    class Foo:
        "Foo的描述信息"
        pass
    class Son(Foo):
        pass
    print(Foo.__doc__)#Foo的描述信息
    print(Son.__doc__)#None

    十一、__module__和__class__

    __module__表示当前操作对象在哪个模块

    __class__表示当前操作对象的类

    from test.test1 import Foo
    f1 = Foo("dazui")
    print(f1.__module__)#test.test1
    print(f1.__class__)#<class 'test.test1.Foo'>

    十二、__del__

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

    class Foo:
        def __init__(self,name):
            self.name = name
        def __del__(self):
            print("执行析构函数")
    f1 = Foo("dazui")#执行析构函数
    # del f1.name
    # print("<><>")#先打印"<><>",然后执行构析函数释放内存
    #<><>
    # 执行析构函数
    del f1#先执行构析函数释放内存,然后打印"<><>"
    print("<><>")
    #执行析构函数
    # <><>

    十三、__call__

    #对象后面加(),触发执行
    class Foo:
        def __call__(self, *args, **kwargs):
            print("执行__call__")
    f1 = Foo()
    f1()#执行__call__

    十四、__enter和__exit__

    1.with语句

      又称上下文管理协议,为了让一个对象兼容with语句,必须在这个对象的类中声明__enter__和__exit__方法

    2.优点

    (1)使用with语句的目的就是把代码块放入with中执行,with结束后,自动完成清理工作,无须手动干预

    (2)在需要管理一些资源比如文件,网络连接和锁的编程环境中,可以在__exit__中定制自动释放资源的机制。

    3.代码

    class Foo:
        def __init__(self,name):
            self.name = name
        def __enter__(self):
            print("执行__enter__")#出现with语句,执行,返回值赋给as声明的变量
            return self
        def __exit__(self, exc_type, exc_val, exc_tb):
            print("执行__exit__")
            print(exc_type)#异常类
            print(exc_val)#异常值
            print(exc_tb)#追踪信息
            return True#异常被清空,with后面的语句正常执行,如不返回,会抛出异常,,程序停止执行
    with Foo("a.txt") as f :
        print(f)
        print(大嘴)
    print("<><><><><><><><><><><>")

    十五、metaclass

      元类是类的类,元类创建类正如类创建对象,当一个类没有声明自己的元类,它的默认元类就是type,,除了使用元类type,用户也可通过继承type来自定义元类

    1.另一种定义类的方式

    def __init__(self,name,age):
        self.name = name
        self.age = age
    def test(self):
        print("test")
    Foo = type("Foo",(object,),{"x":1,"__init__":__init__,"test":test})
    f1 = Foo("dazui",18)
    print(f1.name)
    f1.test()

    2.自定义元类

    class MyType(type):
        def __init__(self,a,b,c):
            print(self,a,b,c)
            print("元类的构造函数执行")
        def __call__(self, *args, **kwargs):
            print(self,*args,**kwargs)
            obj = object.__new__(self)
            self.__init__(obj,*args,**kwargs)
            return obj
    class Foo(metaclass=MyType):
        def __init__(self,name):
            self.name = name
    f1 = Foo("alex")

    十六、property

      一个静态属性property本质就是实现了get、set、delete三种方法

    class Goods:
        def __init__(self):
            self.original_price = 100
            self.discount = 0.8
    
        @property
        def new_price(self):
            new_price = self.original_price*self.discount
            return new_price
        @new_price.setter
        def price(self,value):
            self.original_price = value
        @new_price.deleter
        def del_price(self):
            del self.original_price
    g1 = Goods()
    print(g1.new_price)
    g1.price = 200
    print(g1.original_price)
    
    del g1.original_price
    class Foo:
        def get_AAA(self):
            print("get的时候运行")
        def set_AAA(self,value):
            print("get的时候运行")
        def del_AAA(self):
            print("del的时候运行")
        AAA = property(get_AAA,set_AAA,del_AAA)
    f1 = Foo()
    f1.AAA = "aaa"
    del f1.AAA

    十七、 描述符

    1.描述符定义

      描述符本质就是一个新式类,在这个新式类中,至少实现了__get__(),__set__()和__delete__()中的一个

       __get__():调用一个属性时触发

      __set__():设置一个属性时触发

       __get__():调用一个属性时触发

    2.作用

      描述符是用来代理另外一个类的属性,必须把描述符定义为这个类的类属性,不能定义到构造函数中

    3.分类

    (1)数据描述符:至少实现了__get__()和__set__()

    (2)非数据描述符:没有实现__set__()

    4.优先级

      从高到低类属性>s数据描述符>实例属性>非数据描述符>找不到属性触发__getattr__()

    5.描述符的应用

    class Nametype:
        def __init__(self,key,expected_type):
            self.key = key
            self.expected_type = expected_type
        def __get__(self, instance, owner):
            print("__get__方法")
            return instance.__dict__[self.key]
        def __set__(self, instance, value):
            print("__set__方法")
            if not isinstance(value,self.expected_type):
                raise TypeError("%s输入类型错误,不是%s" %(self.key,self.expected_type))
            instance.__dict__[self.key] =value
        def __delete__(self, instance):
            instance.__dict__.pop(self.key)
    
    class People:
        name = Nametype("name",str)
        age = Nametype("age",int)
        def __init__(self,name,age,salary):
            self.name = name
            self.age = age
            self.salary = salary
    p1 = People("dazui","18",19999)

    6.类的装饰器

    def deco(obj):
        print(obj)
        obj.x = 1
        obj.y = 2
        obj.z = 3
        return obj
    @deco#Foo = deco(Foo)
    class Foo:
        pass
    print(Foo.__dict__)
    def Typed(**kwargs):
        def deco(obj):
            for key,val in kwargs.items():
                setattr(obj,key,val)
                return obj
        return deco
    @Typed(x = 1,y = 2,z= 3)
    class Foo:
        pass
    
    print(Foo.__dict__)
    
    @Typed(name = "dazui")
    class Bar:
        pass
    print(Bar.__dict__)

    7.类的装饰器应用

    class Nametype:
        def __init__(self,key,expected_type):
            self.key = key
            self.expected_type = expected_type
        def __get__(self, instance, owner):
            return instance.__dict__[self.key]
        def __set__(self, instance, value):
            if not isinstance(value,self.expected_type):
                raise TypeError("%s输入类型错误,不是%s" %(self.key,self.expected_type))
            instance.__dict__[self.key] =value
        def __delete__(self, instance):
            instance.__dict__.pop(self.key)
    
    def deco(**kwargs):
        def wrapper(obj):
            for key,val in kwargs.items():
                setattr(obj,key,Nametype(key,val))
            return obj
        return wrapper
    
    
    
    @deco(name = str,age = int)
    class People:
        def __init__(self,name,age,salary):
            self.name = name
            self.age = age
            self.salary = salary
    p1 = People("dazui","18",1000)
    print(p1.__dict__)
    类的装饰器应用
  • 相关阅读:
    全文搜索(AB-2)-权重
    全文搜索(A-2)-推荐算法
    全文检索(AB-1)-相关领域
    全文搜索(A)-相关性
    ElasticSearch全文搜索引擎(A)
    mvc 的HtmlHelper
    left join 与left outer join的区别
    ms sqlserver数据库建索引
    w3c xml
    System and method for critical address space protection in a hypervisor environment
  • 原文地址:https://www.cnblogs.com/hechengwei/p/9069516.html
Copyright © 2020-2023  润新知