美文网首页
Python-学习之路-08 OOP -03

Python-学习之路-08 OOP -03

作者: 末世狂人 | 来源:发表于2019-02-17 23:43 被阅读0次

    类的成员描述符(属性)

    • 类的成员描述符是为了在类中对类的成员属性进行相关操作而创建的一种方式
    • 成员描述符的三种操作
      • get:获取属性的操作
      • set:修改或添加属性操作
      • delete:删除属性操作
    • 如果想使用类的成员描述符,大概有三种方法
      • 使用类实现描述器
        • 适合多个类中多个属性共有一个描述符
      • 使用属性修饰符
        • 在当前类中使用,控制一个类中的一个属性
      • 使用property
        • 在当前类中使用,可以控制一个类中多个属性
        • 无论那种修饰符都是为了对成员属性进行控制
    # 使用property 案例
    class Person():
        
        def fget(self):
            return self._name*2
        
        def fset(self,name):
            self._name = name.upper()
            
        def fdel(self):
            self._name = "NoName"
        
        name = property(fget,fset,fdel,"property")
        
    tom = Person()
    tom.name = "tom"
    print(tom.name)
    
    TOMTOM
    

    类的内置属性

    __dict__:以字典的形似现实类的成员组成
    __doc__: 获取类的文档信息
    __name__:获取类的名称,如果在模块中使用,获取模块的名词
    __bases__:获取某个类的所有父亲,以元组的方式显示
    

    类的常用魔术方法

    • 魔术方法就是不需要人为调用,基本是在特定时刻自动触发
    • 统一特征:方法名被前后两个下划线包裹
      • 典型的魔术方法:'init'
      • 'new' : 对象实例化方法,此函数较为特殊,一般情况下不使用
      • 'call' : 对象当函数使用的时候触发
      • 'str' : 对象当字符串使用的时候触发
      • 'repr': 返回字符串
    • 描述符相关
      • 'set'
      • 'get'
      • 'delete'
    • 属性操作相关
      • 'getattr':访问不存在的属性时触发
      • 'setattr': 对成员属性进行设置的时候触发
        • 参数
          • self用来获取当前对象
          • 被设置属性的名称,以字符串形式出现
          • 需要对属性设置的值
        • 作用:对属性设置的时候进行验证或修改
        • 注意:在该方法中不能对属性直接信息赋值操作,否则会出现死循环
    # __call__
    class A():
        def __init__(self):
            print("我被调用了")
        
        def __call__(self):
            print("call.....")
            
    a = A()
    a()
    
    我被调用了
    call.....
    
    # __str__
    class A():
        def __init__(self):
            print("我被调用了")
        
        def __call__(self):
            print("call.....")
        
        def __str__(self):
            return "str调用"
            
    a = A()
    print(a)
    
    我被调用了
    str调用
    
    # __getattr__
    class A():
        name = "NoName"
        age = 19
        def __getattr__(self,name):
            print("没找到啊没找到!!!")
            
    a = A()
    print(a.add)
    
    没找到啊没找到!!!
    None
    
    # __setattr__
    class Person():
        def __init__(self):
            pass
        
        def __setattr__(self,name,value):
            #不能直接对属性进行赋值
            #self.name = value 这个是错误的 会导致死循环
            super().__setattr__(name,value)
            print("对属性{0}的赋值为{1}".format(name,value))
            
    tom = Person()
    tom.name = "tom"
    
    
    对属性name的赋值为tom
    
    • 运算类相关魔术方法(这里不一一举例)
      • 'gt':进行大于判断的时候触发
        • 参数:
          • self:对象本身
          • 另一个对象(只要对比的两个对象都包含需要对比的属性即可,不必是两个相同的对象)
          • 返回值:任意值,但是推荐返回布尔值
    # __gt__
    class Person():
        def __init__(self,name):
            self._name = name
            
        def __gt__(self,obj):
            return self._name >obj._name
        
    class Person1():
        def __init__(self,name,age):
            self._name = name
            
        
    tom = Person("tom")
    jack = Person1("jack",19)
    print(tom > jack)
    
    True
    

    类和对象的三种方法

    • 实例方法
      • 需要实例化对象才能使用方法,使用过程中可能需要借助对象的其他方法完成
    • 静态方法
      • 不需要实例化,通过类直接调用(适用与各种工具类,方便直接调用)
    • 类方法
      • 不需要实例化
    # 类和对象的三种方法
    class Person():
        age = 18
        def __init__(self,name):
            print("my name is {0}".format(name))
            self.name = name
        # 实例方法
        def eat(self):
            #请注意下面的打印信息,<__main__.Person object at 0x7f9f8eb23cc0> 表示当前self是一个实例
            print(self)
            print("{0}正在吃饭!".format(self.name))
        
        #类方法
        #类方法的一个参数一般命名对cls,用于区别与cls
        #
        @classmethod
        def play(cls):
            #请注意下面的打印信息,<class '__main__.Person'>表示当前cls是一个对象,还没有进行实例化,不是一个实例,所以name属性不能用,只能用定义的类属性 age
            print(cls)
            print("TA现在{0}岁了,可以玩这个了!".format(cls.age))
            
        #静态方法
        #不需要用第一个参数表示自身或类 因为自身还没有实例化啊
        @staticmethod
        def sleep():
            #此时就连init都没有被调用所以下面的输出会报错,说name没有被定义
            #print("{0}正在睡觉!".format(name))
            print("sleeping.........")
            
    #静态方法的调用
    Person.sleep()
    #类方法 调用1
    Person.play()
    #类方法 调用2
    p = Person("tom")
    p.play()
    
    #实例方法
    p.eat()
    
    sleeping.........
    <class '__main__.Person'>
    TA现在18岁了,可以玩这个了!
    my name is tom
    <class '__main__.Person'>
    TA现在18岁了,可以玩这个了!
    <__main__.Person object at 0x7f9f8eb2bd30>
    tom正在吃饭!
    
    # 类方法实例
    '''
    假设我有一个学生类和一个班级类,想要实现的功能为:
        执行班级人数增加的操作、获得班级的总人数;
        学生类继承自班级类,每实例化一个学生,班级人数都能增加;
        最后,我想定义一些学生,获得班级中的总人数。
    
    思考:这个问题用类方法做比较合适,为什么?因为我实例化的是学生,
    但是如果我从学生这一个实例中获得班级总人数,在逻辑上显然是不合理的。
    同时,如果想要获得班级总人数,如果生成一个班级的实例也是没有必要的。
    '''
    class ClassTest(object):
        __num = 0
    
        @classmethod
        def addNum(cls):
            cls.__num += 1
    
        @classmethod
        def getNum(cls):
            return cls.__num
    
        # 这里我用到魔术函数__new__,主要是为了在创建实例的时候调用人数累加的函数。
        def __new__(self):
            ClassTest.addNum()
            return super(ClassTest, self).__new__(self)
    
    
    class Student(ClassTest):
        def __init__(self):
            self.name = ''
    
    a = Student()
    b = Student()
    print(ClassTest.getNum())
    
    2
    

    相关文章

      网友评论

          本文标题:Python-学习之路-08 OOP -03

          本文链接:https://www.haomeiwen.com/subject/loqoeqtx.html