• python3全栈开发-内置函数补充,反射,元类,__str__,__del__,exec,type,__call__方法


    一、内置函数补充

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

    class Foo(object):
      pass
    obj = Foo()                 
    print(isinstance(obj, Foo))  #结果为True

    2、issubclass(sub, super)检查sub类是否是 super 类的派生类

    class Foo(object):
      pass
    class Bar(Foo):
      pass
    print(issubclass(Bar, Foo))  #结果为True

    二、 反射

    1 、什么是反射

      反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。

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

    四个可以实现自省的函数:

    hasattrgetattrsetattrdelattr

    下列方法适用于类和对象(一切皆对象,类本身也是一个对象)

    # 1、hasattr
    # print(hasattr(People,'country'))  #True
    # print('country' in People.__dict__)    #不知道hasattr方法时,用的方法
    # print(hasattr(obj,'name'))          #True
    # print(hasattr(obj,'country'))       #True
    # print(hasattr(obj,'tell'))          #True
    
    # 2、getattr
    # x=getattr(People,'country1',None)      #查找指定属性,没有此属性(提前预防报错写None)显示None,有就返回值
    # print(x)
    # f=getattr(obj,'tell',None)#obj.tell
    # print(f == obj.tell)                 #True
    # f()                               #正常的调用函数
    # obj.tell()
    
    # 3、setattr
    # People.x=111
    # setattr(People,'x',111)              #添加x属性,值为111
    # print(People.x)
    # obj.age=18                      
    # setattr(obj,"age",18)             # 添加age属性,值为18
    # print(obj.__dict__)
    
    # 4、delattr
    # del People.country               #原始的方法
    # delattr(People,"country")             
    # print(People.__dict__)
    # del obj.name
    # delattr(obj,"name")
    # print(obj.__dict__)

    三、__str__

    class People:
        def __init__(self,name,age,sex):
            self.name=name
            self.age=age
            self.sex=sex
    
        def __str__(self):
            # print('========>')
            return '<名字:%s 年龄:%s 性别:%s>' %(self.name,self.age,self.sex)
    
    obj=People('duoduo',18,'male')
    print(obj) #print(obj.__str__())  在print时触发__str__

    四、 __del__

    当对象在内存中被释放时,自动触发执行。

    注:如果产生的对象仅仅只是python程序级别的(用户级),那么无需定义__del__,如果产生的对象的同时还会向操作系统发起系统调用,即一个对象有用户级与内核级两种资源

    import time
    
    class People:
        def __init__(self,name,age,sex):
            self.name=name
            self.age=age
            self.sex=sex
    
        def __del__(self): # 在对象被删除的条件下,自动执行
            print('__del__')
    
    obj=People('duoduo',18,'male')
    
    #del obj #obj.__del__()      #先删除的情况下,直接执行__del__
    
    time.sleep(5)    #可以更形象的看出在资源回收前执行__del__

    典型的应用场景:

    创建数据库类,用该类实例化出数据库链接对象,对象本身是存放于用户空间内存中,而链接则是由操作系统管理的,存放于内核空间内存中

    当程序结束时,python只会回收自己的内存空间,即用户态内存,而操作系统的资源则没有被回收,这就需要我们定制__del__,在对象被删除前向操作系统发起关闭数据库链接的系统调用,回收资源

    这与文件处理是一个道理:

    f=open('a.txt') #做了两件事,在用户空间拿到一个f变量,在操作系统内核空间打开一个文件
    del f #只回收用户空间的f,操作系统的文件还处于打开状态
    #所以我们应该在del f之前保证f.close()执行,即便是没有del,程序执行完毕也会自动del清理资源,于是文件操作的正确用法应该是
    f=open('a.txt')
    读写...
    f.close()
    #很多情况下大家都容易忽略f.close,这就用到了with上下文管理
    
    class MyOpen:          #自己写个打开读文件类,封装内置的open
        def __init__(self,filepath,mode="r",encoding="utf-8"):
            self.filepath=filepath
            self.mode=mode
            self.encoding=encoding
            self.fobj=open(filepath,mode=mode,encoding=encoding)  #申请系统内存
    
        def __str__(self):
            msg="""
            filepath:%s
            mode:%s
            encoding:%s
            """ %(self.filepath,self.mode,self.encoding)
            return msg
    
        def __del__(self):
            self.fobj.close()
    
    f=MyOpen('aaa.py',mode='r',encoding='utf-8')
    # print(f.filepath,f.mode,f.encoding)
    # print(f)
    
    # print(f.fobj)
    res=f.fobj.read()   #一样可以读
    print(res)

    五、exec

    #例子 一
    code="""                     
    #global x     #shsh声明x为全局变量
    x=0
    y=2
    """
    global_dic={'x':100000}
    local_dic={}         #字符串中声明全局就是全局,不声明就是局部
    exec(code,global_dic,local_dic)
    #
    # print(global_dic)
    # print(local_dic)
    
    #例子 二
    # code="""
    # x=1
    # y=2
    # def f1(self,a,b):
    #     pass
    # """
    # local_dic={}
    # exec(code,{},local_dic)
    # print(local_dic)

    六、元类

    1、什么是元类:

      类的类就是元类
    #我们用class定义的类使用来产生我们自己的对象的
    #内置元类type是用来专门产生class定义的类的

    #一切皆为对象:
    # Chinese=type(...)
     class Chinese:
         country="China"
    
         def __init__(self,name,age,sex):
             self.name=name
             self.age=age
             self.sex=sex
    
         def speak(self):
             print('%s speak Chinese' %self.name)
    
    # print(Chinese)
    # p=Chinese('duoduo',18,'male')
    # print(type(p))     #最上层的类 type
    
    # print(type(Chinese))

    2、用内置的元类type,来实例化得到我们的类

    #2、用内置的元类type,来实例化得到我们的类
    class_name='Chinese'
    class_bases=(object,)
    lass_body="""
    country="China"
    def __init__(self,name,age,sex):
         self.name=name
         self.age=age
         self.sex=sex
     def speak(self):
         print('%s speak Chinese' %self.name)
     """
    class_dic={}
    exec(class_body,{},class_dic)
     #类的三大要素
    # print(class_name,class_bases,class_dic)
    
    Chinese=type(class_name,class_bases,class_dic)
    # print(Chinese)
    
    p=Chinese('duoduo',18,'male')
    # print(p.name,p.age,p.sex)

    3、 __call__ 

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

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

    class Foo:
        def __init__(self):
            pass
        def __str__(self):
            return '123123'
        def __del__(self):
            pass
        # 调用对象,则会自动触发对象下的绑定方法__call__的执行,
        # 然后将对象本身当作第一个参数传给self,将调用对象时括号内的值
        #传给*args与**kwargs
        def __call__(self, *args, **kwargs):
            print('__call__',args,kwargs)
    
    obj=Foo()
    # print(obj)
    
    obj(1,2,3,a=1,b=2,c=3) #

    4、自定义元类

    class Mymeta(type):
        # 来控制类Foo的创建
        def __init__(self,class_name,class_bases,class_dic): #self=Foo
            # print(class_name)
            # print(class_bases)
            # print(class_dic)
            if not class_name.istitle():     #加上判断
                raise TypeError('类名的首字母必须大写')
    
            if not class_dic.get('__doc__'):
                raise TypeError('类中必须写好文档注释')
                 
        super(Mymeta,self).__init__(class_name,class_bases,class_dic)
    
        # 控制类Foo的调用过程,即控制实例化Foo的过程
        def __call__(self, *args, **kwargs): #self=Foo,args=(1111,) kwargs={}
            # print(self)
            # print(args)
            # print(kwargs)
    
            #1 造一个空对象obj
            obj=object.__new__(self)
    
            #2、调用Foo.__init__,将obj连同调用Foo括号内的参数一同传给__init__
            self.__init__(obj,*args,**kwargs)
    
            return obj
    
    #Foo=Mymeta('Foo',(object,),class_dic)
    class Foo(object,metaclass=Mymeta):
        """
        文档注释
        """
        x=1
        def __init__(self,y):
            self.Y=y
    
        def f1(self):
            print('from f1')
    
    obj=Foo(1111) #Foo.__call__()
    
    # print(obj)
    # print(obj.y)
    # print(obj.f1)
    # print(obj.x)

    5、单例模式

    import settings   #调用配置文件的IP,PORT
    
    class MySQL:
        __instance=None
        def __init__(self,ip,port):
            self.ip=ip
            self.port=port
    
        @classmethod   #绑定方法
        def singleton(cls):
            if not cls.__instance:
                obj=cls(settings.IP, settings.PORT)  
                cls.__instance=obj
            return cls.__instance
    
    obj1=MySQL('1.1.1.2',3306)
    obj2=MySQL('1.1.1.3',3307)
    obj3=MySQL('1.1.1.4',3308)
    
    # obj4=MySQL(settings.IP,settings.PORT)
    # print(obj4.ip,obj4.port)
    
    obj4=MySQL.singleton()
    obj5=MySQL.singleton()
    obj6=MySQL.singleton()
    
    print(obj4 is obj5 is obj6)    #Ture
  • 相关阅读:
    XE8下安装IntraWeb 14.0.40和D7下安装IntraWeb 11.0.63破解版的正确方法
    网易博客打不开怎么办
    SQL SERVER 导入EXCEL的存储过程
    TMemoryStream、String与OleVariant互转
    【转载】Delphi Idhttp的get和post方法
    sqlserver得到行号
    Delphi 中的 XMLDocument 类详解(5)
    10款免费且开源的项目管理工具
    iOS开发者必备:九大设计类工具
    15个步骤创立技术公司,并收获千万用户(完结)
  • 原文地址:https://www.cnblogs.com/ManyQian/p/8868350.html
Copyright © 2020-2023  润新知