zoukankan      html  css  js  c++  java
  • 面向对象的进阶(一)

    面向对象进阶(一)

    一、类的成员

      类的成员分为三类 : 变量、方法、属性。

    二、变量

      变量分为:

        1) 实例变量  (字段)

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

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

        2) 类变量   (静态字段)

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

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

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

    # ######示例一(类变量和实例变量)
      class Foo:
          country = "中华人民共和国"  # 类变量(静态字段)
        
          def __init__(self, name):
              self.name = name  # 实例变量(字段)
            
          def func(self):
              pass
      obj1 = Foo("juan")
      obj2 = Foo("sylar")
      print(obj1.name)  # juan
      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("juan")
        # 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()
  • 相关阅读:
    The OpenGL pipeline
    HLS协议实现
    用C++设计一个不能被继承的类
    Ansible@一个高效的配置管理工具--Ansible configure management--翻译(八)
    史上最简单的软件破解——5行脚本代码完美破解99%的过期软件
    oracle11g创建新的用户和改动最大连接数
    【SICP感应】1 工艺和替代模式
    ant利用先进,ant订单具体解释,ant包,ant包装删除编译jar文件
    SqlServer表EXCEL数据复制的另一种方法
    【摘要干】如何执飞前写商业计划?
  • 原文地址:https://www.cnblogs.com/wxj1129549016/p/9554747.html
Copyright © 2011-2022 走看看