• Python:Day25 成员修饰符、特殊成员、反射、单例


    一、成员修饰符

      共有成员

      私有成员,__字段名,__方法

        - 无法直接访问,只能间接访问

    class Foo:
        def __init__(self,name,age):
            self.name = name
            self.__age = age    #字段名前加双下划线就成私有成员了,外部无法直接访问
    
        def show(self):      #如果想访问的话需要定义一个公有成员,然后返回私有私有字段。
            return self.__age
    
    obj = Foo('alex',18)
    print(obj.name)
    print(obj.__age)    #外部无法直接访问,AttributeError: 'Foo' object has no attribute '__age'
    print(obj.show())   #通过定义的公有方法,可以间接访问

    公有字段私有化

    class Foo:
        __v = '123'   #静态字段
        def __init__(self):
            pass
    
        def show(self):
            return Foo.__v    #前面必须要加Foo
    
    print(Foo.__v)  #静态字段私有之后也是无法通过外部访问的
    obj = Foo()
    print(obj.show())

    继承中的私有字段:

    class F():
        def __init__(self):
            self.ge = '123'
            self.__gene = '234'
    
    class S(F):
        def __init__(self,name):
            self.name = name
            self.__age = 18
            super(S,self).__init__()    #想要使用父亲字段,必须要执行父类Init
    
        def show(self):
            print(self.name)
            print(self.__age)
            print(self.ge)    #必须要在init中同时执行父类,不然此代码报错:AttributeError: 'S' object has no attribute 'ge'
            print(self.__gene)    #继承的时候父亲中的私有字段不继承,如果想访问,要在父类中写一个公有方法间接访问
    
    obj = S('alex')
    obj.show()  #AttributeError: 'S' object has no attribute '_S__gene'

    二、特殊成员

      __init__  类()自动执行

      __call__  对象()  类()()自动执行

    class foo:
    
        def __init__(self):
            pass
    
        def __call__(self, *args, **kwargs):
            print('aaa')
    
    foo()()     #对象加括号自动执行__call__方法

      __int__  int(对象)

    class foo:
        def __init__(self):
            pass
    
        def __int__(self):
            print('1111')
            return 2222
    
    obj = foo()
    print(obj,type(obj))    #<__main__.foo object at 0x000000000065E3C8> <class '__main__.foo'>
    r = int(obj)    #int一个对象,自动执行对象中的__int__方法,并将返回值赋值给int对象
    print(r)    #2222

      __str__  str(对象)

    class foo:
        def __init__(self):
            pass
    
        def __str__(self):
            return 'alex'
    
    obj = foo()
    print(obj,type(obj))    #数据类型为<class '__main__.foo'>
    i = str(obj)    #str一个对象,自动执行对象中的__str__方法
    print(i)    #alex
    class foo:
        def __init__(self,n,a):    #TypeError: object() takes no parameters,如果出现这个错误,一般是init写成了int
            self.name = n
            self.age = a
    
        def __str__(self):
            return '%s - %s'%(self.name,self.age)
    
    obj = foo('alex',18)
    print(obj)  #print(str(obj))   str(obj)运行对象中的__str__方法,并获取其返回值

      __add__

      __del__

    class foo:
        def __init__(self,n,a):
            self.name = n
            self.age = a
    
        def __add__(self, other):   #self = obj1,other = obj2
            return 'xxxoooo'
    
        def __del__(self):
            print('析构方法')   #对象被销毁时,自动执行
    
    obj1 = foo('alex',18)
    obj2 = foo('eric',66)
    r = obj1 + obj2     #两个对象相加时,自动执行第一个对象的__add__方法,并且将第二个对象当做参数传入
    print(r,type(r))

      __dict__  #将对象中封装的所有内容以字典的形式返回

    class foo:
        def __init__(self,n,a):
            self.name = n
            self.age = a
            self.gender = 'male'
    
    obj = foo('alex',18)
    d = obj.__dict__
    print(d)    #{'gender': 'male', 'name': 'alex', 'age': 18}
    
    ret = foo.__dict__    #不仅可以返回对象的,也可以返回类中的成员,包括类的注释
    print(ret)

      __getitem__  #切片(sliceo类型)或者索引

      __setitem__  

      __delitem__

    class foo:
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        def __getitem__(self, item):
            return item+10  #因为这是获取数值,所以有返回值,下面两个没必要有返回值,因为也没地方接收了
    
        def __setitem__(self, key, value):  #key其实就是索引
            print(key,value)
    
        def __delitem__(self, key):
            print(key)
    
    li = foo('alex',18)
    r = li[8]   #自动执行li对象的类中的__getitem__方法,8当作参数传递给item
    print(r)
    
    li[100] = "asdjk"   #这种对象带[]的形式,将自动执行__setitem__方法,key为中括号中值,value为等号后面值
    # 这个方法没必要有返回值,因为这已经是个等式了,有返回值也没地接收了
    
    del li[999]   #这种形式和类中的__delitem__这个方法是对应的,执行此命令,将执行__delitem__方法
    
    #只要前面几个的语法这样写,就对应执行上面的函数,也只是对应关系,具体执行什么操作和表面意思一点关系都没有

      __iter__

    class Foo:
    
        def __iter__(self):
            return iter([11,22,33])
    
    obj = Foo()
    
    for i in obj:
        print(i)
    
    # 如果对象中有__iter__方法,那么该对象就是可迭代对象。
    # 可迭代对象.__iter__返回的是一个迭代器。
    # for循环的时候,如果循环的对象是可迭代对象,那么先执行对象的__iter__,然后针对return的迭代器进行迭代。
    # 如果循环的对象是迭代器,那么就直接进行迭代。
    # 迭代的本质其实就是执行迭代器的next方法

    metaclass元类

    在python中一切皆对象,对象是对象,类也是对象,类是type的对象。

    class Foo:
        def func(self):
            print(123)
    # =============================================================================
    def func(self):
        print("hello world!")
    
    Foo = type("QQQ",(object,),{"func":func})   #声明一个类,类中有一个成员func,成员信息可以用__dict__查看
    
    # 上面两种写法是一样的
    obj = Foo()
    print(Foo.__dict__)
    obj.func()

    异常处理

    try:
        # 代码块,逻辑
        inp = input("请输入:")
        i = int(inp)
    except Exception as e:
        # e是Exception的对象,对象中封装了错误信息
        # 上述代码块出错,自动执行当前代码块的内容
        print(e)
        i = 1

    Exception是大BOSS,包含所有异常,如果想捕捉某一类型的异常可以用具体异常类型。

    try:
        int("22w")
    except IndexError as e:
        print(e)
    except ValueError as e:
        print("value_error:",e)
    except Exception as e:
        print("Exception",e)
    else:
        print("没错的时候执行这块,有错时不执行")
    finally:
        print("无论是否错误都执行")

    反射:

      - getattr

      -setattr

      -hasattr

      -delattr

      通过字符串的形式操作对象中的成员

    class foo:
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        def show(self):
            print('this is the test')
    
    obj = foo('alex',18)
    
    r = getattr(obj,'name')     #有返回值,返回值为对应字段的值
    print(r)    #alex
    r1 = getattr(obj,'show')    #引种形式获取成员,括号后面的参数必须是字符串
    r1()    #执行show方法,得到结果:this is the test,说明getattr不仅可以获得字段,也可以获得方法。
    
    setattr(obj,'score',88)   #没有返回值,返回值为None
    print(obj.score)    #88
    
    r2 = hasattr(obj,'gender')  #有返回值,返回值为布尔值
    print(r2)   #False
    
    delattr(obj,'score')
    print(obj.score)    #AttributeError: 'foo' object has no attribute 'score'
    #类也是对象,所以也可以对类使用上述函数
    class foo:
        country = 'china'
    
        def show(self):
            print('this is the test')
    
    r = getattr(foo,'country')    #同样可以获得里面的字段,因为类是type的对象,从这块可以看出,其实country和self.name一样,都是封装在对象里的内容
    print(r)    #china
    
    r1= hasattr(foo,'show')     #
    print(r1)   #True
    #为什么是ture?由此可以看出getattr获取的是包含在对象内部的内容。
    # 那为什么之前对象可以获得类中的内容?因为对象中有类对象指针,所以类中的成员也是对象中的一部分
    #在python中一切皆对象,所以模块也是对象,对模块也可以操作
    import model1
    
    r1 = getattr(model1,'s')
    print(r1)
    setattr(model1,'tel',88888)     #虽然设置了,可以获取到值,但这些现在只是存在内存中,并未存在文件中
    print(getattr(model1,'tel'))
    
    r2 = getattr(model1,'func')     #获取模块中的函数
    r2()
    
    r3 = getattr(model1,'cls')      #获取模块中的类
    obj = r3('alex',18)     #创建对象
    print(obj.name)     #获取类中的name字段

    反射小练习:仿WEB业面点击获得相应信息

    class foo:
        def f1(self):
            return '首页'
        def f2(self):
            return '新闻'
        def f3(self):
            return '精华'
    
    inp = input('please input your URL>>>:')
    obj = foo()
    #因为方法中需要有self,所以要创建对象,如果不想创建对象,有两种方法,一是用静态方法,这样就不用传self了,另外一个是引入模块,在定义函数,这样也不用传参数
    if hasattr(obj,inp):
        func = getattr(obj,inp)    #这里用Foo也可以取到方法,但是执行的时候需要self,解决方法如上
        result = func()
        print(result)
    else:
        print('404')

    单例模式:

    单例,使用同一个实例(对象)

    class foo:
        __v = None    #这个字段是静态字段,而且是私有字段
        @classmethod    #此处为类方法,这样的话,下面的方法的cls就不用传参了,python会自动传,此处也可以用静态方法,这样下面的参数就需要自己传了
        def get_instance(cls):     #此处的cls为类
            if cls.__v:
                return cls.__v
            else:
                cls.__v = foo()     #给__v赋值,前面必须要加cls,就像给self.name赋值一样
                return cls.__v      #return的值也要是cls.__v
    
    obj = foo.get_instance()    #因为上面用的是类方法,所以这块不用传入参数类,如果为静态方法,那么此处括号内要加foo才行
    obj1 = foo.get_instance()
    obj2 = foo.get_instance()
    
    print(obj)    #<__main__.foo object at 0x00000000009B70B8>
    print(obj1)    #<__main__.foo object at 0x00000000009B70B8>
    print(obj2)     #<__main__.foo object at 0x00000000009B70B8>

    第二次写单例:

    class Foo:
        __v = None
    
        @classmethod    # 这块用类方法好一些,因为在方法里面用到类了,用静态方法也行,只不过就要写成Foo.__v
        def get_instance(cls):
            if not cls.__v:
                cls.__v = Foo()
            return cls.__v
    
    
    obj1 = Foo.get_instance()
    print(obj1)    # <__main__.Foo object at 0x0000000000426C18>
    obj2 = Foo.get_instance()
    print(obj2)    # <__main__.Foo object at 0x0000000000426C18>
  • 相关阅读:
    iOS启动项目(二)引入第三方库
    Swift技巧(九)CGImage To CVPixelBuffer
    Swift技巧(四)设置照片尺寸和格式
    Swift技巧(十) Protocol 的灵活使用
    Alamofire5.0.0 以上报错
    Swift技巧(八)CVPixelBuffer To CGImage
    Swift技巧(十一)重写运算符
    Swift技巧(五)设置圆角的代码
    Swift技巧(七)重识 Array
    Swift技巧(六)设置按钮状态并更改
  • 原文地址:https://www.cnblogs.com/sq5288/p/8510813.html
Copyright © 2020-2023  润新知