• 面向对象进阶一(成员(变量、方法、属性),组合或嵌套)


    一、类的成员

      类的成员共分为三类:变量、方法、属性。下面我们来一一学习。

    二、变量

      变量分为:

        1)实例变量(又称字段)

               a)公有实例变量(公有字段)

               b)私有实例变量(私有字段)

        2)类变量(又称静态字段)

               a)公有类变量(公有静态字段)

               b)私有类变量(私有静态字段)

      分析下面示例,并了解实例变量和类变量:

      # ######示例一(类变量和实例变量)
      class Foo:
          country = "中国"  # 类变量(静态字段)
        
          def __init__(self, name):
              self.name = name  # 实例变量(字段)
            
          def func(self):
              pass
      obj1 = Foo("alex")
      obj2 = Foo("sylar")
      print(obj1.name)  # alex
      print(Foo.country)  # 或print(obj1.name)  结果为:中国

      上述示例一得如下准则:

        实例变量(字段)访问时,使用对象访问,即obj1.name

        类变量(静态字段)访问时,使用类访问,即Foo.country(实在不方便时,才使用对象访问)

        # 易错点--通过类的某个对象改变类变量的值,该类的其他对象不会受影响,通过类改变类变量,该类的所有对象都会跟着改变
        obj1.country = "美国"
        print(obj1.country)  # 美国
        print(obj2.country)  # 中国
    
        Foo.country = "美国"
        print(obj1.country)  # 美国
        print(obj2.country)  # 美国

      问题一:什么时候使用类变量?

        当所有对象中有共同的字段,且要改都改,要删都删时,可以将实例变量(字段)提取到类变量(静态变量)

        # ######示例二(私有实例变量(私有字段))
        class Foo:
            def __init__(self,name):
                # 规则:公有实例变量前加两个下划线(变量成员修饰符)就是私有实例变量
                self.__name = name    # 私有实例变量(私有字段)
                self.age = 123
    
            def func(self):
                print(self.__name)
    
        obj = Foo('alex')
        print(obj.age)  # age是公有实例变量  可以访问  结果为:123
        # obj.__name  # name是私有实例变量  无法直接访问
        obj.func()  # 找一个内部人:func, 让func帮你执行私有 __name  结果为:alex
        # ######示例三(私有类变量(私有静态变量))
        class Foo:
            # 规则:公有类变量前加两个下划线(变量成员修饰符)就是私有类变量
            __country = "中国"   # 私有类变量(私有静态变量)
    
            def func(self):
                # 内部调用
                print(self.__country)
                print(Foo.__country)  # 推荐使用类来使用静态变量
    
        # print(Foo.country)  # 报错  外部无法使用私有类变量
        obj = Foo()
        obj.func()
        # 结果为:
        # 中国
        # 中国
        # ######示例四(验证该类的子类也不能访问该类的私有变量)
        class Base(object):
            __secret = "受贿"
    
        class Foo(Base):
            def func(self):
                print(self.__secret)
                print(Foo.__secret)
            
        obj = Foo()
        obj.func()  
        # 报错  AttributeError: 'Foo' object has no attribute '_Foo__secret'

    三、方法

      方法分为:

        1)实例方法

          a)公有实例方法

          b)私有实例方法

        2)静态方法

          a)公有静态方法

          b)私有静态方法

        3)类方法

          a)公有类方法

          b)私有类方法

      分析下面示例,并了解实例方法、静态方法、类方法:

        # ######示例一(实例方法)
        class Foo(object):
            def __init__(self, name):
                self.name = name
    # 实例方法 def func(self): print(self.name) # 使用了对象中封装的值 obj = Foo('alex') obj.func()
        # ######示例二(静态方法 @staticmethod  参数可有可无
        class Foo(object):
            def __init__(self, name):
                self.name = name
    # 静态方法,如果方法无需使用对象中封装的值,那么就可以使用静态方法 @staticmethod def display(a1,a2): return a1 + a2 print(Foo.display(1,3)) # 4

      静态方法总结:

        1)定义时:方法上方写@staticmethod、方法参数可有可无;

        2)执行时:推荐用 类.方法名(),也可以用对象.方法名(),但是不推荐;

        3)什么时候写静态方法:无需调用对象中封装的值时;

        # ######示例三(类方法 @classmethod  参数至少有一个cls
        class Foo(object):
    # 类方法,自动传递cls,cls就是这个类 @classmethod def show(cls, x1, x2): print(cls, x1, x2) # 执行类方法 Foo.show(1, 8) # <class '__main__.Foo'> 1 8

      类方法总结:

        1)定义时:方法上方写@classmethod、方法至少有一个cls参数;

        2)执行时:类名.方法名()   注意:默认会将当前类传到参数中,也可用 对象名.方法名() 但不推荐;

        3)什么时候写类方法:如果在方法中会使用到当前类,那么就可以使用类方法;

      面试题:静态方法/类方法和实例方法的区别?

             定义时:

          静态方法/类方法:方法上方分别要加@staticmethod/@classmethod;

                    实例方法:方法上方不用加东西;

             调用时:

                    静态方法/类方法:通过 类名.方法名() 调用;

                    实例方法:通过 对象名.方法名() 调用;

             应用场景:

                    静态方法:在方法内部不会用到对象封装的数据时;

          类方法:在方法内部不会用到对象封装的数据,且会用到当前类时;

                    实例方法:在方法内部需要用到对象封装的数据时;

      同变量类似,方法也有私有方法,规则分别是在公有方法名前加两个下划线(方法成员修饰符),如下:

        # ######示例四(私有实例方法、私有静态方法、私有类方法)
        class Foo(object):
            def __init__(self, name):
                self.name = name
    
            def __fun1(self):
                print("私有实例方法",self.name)
    
            @staticmethod
            def __display():
                print('私有静态方法')
    
            @classmethod
            def __func(cls):
                print(cls, "私有类方法")
    
        obj = Foo("alex")
        # obj.__fun1()  # 无法访问
        # Foo.__display()  # obj.__display() # 类和对象都无法访问
        # Foo.__func()  # 无法访问
    私有方法

    四、属性

      属性是通过实例方法改造出来的,属性也分为公有属性和私有属性,看如下有关属性的示例:

        # ######示例一
        class Foo(object):
    @property
    # 属性 def start(self): return 1 @property # 属性 def end(self): return 10 obj = Foo() print(obj.start) # 调用时不用加括号 结果为:1 print(obj.end) # 调用时不用加括号 结果为:10 # 在公有属性方法名前加两个下划线就是私有属性,不再举例

      属性总结:

        1)定义时:方法上方写@property、方法参数只有一个self;

        2)调用时:无需加括号,直接写  对象.方法   即可;

        3)应用场景:对于简单的方法,当无需传参且有返回值时,可以使用@property;

        class Pagenation(object):
            """
            处理分页相关的代码
            """
            def __init__(self, data_list, page, per_page_num = 10):
                """
                初始化
                :param data_list: 所有的数据
                :param page: 当前要查看的页面
                :param per_page_num: 每页默认要显示的数据行数
                """
                self.data_list = data_list
                self.page = page
                self.per_page_num = per_page_num
    
            @property
            def start(self):
                """
                计算索引的起始位置
                :return:
                """
                return (self.page-1) * self.per_page_num
    
            @property
            def end(self):
                """
                计算索引的结束位置
                :return:
                """
                return self.page * self.per_page_num
    
            def show(self):
                """
                打印一页的内容
                :return:
                """
                result = self.data_list[self.start:self.end]
                for row in result:
                    print(row)
    
        data_list = []
        for i in range(1, 901):
            data_list.append('alex-%s' % i)
        while True:
            page = int(input('请输入要查看的页码:'))
            obj = Pagenation(data_list,page)
            obj.show()
    属性应用示例-分页

    五、组合或嵌套(建模)

      这里的嵌套不是专业的词汇,是我们用大白话解释的。面向对象中的嵌套其实就是对象的相互嵌套,看如下一个对象嵌套的示例:

      class School(object):  # 定义一个学校类
          def __init__(self, name, address):
              self.name = name
              self.address = address
          def speech(self):
              print('讲课')
      # 创建三个学校对象
      obj1 = School('北京校区', '昌平区')
      obj2 = School('上海校区', '浦东新区')
      obj3 = School('深圳校区', '南山区')
      class Teacher(object):  # 定义一个老师类
          def __init__(self, name, age, salary):
              self.name = name
              self.age = age
              self.__salary = salary
              self.school = None
      # 创建三个老师对象
      t1 = Teacher('李杰', 19, 188888)
      t2 = Teacher('sylar', 18, 60)
      t3 = Teacher('女神',16, 900000)
      # 给老师分配校区
      t1.school = obj1  # t1对象的school变量是一个obj1对象
      t2.school = obj1
      t3.school = obj2
      # 查看t1老师,所在的校区名称/地址
      print(t1.school.name)
      print(t1.school.address)
      print(t1.name)
      print(t1.age)
      t1.school.speech()
  • 相关阅读:
    hilla 项目基本结构
    dremio 的配置管理简单说明
    基于jackson 多态数据类型处理rest api 业务
    dremio SourceMetadataManager 服务简单说明
    hilla 框架的组成
    dremio jdbc arp 扩展包装以及加载处理
    krakend 2.0.0 发布了
    lightdash 运行简单说明
    dremio 源码分析学习的几个方便工具
    dremio 社区版本scheduler 任务池加载处理机制简单说明
  • 原文地址:https://www.cnblogs.com/li-li/p/9548275.html
Copyright © 2020-2023  润新知