• Python 类与对象


    # coding:UTF-8
    
    """
    ***此实例是为了尽可能简单地介绍面向对象设计***
    1. 类是什么
    类是一个或多个(有着共同的目标)的方法(类中的函数叫方法)所组成的对象。
    可以把类看成是一个公司,方法就是其中一个个的部门。
    [NOTICE]这里的公司是一个泛指和统称,或者可以看做一个抽象,本身并不能做任何事情
            但是可以创办一个公司(实例化),创办公司时需要注入资金人力物力等(传参数),规定好做事的步骤(语句)。
            当一切准备妥当,按照创办公司标准(类)成立了公司(实例),那么这个公司的每个部门
            就可以运作了,不同的部门(方法)做的事情不同,但又相互关联,都是为了公司(类)共同的目标。
    2. 为什么要用类?
    类的体现了面向对象的三个特性:继承、封装和多态。所以这个问题就是为什么要用面向对象方式,
    也就是继承、封装和多态的优势,比如复用性、解耦性、可读性(语义)等等,关于这一点限于水平我说不了那么多,
    大家可以去查这方面的资料,但是最重要的是,在编程的过程中去理解。
    还是通过上面公司的例子来说明:
    * A公司继承自B公司,那么A就是B的子公司(子类),B是A的父公司(父类,实际中习惯叫母公司)。比如母公司有财务部(X方法).
    * 但是子公司可能财务并不独立,没有财务部门(没有X方法),
    所以财务方面的事情就由母公司(父类)的财务部门(X方法)来处理,也就是默认会继承母公司的财务部门。
    * 子公司也可以对母公司的财务部门进行更改,如增加若干流程并加入自己的人员(继承并改写),或者干脆直接成立一个财务部门
    (重写并覆盖)。
    * 这种继承但是改变了原有类或方法的行为是多态的一种表现形式。
    * [NOTICE]即使是多态的,在子类或子方法中尽量也要保持形式上的一致,比如父公司的财务部中要求加入钱和人力(参数),
    你不能把子公司的财务部定义为接收一些文件书籍,并且财务部们的产出一定都是报表,不能是制造的产品。
    也就是说功能职责要明确且一致。
    * 封装就是将多个步骤动作(这多个步骤是完成某件独立的事情,其功能性完整,可复用性强),组合成一个独立的部门
    (某函数或类等),当某个部门需要做这件事的时候,就去交给(调用)这个独立的部门去做,自己只需要知道或拿到结果。
    封装的水平很大程度上决定了代码的可读性、复用性和扩展性,在面向对象设计时要考虑好封装的功能点。
    
    3. 如何使用类?
    下面的实例简单地介绍了类的一些使用方法。
    """
    
    
    class Parent(object):
    
        def __init__(self):
            # 定义了一个类对象的变量(全局)
            self.foo = 'foo'
    
        def test(self, a, b=True, **kwargs):
            # **kwargs表示接收所有剩下的关键词参数(这里除了b=True以外)
            # 如果这个test方法传入了关键词参数x=10,那么不会报任何错误,会被接收,但并没有被使用
            print 'a is %s' % a
            print 'b is %s' % b
    
        @property
        # property装饰器将方法(的结果)变为了类的属性
        # 如可以使用Parent().bar接收到了bar函数的返回值
        def bar(self):
            return 'bar'
    
    
    class C1(Parent):
    
        def __init__(self):
            # 仅使用super继承了父类的构造函数__init__
            # 继承到了父类__init__方法中所有的语句
            # 也就是继承到了self.foo这个变量
            # C1().foo便有了定义--字符串'foo'
            super(C1, self).__init__()
    
        def test(self, a, b=False, **kwargs):
            # 此函数固定接收两个参数,其中a为普通参数(顺序固定)
            # b为关键词参数,并给定了默认值False,在不传值的情况下使用默认值
            super(C1, self).test(a, b=b, **kwargs)
            # 在父类test执行之后继续执行一句print,并打印了由父类继承来的对象变量
            print self.foo
    
    
    class C2(Parent):
    
        # C2子类没有__init__方法,那么就是完全继承父类,并没有任何改动,
        # 和C1的__init__效果完全一样
    
        def test(self, a, b=True, c=123):
            # 重写父类的方法test,在参数中a和b是必要的参数,但是可以修改关键词参数b的默认值
            # c为子方法中新定义的参数,默认值为123
    
            # assert是一个判断(断言),如果不符合条件,那么会抛出AssertionError异常
            # 作用是保证参数的合法性
            assert type(c) == int
    
            # 显而易见,继承前后都可以增加代码,对父类方法进行修改
            print 'before super'
            super(C2, self).test(a, b=True)
            print 'after super'
    
    
    class C3(Parent):
    
        class C31(object):
            # C31类为C3的内部类,继承自object(所有类的父类)
            # 注意这里也有个变量self,这个self和它的外部类的self不冲突,分别代表它们自己的对象实例
            # 也就是说C31().foo和C3().C31().foo是不同的,并没什么联系
            def __init__(self):
                # 定义了C31自己对象的一个变量foo
                self.foo = 'C31 foo'
    
            def print_foo(self):
                # 同样是self.foo,C31这里的self指的是自己实例化后的对象
                # 也就和C3的self.foo完全不同了
                print self.foo
    
            @staticmethod
            # staticmethod装饰器将类的方法变为静态方法,此方法不能传入self参数
            # 因为静态方法在实例化前(只要类存在内存中时)就可以被调用,传入self肯定会出错
            def test_31():
                print('c31 test')
    
        def test(self, a, b=True, c=10, d=5):
            # 新增加了两个参数c和b,super中的参数只需要传入a和b(因为父类只需要这两个参数)
            super(C3, self).test(a, b)
            print('c3 test')
            print(c * d)
    
    # 大家可以试着改变参数以及调用方法,理解类是如何运作的
    if __name__ == '__main__':
        C1().test('c1')
        print C1().foo
        print '----'
        C2().test('c2')
        print '----'
        C3().test('c3', b=False, c=20)
        print '----'
        C3().C31().test_31()
        print '----'
        print C3().foo
        C3().C31().print_foo()
  • 相关阅读:
    LightOJ 1236 Pairs Forming LCM(算数基本定理)
    LightOJ 1197 Help Hanzo(区间素数筛法)
    hdu4291 A Short problem(矩阵快速幂+循环节)
    弗洛伊德判圈法
    poj 1845 Sumdiv (算数基本定理+逆元)
    2018 ACM-ICPC 亚洲青岛区域网络赛 K XOR Clique(异或)
    牛客网暑期ACM多校训练营(第二场)A-run
    最长上升子序列和最长公共子序列
    Olympic Bus
    现代密码学
  • 原文地址:https://www.cnblogs.com/mysterious-killer/p/10155984.html
Copyright © 2020-2023  润新知