# 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()