zoukankan      html  css  js  c++  java
  • 类和实例

    首先要明白几个概念:

    • 类:class,是抽象的模板;
    • 实例:instance,是基于类的具体的一个例子;
    • 一个类里边,既有“属性”,也有“方法”,属性比如说:年龄、性别、婚姻等等,方法是对特定属性的加工、处理等。
    • 创建实例:bart = Student('Bart Simpson', 59);   bart的数据类型就是“Student类”;
      理解:其实Student这个类,就是一个模板,一种算法,而我们创建的实例对象bart,是bart变量指向的存储单元存储了:
        1.指向Student这个类的地址;
        2..('Bart Simpson', 59)这组信息。
      再次理解:bart.方法 = Student('Bart Simpson', 59).方法;
    • 实例变量:上边的bart就是一个实例变量名,他被链接到class 中的 self上;
    • 隐藏某个属性或字段:__name、__gender等,请参考:廖雪峰“访问限制”
    • 继承、重写→多态:父类有的“方法”子类就会继承,当然也可以在子类中修改该“方法”从而覆盖父类的方法,从而产生某一属性的多种样态,即多态。
    • 对于数据类型的理解:
      •   当我们定义一个class的时候,我们实际上就定义了一种数据类型(可见通过class可以定义很多种数据类型)。我们定义的数据类型和Python自带的数据类型,比如str、list、dict没什么两样:
        a = list() # a是list类型
        b = Animal() # b是Animal类型     可见,每一个具体的class就是一个具体的类型
        c = Dog() # c是Dog类型  且Dog是Animal的子类

        判断一个变量是否是某个类型可以用isinstance()判断:

        >>> isinstance(a, list)
        True
        >>> isinstance(b, Animal)
        True
        >>> isinstance(c, Dog)
        True

        在继承关系中,如果一个实例的数据类型是某个子类,那它的数据类型也可以被看做是父类。但是,反过来就不行

        >>> b = Animal()
        >>> isinstance(b, Dog)
        False

        多态的好处就是,当我们需要传入DogCatTortoise……时,我们只需要接收Animal类型就可以了,因为DogCatTortoise……都是Animal类型,然后,按照Animal类型进行操作即可。由于Animal类型有run()方法,因此,传入的任意类型,只要是Animal类或者子类,就会自动调用实际类型的run()方法,这就是多态的意思:

        对于一个变量,我们只需要知道它是Animal类型,无需确切地知道它的子类型,就可以放心地调用run()方法,而具体调用的run()方法是作用在AnimalDogCat还是Tortoise对象上,由运行时该对象的确切类型决定,这就是多态真正的威力:调用方只管调用,不管细节,而当我们新增一种Animal的子类时,只要确保run()方法编写正确,不用管原来的代码是如何调用的。这就是著名的“开闭”原则:

        对扩展开放:允许新增Animal子类;

        对修改封闭:不需要修改依赖Animal类型的run_twice()等函数。
        继承还可以一级一级地继承下来,就好比从爷爷到爸爸、再到儿子这样的关系。而任何类,最终都可以追溯到根类object,这些继承关系看上去就像一颗倒着的树。比如如下的继承树:


         

    •   

      静态语言 vs 动态语言

      对于静态语言(例如Java)来说,如果需要传入Animal类型,则传入的对象必须是Animal类型或者它的子类(他的子类依然可以看作是Animal类),否则,将无法调用run()方法,因为Java定义函数需要提前声明数据或变量类型,数据类型对不上函数当然无法执行,这就是静态语言的特性。

      对于Python这样的动态语言来说,则不一定需要传入Animal类型(可以是Sun类,可以是Sea类等等)(因为python不需要你声明参数或数据类型,他的适应性很强)。我们只需要保证传入的对象有一个run()方法就可以了:

      class Timer(object):
          def run(self):
              print('Start...')

      这就是动态语言的“鸭子类型”,它并不要求严格的继承体系,一个对象只要“看起来像鸭子,走起路来像鸭子”,那它就可以被看做是鸭子(症结所在:python不限定传入的数据类型)。

      

    补充关于鸭子类型的概念:

    首先要明确python里“鸭子类型”的概念:

    1、看起来像鸭子(举例:一个纸做的手工,参考了鸭子的外形)

    2、走起路来像鸭子(这个手工作品,实现了八字走路,而且内置了扬声器可以嘎嘎叫)

    总结:那么我们可以认为这个纸工艺品,它就是鸭子。

    这就是python的灵活之处,不拘泥于静态类型的严格定义,只要这个类型内部有run()函数,可以看作是目标类型。(再做个补充,其实不管是timer类也好,还是其他什么类也好,只要有run()函数,都可以传入到run_twice里运行,因为他们满足run_twice里需要运行run()函数的需要)

    郑重声明:以上内容是基于 廖雪峰的python教程 整理的,不是原创,不喜勿喷。

         

  • 相关阅读:
    Google app engine python 2.5.4 安装ssl
    Ubuntu 10.04分辨率
    Google Voice 国内用户开通全攻略(图文)
    (linux)查看及修改文件权限以及相关
    InstallAnyWhere使用笔记制作升级补丁时的一些判断
    openoffice 编译依赖关系履历
    匹配连续的任意字词
    BT3 无线密码
    All roads lead to Rome, some smooth, some rough.
    test
  • 原文地址:https://www.cnblogs.com/Jie-Bian/p/11053203.html
Copyright © 2011-2022 走看看