day23

1. 类的成员

    class Foo:
            
        # 方法
        def __init__(self,name):
            # 实例变量/字段
            self.name = name     
                
        # 方法
        def func(self):
            pass 
            
        # 属性
        @ property
        def func2(self):
            return ..
    
    # obj,Foo类的对象
    # obj,Foo类的实例
    obj = Foo('闫子哲')
        
成员共分为三类:    
            1. 变量
            2. 方法
            3. 属性
1.1 变量
    变量:
        - 实例变量(字段)
            - 公有实例变量(公有字段)
            - 私有实例变量(私有字段)
        - 类变量(静态字段)
            - 公有类变量(公有静态字段)
            - 私有类变量(私有静态字段)
        
    (1) 字段
        class Foo:
            # 类变量(静态字段)
             conutry = "中国"
        
             def __init__(self, name):
                 # 实例变量/字段
                 self.name = name
        
              def func(self):
                  pass
        
        知识点一:
        # 准则:
            #   对于实例变量(字段)访问时,使用对象访问,即: obj1.name
            #   类变量(静态字段)访问时,使用类方法,即: Foo.country (实在不方便时,才用对象)
        
        obj1 = Foo('西瓜')
        obj2 = Foo('冬瓜')
        print(obj1.name)
        print(Foo.country)  # obj1.conutry
    
        易错点:
        obj1 = Foo('西瓜')
        obj2 = Foo('冬瓜')
        
        # 练习1
        obj1.name = 'alex'
        print(obj1.name)  # alex
        print(obj2.name)  # 冬瓜
        
        # 练习2
        obj1.country = '美国'
        print(obj1.country)  # 美国
        print(obj2.country)  # 中国
        
        # 练习3
        Foo.country = '美国'
        print(obj1.country)  # 美国
        print(obj2.country)  # 美国
        
    (2) 字段成员修饰符
        -----------------------公有实例变量(字段) -----------------------
        # 公有实例变量(字段): 内外部都可以访问
        
        class Foo:
        
            def __init__(self,name):
                self.name = name
                self.age = 123
        
            def func(self):
                print(self.name)
        
        obj = Foo('闫子哲')
        print(obj.name)
        print(obj.age)  # 外部可以访问
        obj.func()  # 内部也可以访问
        
        ---------------------- 私有实例变量(私有字段) -------------------
        # 私有实例变量(私有字段): 内部可以访问,外部不能访问

        class Foo:
        
            def __init__(self, name):
                # 私有实例变量(私有字段)
                self.__name = name
                self.age = 123
        
            def func(self):
                print(self.__name)
        
        obj = Foo('闫子哲')
        print(obj.age)
        # obj.__name  # 无法访问(外部)
        obj.func()  # 间接访问,找一个内部人:func, 让func帮助你执行内部私有__name

        --------------------- 公有类变量(公有静态字段) ---------------
        class Foo:
            country = "中国"
        
            def __init__(self):
                pass
        
            def func(self):
                # 内部调用
                print(self.country)
                print(Foo.country)  # 推荐
        
        # 外部调用
        print(Foo.country)
        
        obj = Foo()
        obj.func()
        
        -------------------- 私有类变量(私有静态字段) ---------------
        class Foo:
            __country = "中国"
        
            def __init__(self):
                pass
        
            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()

可以访问:
    class Base(object):
        __secret = "受贿"
    
        def zt(self):
            print(Base.__secret)
            
    
    class Foo(Base):
    
        def func(self):
            print(self.__secret)
            print(Foo.__secret)
    
    
    obj = Foo()
    obj.zt()
1.2 方法
    (1) 方法
        ------------------------ 实例化方法 -----------------------------
        ############ 没必要写实例化方法 ############
        没有用到对象内部的数据
        class Foo(object):
        
            def __init__(self, name):
                self.name = name
        
            def func(self):
                print("123")
        
        
        obj = Foo("李华")
        obj.func()
        
       ############ 有必要写实例化方法 #############
        需要用到对象内部的数据
        class Foo(object):
        
            def __init__(self, name):
                self.name = name
        
            def func(self):
                print(self.name)
        
        
        obj = Foo("李华")
        obj.func()

        -------------------------- 静态方法 ---------------------------
        class Foo(object):
        
            def __init__(self, name):
                self.name = name
        
            # 实例方法
            def func(self):
                print(self.name)
        
            # 静态方法,如果方法中无需使用对象中封装的值,那么就可以使用静态方法
            @staticmethod
            def display(a1, a2):
                return a1 + a2
        
        
        obj = Foo("李华")
        obj.func()  # 调用实例方法
        
        ret = Foo.display(1, 3)  # 调用静态方法
        print(ret)
        
        # 总结
        #   1. 编写时:
        #       - 方法上方写 @staticmethod
        #       - 方法参数可有可无
        #   2. 调用时:
        #       - 类.方法名()  # 推荐
        #       - 对象.方法名()
        #   3. 什么时候写静态方法?
        #       - 无需调用对象中已封装的值

       -------------------------- 类方法 ------------------------------
        class Foo(object):
        
            def __init__(self, name):
                self.name = name
        
            # 实例方法,self是对象
            def func(self):
                print(self.name)
        
            # 静态方法,如果方法中无需使用对象中封装的值,那么就可以使用静态方法
            @staticmethod
            def display(a1, a2):
                return a1 + a2
        
            # 类方法,cls是类,自动传递了类,无需手动传递
            @classmethod
            def show(cls, x1, x2):
                print(cls, x1, x2)
        
        # 执行类方法
        Foo.show(1, 8)
        
        # 总结
        #   1. 定义时:
        #       - 方法上方写: @classmethod
        #       - 方法的参数: 至少有一个cls参数
        #   2. 执行时:
        #       - 类名.方法名  # 默认会将当前类传递到参数中
        #   3. 什么时候用?
        #       - 如果在方法中会使用到当前类,那么就可以使用类方法

    (2) 方法成员修饰符
        --------------------- 私有的实例方法 ---------------------
        class Foo(object):
        
            def __init__(self):
                pass
        
            def __dispaly(self, arg):
                print('私有方法', arg)
        
            def func(self):
                self.__dispaly(123)
        
        
        obj = Foo()
        # obj.__display  # 外部无法访问
        obj.func()  # 通过内部访问

        ------------------------- 私有的静态方法 -----------------------
        class Foo(object):
        
            def __init__(self):
                pass
        
            @staticmethod
            def __dispaly(arg):
                print('私有方法', arg)
        
            def func(self):
                Foo.__dispaly(123)
        
            @staticmethod
            def get_display():
                Foo.__dispaly(888)
        
        # Foo.__display(123)  报错
        
        obj = Foo()
        obj.func()
        
        Foo.get_display()

       ------------------------- 私有的类方法 --------------------------
        class Foo:
        
            def __init__(self):
                pass
        
            @classmethod
            def __display(cls, a1):
                print("我爱你", a1)
        
            def func(self):
                Foo.__display('大西瓜')
        
            @classmethod
            def get_display(cls):
                Foo.__display('冬瓜')
        
        # Foo.__dispaly('南瓜')  # 报错
        
        obj = Foo()
        obj.func()
        
        Foo.get_display()
    # 面试题: 静态方法 / 类方法和实例方法的区别?
    答:
        # 定义:
            # 静态方法和类方法上面都要加一个东西
                # 静态方法: @staticmethod
                # 类方法: @classmethod
            # 实例方法不用加
        
        # 调用:
            # 静态方法/类方法调用时,通过 类.方法 调用
            # 实例方法调用时,先实例化,再通过 对象.方法 调用
        
        # 应用场景:
            # 如果在方法内部不会用到对象内部的数据, 就可以用静态方法 / 类方法
                # 类方法: 如果你在代码中会用到当前类, 为了简便, 就用类方法
            # 如果需要用对象内部的数据, 才用实例方法
1.3 属性(通过方法改造出来的)
        class Foo(object):
    
        def __init__(self):
            pass
    
        @property
        def start(self):
            return 1
    
        @property
        def end(self):
            return 10
    
    obj = Foo()
    print(obj.start)
    print(obj.end)
    
    # 总结:
    #   1. 编写时
    #       - 方法的上方写: @property
    #       - 方法参数: 只有一个self
    #   2. 调用时: 无需加括号  对象.方法
    #   3. 应用场景: 对于简单的方法,当无需传参且有返回值时,可以使用 @property
练习题:
    """
    有一个列表,里面有900条数据,要求输入页码显示该页的数据,每页显示10条数据
    """

    # 以前的写法
        data_list = []
    
        for i in range(1, 901):
            data_list.append('alex-%s' % i)
    
        while 1:
            # 1. 要查看的页面
            page = int(input('请输入要查看的页码:'))
    
            # 2. 每页显示 10 条
            per_page_num = 10
    
            start = (page-1) * per_page_num
            end = page * per_page_num
    
            page_data_list = data_list[start:end]
            for item in page_data_list:
                print(item)

    # 面向对象的写法: 把处理分页的函数写一个类
                class Pagenation(object):
            """
            处理分页相关的代码
            """
    
            def __init__(self, page, per_page_num=10):
                """
                初始化
                :param page: 当前要查看的页码
                :param per_page_num: 每页默认要显示的数据行数
                """
                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
    
    
        data_list = []
    
        for i in range(1, 901):
            data_list.append('alex-%s' % i)
    
        while 1:
            # 1. 要查看的页面
            page = int(input('请输入要查看的页码:'))
    
            obj = Pagenation(page)
    
            page_data_list = data_list[obj.start:obj.end]
            for item in page_data_list:
                print(item)

    # 把显示数据的功能也归到这个类
        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 1:
            # 1. 要查看的页面
            page = int(input('请输入要查看的页码:'))
            obj = Pagenation(data_list, page)
            obj.show()

2. 嵌套(组合/建模)

# 面向对象:
    """
    创建三个学校且三个学校的设施内容等都是一致.
    """
    
    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.__aslary = salary
            self.school = None
    
    
    t1 = Teacher('李杰', 19, 188888)
    t2 = Teacher('颜涛', 18, 60)
    t3 = Teacher('女神', 16, 900000)
    ############## 老师分配了校区 ##############
    t1.school = obj1
    t2.school = obj1
    t3.school = obj2

   ######################################
    # 查看t1老师,所在的校区名称/地址
    print(t1.school.name)  # 老男孩北京校区
    print(t1.school.address)  # 美丽富饶的沙河
    print(t1.name)  # 李杰
    print(t1.age)  # 19
    t1.school.speech()  # 演讲
    
    # 准则: 字段和方法的归类.
原文地址:https://www.cnblogs.com/kangqi452/p/11573432.html