• Python之旅.第六章.面向对象高级


    一、内置函数补充 isinstance issubclass

    class Foo:

        pass

     

    obj=Foo()

     

    print(type(obj) is Foo)   #type可以完成但这不是type的主要用途,顾不推荐

    print(isinstance(obj,Foo)) # 推荐使用该函数来判断一个函数的类型

    print(isinstance('abc',str)) # ‘abc’是否是类str的一个对象/函数

    print(isinstance(123,int))

     

    print(issubclass(Foo,object))   #Foo是否是object的子类

     

    一、反射

    通过字符串来操作类与对象的属性,这种操作称为反射;反射也是内置函数

    下述四个函数是专门用来操作类与对象属性的

    class People:

        country="China"

        def __init__(self,name):

            self.name=name

        def tell(self):

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

     

    obj=People('egon')

     

    1hasattr

    print(hasattr(People,'country')) #可用来操纵类 # print('country' in People.__dict__)

    print(hasattr(obj,'name'))     #可用来操纵对象

    print(hasattr(obj,'country'))

    print(hasattr(obj,'tell'))

     

    2getattr

    print(getattr(People,'country1',None))  #如果没有返回None;若不写,没有报错

    f=getattr(obj,'tell',None)              #obj.tell

    f()                               #obj.tell()

     

    3setattr

    setattr(People,'x',111)   #People.x=111

    print(People.x)

    setattr(obj,"age",18)     #obj.age=18

    print(obj.__dict__)

     

    4delattr

    delattr(People,"country")   #del People.country

    print(People.__dict__)

    delattr(obj,"name")           #del obj.name

    print(obj.__dict__)

     

    #用户用input输入了字符串形式的指令,可以被反射以操纵类和对象的属性

    class Foo:

        def run(self):

            while True:

                cmd=input('cmd>>: ').strip()

                if hasattr(self,cmd):

                    func=getattr(self,cmd)

                    func()

     

        def download(self):

            print('download....')

     

        def upload(self):

            print('upload...')

     

    obj=Foo()

    obj.run()

     

    三、__str__方法

    __xxx__是满足一定条件时自动触发

    __str__ 当打印对象时自动触发,可用来定制打印格式

    class People:

        def __init__(self,name,age,sex):

            self.name=name

            self.age=age

            self.sex=sex

     

        def __str__(self):

            return '<名字:%s 年龄:%s 性别:%s>' %(self.name,self.age,self.sex)

     

    obj=People('egon',18,'male')

    print(obj) #print(obj.__str__()),若没有__str__,返回一个内存地址(原生状态)

     

    l=list([1,2,3])

    print(l)   #[1, 2, 3] python帮忙优化的,否则返回一个内存地址

     

    四、__del__方法

    __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('egon',18,'male')

    del obj #obj.__del__()  #若没有这一行,睡2s后会自动触发__del__,因为程序结束前会删除对象(清除资源)

    time.sleep(2)

     

    __del__的主要用途是回收系统资源

    class Mysql:

        def __init__(self,ip,port):

            self.ip=ip

            self.port=port

            self.conn=connect(ip,port) #申请系统资源, 此行为伪代码

        def __del__(self):

            self.conn.close()         #回收系统资源

     

    obj=Mysql('1.1.1.1',3306)

     

    class MyOpen:

        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)

     

    以下四个皆为绑定对象的方法,在满足一定条件时,自动触发

    __init__

    __str__

    __del__

    __call__

     

    五、元类

    exec执行字符串中的代码,将产生的名字存入global_dic(全局名称空间)和local_dic(局部名称空间)

    code="""

    global 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)  #{'x': 1, 'y': 2, 'f1': <function f1 at 0x101c60e18>}

     

    a 一切皆对象

    元类:类的类就是元类,内置元类type是用来专门产生class定义的类的

    我们用class定义的类来产生我们自己的对象的

    class Chinese:        #Chinese=type(...)

        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)        #<class '__main__.Chinese'>

    p=Chinese('egon',18,'male')

    print(type(p))        #对象p的类是类chinese   <class '__main__.Chinese'>

    print(type(Chinese))   #对象(类chinese)的类是类type  <class 'type'>

     

    class Foo:         #Foo=type(...)

        pass

    print(type(Foo))   #<class 'type'>

    f=Foo

    l=[Foo,]

    print(l)           #[<class '__main__.Foo'>]

     

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

    class_name='Chinese'

    class_bases=(object,)

    class_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('egon',18,'male')

    print(p.name,p.age,p.sex)

     

    c 储备知识 __call__

    调用对象,则会自动触发对象下的绑定方法__call__的执行,然后将对象本身当作第一个参数传给self,将调用对象时括号内的值传给*args**kwargs

    class Foo:

        def __init__(self):

            pass

        def __str__(self):

            return '123123'

        def __del__(self):

            pass

        def __call__(self, *args, **kwargs):

            print('__call__',args,kwargs)

     

    obj=Foo()

    print(obj)             #123123

    obj(1,2,3,a=1,b=2,c=3) #__call__ (1, 2, 3) {'a': 1, 'b': 2, 'c': 3}

     

    d 自定义元类

    class Mymeta(type):

        # 来控制类Foo的创建

        def __init__(self,class_name,class_bases,class_dic): #self=Foo

            if not class_name.istitle():

                raise TypeError('类名的首字母必须大写')

            if not class_dic.get('__doc__'):  #对象.__doc__看类注释,无注释返回None

                raise TypeError('类中必须写好文档注释')

            super(Mymeta,self).__init__(class_name,class_bases,class_dic) #其他的遗传object

     

        # 控制类Foo的调用过程,即控制实例化Foo的过程

        def __call__(self, *args, **kwargs): #self=Foo,args=(1111,) kwargs={}

            obj=object.__new__(self)  #1 造一个空对象obj

            self.__init__(obj,*args,**kwargs) #2、调用Foo.__init__,obj连同调用Foo括号内的参数一同传给__init__

            return obj

     

    class Foo(object,metaclass=Mymeta): # Foo=Mymeta('Foo',(object,),class_dic)

        """

        文档注释

        """

        x=1

        def __init__(self,y):

            self.y=y

        def f1(self):

            print('from f1')

     

    obj=Foo(1111)  #Foo.__call__()

    print(obj)     #<__main__.Foo object at 0x104501cf8>

    print(obj.y)   #1111

    print(obj.f1)  #<bound method Foo.f1 of <__main__.Foo object at 0x104501cf8>>

    print(obj.x)   #1

     

    e 单例模式

    import settings

    class MySQL:

        __instance=None   #instance隐藏使外部不能直接调用

        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)  #True

  • 相关阅读:
    对C#泛型中的new()约束思考
    c语言位运算符
    最简单易懂的委托例子
    静态方法是否属于线程安全
    使用JS实现鼠标滚轮事件
    Google Map 自定义 infowindow
    firefox下对ajax的onreadystatechange的支持情况分析及解决
    xcode7和ios9下UIWebView不能加载网页的解决方法
    在iOS平台使用ffmpeg解码h264视频流(转)
    Mac下批量删除.svn文件
  • 原文地址:https://www.cnblogs.com/yangli0504/p/8868698.html
Copyright © 2020-2023  润新知