美文网首页
Python基础之面向对象编程(二)

Python基础之面向对象编程(二)

作者: Coralline_xss | 来源:发表于2017-12-08 13:53 被阅读1次

    本篇文章主要介绍面向对象编程。

    面向对象编程

    几个定义

    • 面向过程编程:围绕函数,编写能处理数据的代码块的编程方式。
    • 类、对象:面向对象编程的两个主要方面。一个类(Class)能创建一种新的类型;对象(Object)是类的实例。可这样类比:你可拥有类型 int 的变量,也即,存储整数的变量是 int类 的对象实例。
    • 字段、方法和属性:从属于对象或类的变量叫字段(Field);对象调用从属于类的函数实现某些功能,这些函数叫类的方法(Method);字段和方法统称为累的属性(Attribute)。

    Tips: 不同于静态语言,Python 中即使是整数也会被视为对象(int类的对象),同 Java 中装箱与拆箱概念颇为相似。

    类和对象

    最简单的类结构如下所示:

    class Student(object):
        pass # 一个空的代码块
    
    # 创建类对象实例
    student = Student()
    print(student)  
    # 打印:<__main__.Student object at 0x101985f28>   
    

    *Tips: *

    • Python 中所有类均继承自 object;
    • Python 打印对象,默认可查看对象地址。Python 会在它找到的任何空间来存储对象。
    类属性和实例属性

    方法(Method)

    Python 对比于 Java 类方法属性,有两个特殊点:

    • 类中定义的所有方法,第一个参数必须是 self;相当于 Java 中的 this 引用;
    • _init_() 方法:在类的对象被实例化时立即运行;相当于 Java 中的构造方法。
      Tips: Python中不存在方法的重载,方法的重载是对同一个方法使用可变参数来实现,这在后面函数参数这块会提到。

    示例代码如下:

    class Student(object):
        count = 0  # 类变量
    
        def __init__(self, name):
            self.name = name  # 实例变量
        
        def say_hi(self):
            print(r'Hello, I'm', self.name)
            
    student = Student('Coral')  
    student.say_hi()  
    # 打印:Hello, I'm Coral
    

    字段(Field)

    Python 中字段有两种类型——类变量与对象变量,对比上述示例代码,两者的区别点如下图所示:


    类变量和实例变量区别.png

    因为 Python 是动态语言,可以给类创建的实例动态绑定属性,那么如何给 实例 绑定属性?如何给 类 绑定属性呢?

    1)给实例绑定属性

    • 通过在 _init_ 方法中给 self 绑定属性,这种属性所有对象实例均可访问;
    • 直接给实例绑定,这种属性只适用于该实例,其他实例不能访问该属性。如:
    student = Student('Coral')
    # grade是给实例动态绑定的属性,name是通过 self绑定的属性
    student.grade = 90 
    print('{} grade = {} '.format(student.name, student.grade)) 
    
    student2 = Student('Jane')
    print(student2.grade)
    # 这句会抛出:AttributeError: 'Student' object has no attribute 'grade'
    

    2)给类绑定属性
    要让同一个字段属性对所有实例均适用,除了 self 绑定,还可以适用 类属性。

    • 类属性,直接在 class 中定义属性,归整个 Student 类所有,如 count 字段。

    Tips: 当 实例属性 和 类属性 同名时,实例属性 优于 类属性,也即,实力属性会覆盖类属性,所以在项目中要避免使用这种同名变量。

    访问限制

    Java 中有四种访问修饰符,Python 中并没有指定具体的访问修饰符,仅是按照一种约定的写法来,如下图所示:


    访问限制.png
    获取对象信息

    在 Java 中通常会判断一个对象是什么类型,用 instanceOf 来判断,Python 中也有判断对象类型的方法,还可以获取对象拥有的属性和方法,这些都是 Python 内置的方法。常见的如下图所示:


    获取对象信息方法.png

    这里重点说下 isinstance() 方法,示例如下:

    a = list() # a 是 list 类型
    b = Animal() # b 是 Animal 类型
    c = Dog()  # c 是 Dog 类型
    
    # 1.判断一个变量是否是某个类型可以用 isinstance() 判断:
    print('a is list:', isinstance(a, list))     # True
    print('b is Animal:', isinstance(b, Animal)) # True
    print('c is Dog:', isinstance(c, Dog))       # True
    print('c is Animal:', isinstance(c, Animal)) # True
    
    # 2. 能用 type() 判断的基本类型也可以用 isinstance() 判断:
    print(isinstance('a', str))    # True
    print(isinstance(123, int))    # True
    print(isinstance(b'a', bytes)) # True
    
    # 3. 另外,isinstance() 还可以判断一个变量是否是某些类型中的一种:
    # 判断变量是否是 list 或 tuple.
    def is_list_or_tuple(x):
        return isinstance(x, (list, tuple))
    

    Tips: 区别于 type,对于 class 继承关系,不便使用 type();要判断 class 类型,使用 isinstance() 函数。因为 type() 只能返回对象本身的类型,比如 type(dog) != type(animal), 但是 isinstance(dog, Dog) = isinstance(dog, Animal)。

    继承和多态

    Python 中允许多继承,没有接口实现的概念。继承和多态总结点如下:


    继承和多态.png

    Python 中没有方法的重载,但是存在方法的覆盖,子类可以覆盖父类方法,也适用于运行时绑定传入的实例。

    关于继承的几个问题
    1. 子类 能否继承 父类绑定的 属性?(每个类通过 self 或者 给实例动态绑定的 属性都是该类实例 独立拥有,跟子类没有任何关联?)
      A: 子类不能继承 父类中通过 self或者 动态绑定的属性;
    2. 子类 是否只能继承 父类绑定的 类属性?
      A:子类能继承 父类中的 类属性,在操作该类属性时,使用 ChildClass.property 访问该类属性;
    3. 子类可以继承 父类的所有方法?
      A:Python 中方法没有 访问限制符修饰;
    4. 每个类通过 self 或者 给实例动态绑定的 属性都是该类实例 独立拥有,跟子类没有任何关联?
      A:是。
    5. 子类和父类有同名的 属性,优先使用哪个?(避免这种情况,直接继承使用父类的属性)
      A:子类优先,但最好不要让子类属性和父类属性同名 。
    6. 子类能否继承父类中 __xxx 隐藏属性?
      A:这个可以看做是每个类通过 self 绑定的属性均属于本类所有,父类中通过 self 绑定的属性不管是否是隐藏属性,子类直接访问就会抛出:AttributeError: 'Dog' object has no attribute '_BaseClass__name' .

    相关文章

      网友评论

          本文标题:Python基础之面向对象编程(二)

          本文链接:https://www.haomeiwen.com/subject/vuyrixtx.html