内置函数isinstance,issubclass ,反射,自定义内置方法来定制类的功能,元类

一:内置函数 

     1,isinstance 判断某个对象是不是属于某一类型?

        class Foo:
            pass
        obj=Foo()

        print(isinstance(obj,Foo))# 在python3中统一类与类型的概念返回True 或者False

      2,issubclass 判断一个类是不是另一个类的子类

        class Parent:
            pass
        class Sub(Parent):
            pass
        print(issubclass(Sub,Parent))

        print(issubclass(Parent,object))#返回True或者False

二:反射

        反射:就是通过字符串来操作类或者对象的属性

        用:hasattr
               getattr
                setattr
                delattr

       class People:
            country='China'
            def __init__(self,name):
                self.name=name
            def eat(self):
                print('%s is eating' %self.name)
            peo1=People('egon')
            # print(hasattr(peo1,'eat')) #peo1.eat
            # print(getattr(peo1,'eat')) #peo1.eat
            # print(getattr(peo1,'xxxxx',None))
            # setattr(peo1,'age',18) #peo1.age=18
            # print(peo1.age)
            # print(peo1.__dict__)
            # delattr(peo1,'name') #del peo1.name

            # print(peo1.__dict__)     

             应用场景:

                class Ftp:
                    def __init__(self,ip,port):
                        self.ip=ip
                        self.port=port
                    def get(self):
                        print('GET function')
                    def put(self):
                        print('PUT function')
                    def run(self):
                        while True:
                            choice=input('>>>: ').strip()#接收用户输入的字符串映射到具体的属性
                            # print(choice,type(choice))
                            # if hasattr(self,choice):
                            #     method=getattr(self,choice)
                            #     method()
                            # else:
                            #     print('输入的命令不存在')
                            method=getattr(self,choice,None)
                            if method is None:
                                print('输入的命令不存在')
                            else:
                                method()
                    conn=Ftp('1.1.1.1',23)
                    conn.run()

  三:自定义内置函数方法?

                #1、__str__方法
                # class People:
                #     def __init__(self,name,age):
                #         self.name=name
                #         self.age=age

                #     #在对象被打印时,自动触发,应该在该方法内采集与对象self有关的信息,然后拼成字符串返回

                #     def __str__(self):
                #         # print('======>')
                #         return '<name:%s age:%s>' %(self.name,self.age)
                # obj=People('egon',18)
                # obj1=People('alex',18)
                # print(obj)  #obj.__str__()
                # print(obj)  #obj.__str__()
                # print(obj)  #obj.__str__()
                # print(obj1)  #obj1.__str__()

                #1、__del__析构方法
                # __del__会在对象被删除之前自动触发#只要是针对对象使用的
                class People:
                    def __init__(self,name,age):
                        self.name=name
                        self.age=age
                        self.f=open('a.txt','rt',encoding='utf-8')
                    def __del__(self):
                        # print('run=-====>')
                        # 做回收系统资源相关的事情
                        self.f.close()
                obj=People('egon',18)#对象obj已经被创建出来之后不会受类的影响,删除类之后也不会影响对象的使用

                print('主') 

四:元类

           4.1, 元类:在python中一切皆对象,那么我们用class 关键字定义的类本身也是一个对象。关键字定义的类本身也是一个对象。

            4.2,为什么要用元类:元类是负责产生类的,所以我们学习元类或者自定义元类的目的是为了控制类的产生过程,还可以控制对象的产生过程

            4.3  使用:

                #1、储备知识:内置函数exec的用法
                # cmd="""
                # x=1
                # def func(self):
                #     pass
                # """
                # class_dic={}
                # exec(cmd,{},class_dic)#excu用来模拟python解释器解释运行字符串格式的代码

                # print(class_dic)#得到一个名称空间放到class—dic中去

                #2、创建类的方法有两种
                # 大前提:如果说类也是对象的化,那么用class关键字的去创建类的过程也是一个实例化的过程
                # 该实例化的目的是为了得到一个类,调用的是元类
                #2.1 方式一:用的默认的元类type
                # class People: #People=type(...)
                #     country='China'
                #     def __init__(self,name,age):
                #         self.name=name
                #         self.age=age
                #     def eat(self):
                #         print('%s is eating' %self.name)
                # print(type(People))

                #2.1.1 创建类的3个要素:类名,基类,类的名称空间
                class_name='People'
                class_bases=(object,)#基类写成元祖形式,用内置方法__bases__查看基类
                class_dic={}
                class_body="""   #类体代码
                country='China'
                def __init__(self,name,age):
                self.name=name
                self.age=age
                def eat(self):

                    print('%s is eating' %self.name)

                    """

                 exec(class_body,{},class_dic)

                # 准备好创建类的三要素
                # print(class_name)
                # print(class_bases)
                # print(class_dic)
                # People=type(类名,基类,类的名称空间)
                # People1=type(class_name,class_bases,class_dic)
                # print(People1)
                # obj1=People1('egon',18)
                # print(People)
                # obj=People('egon',18)
                #
                # obj1.eat()
                # obj.eat()

                #2.2 方式二:用的自定义的元类
                class Mymeta(type): #只有继承了type类才能称之为一个元类,否则就是一个普通的自定义类
                    def __init__(self,class_name,class_bases,class_dic):
                        print(self) #现在是People
                        print(class_name)
                        print(class_bases)
                        print(class_dic)
                        super(Mymeta,self).__init__(class_name,class_bases,class_dic) #重用父类的功能    

                # 分析用class自定义类的运行原理(而非元类的的运行原理):
                #1、拿到一个字符串格式的类名class_name='People'
                #2、拿到一个类的基类们class_bases=(obejct,)
                #3、执行类体代码,拿到一个类的名称空间class_dic={...}
                #4、调用People=type(class_name,class_bases,class_dic)
                class People(object,metaclass=Mymeta): #People=Mymeta(类名,基类们,类的名称空间)
                    country='China'
                    def __init__(self,name,age):
                        self.name=name
                        self.age=age
                    def eat(self):

                        print('%s is eating' %self.name) 

                 # 应用:自定义元类控制类的产生过程,类的产生过程其实就是元类的调用过程
                class Mymeta(type): #只有继承了type类才能称之为一个元类,否则就是一个普通的自定义类
                    def __init__(self,class_name,class_bases,class_dic):
                        if class_dic.get('__doc__') is None or len(class_dic.get('__doc__').strip()) == 0:
                            raise TypeError('类中必须有文档注释,并且文档注释不能为空')
                        if not class_name.istitle():
                            raise TypeError('类名首字母必须大写')
                        super(Mymeta,self).__init__(class_name,class_bases,class_dic) #重用父类的功能
                class People(object,metaclass=Mymeta): #People=Mymeta('People',(object,),{....})
                    """这是People类"""
                    country='China'
                    def __init__(self,name,age):
                        self.name=name
                        self.age=age
                    def eat(self):
                        print('%s is eating' %self.name)

            #3 储备知识:__call__
            # class Foo:
            #     def __call__(self, *args, **kwargs):
                #         print(self)
                #         print(args)
                #         print(kwargs)
                # obj=Foo()
                #
                # # 要想让obj这个对象变成一个可调用的对象,需要在该对象的类中定义一个方法__call__方法
                # # 该方法会在调用对象时自动触发
                # obj(1,2,3,x=1,y=2)                      

            # 4、自定义元类来控制类的调用的过程,即类的实例化过程
            class Mymeta(type):
                def __call__(self, *args, **kwargs):
                    # print(self) # self是People
                    # print(args)
                    # print(kwargs)
                    # return 123
                    # 1、先造出一个People的空对象
                    obj=self.__new__(self)
                    # 2、为该对空对象初始化独有的属性
                    # print(args,kwargs)
                    self.__init__(obj,*args,**kwargs)
                    # 3、返回一个初始好的对象
                    return obj

            class People(object,metaclass=Mymeta):
                country='China'
                def __init__(self,name,age):
                    self.name=name
                    self.age=age
                def eat(self):
                    print('%s is eating' %self.name)
                def __new__(cls, *args, **kwargs):
                    print(cls)
                    # cls.__new__(cls) # 错误
                    obj=object.__new__(cls)
                    return obj
            # 分析:调用Pepole的目的
            #1、先造出一个People的空对象
            #2、为该对空对象初始化独有的属性
            # obj1=People('egon1',age=18)
            # obj2=People('egon2',age=18)
            # print(obj1)
            # print(obj2)
            obj=People('egon',age=18)
            print(obj.__dict__)
            print(obj.name)
            obj.eat()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值