面向对象编程基础

在计算机科学中,对象(object)是一个存储器地址(其中拥有值),这个地址可能有标识符指向此处。对象可以是一个变量,一个数据结构,或是一个函数。是面向对象中的术语,既表示客观世界问题空间中的某个具体的事物,又表示软件系统解空间中的基本元素。

在软件系统中,对象具有唯一的标识符,对象包括属性和方法,属性就是需要记忆的信息,方法就是对象能够提供的服务。对象(Object)指的是类(Class)的实例。它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性、灵活性和扩展性。

面向对象思想有着三大要素:封装、继承、多态。

把一组数据结构和处理他们的方法组成对象(Object),把相同行为的对象归纳为类(class),通过类的封装隐藏内部细节,通过 继承实现类的特化和泛化,通过多态实现基于对象类型的动态分派。

类和对象

简单的说,类是对象的模板,而对象是类的实例,类是抽象的,而对象是具体的东西。在面向对象编程中,一切皆为对象,对象都有属性和行为,每个对象都是独一无二的,而且对象一定属于某个类(型)。当我们把一大堆拥有共同特征的对象的静态特征(属性)和动态特征(行为方法)都抽取出来后,就可以定义一个叫做“类”的东西。

在Python中可以使用class关键字定义类,然后在类中通过函数来定义方法,这样就可以将对象的动态特征描述出来。代码如下:

# 定义一个类

class Student(object):

     # 类的初始化方法,对类实例化时自动调用该方法

    def __init__(self,name,age):
    # 成员变量,即属性
        self.name = name
        self.age = age

    def student(self,course):
        print(f"{self.name}在学习{course}")


    # 标识符的名字可以用全小写多个单词用下划线连接
     # 也可以用驼峰法进行连接
    def watchMovie(self,movie_name):
        print(f"学生{self.name}可以看{movie_name}的电影")
        print(f"年龄{self.age}可以看{movie_name}的电影")


if __name__ == '__main__':

    # 对类进行实例化,就相当于函数的调用
    # 初始化方法中包含了参数,所以需要进行传参

    student1 = Student("lisi",18)

    # 通过实例化的类去调用方法,并传参
    student1.student("math")
    
    student1.watchMovie("kongbupian")

私有属性与方法

类中的成员变量称之为属性,成员函数称之为方法。通常我们会将对象的属性设置为私有的或受保护的,不允许外界访问,就像我们人一样,不想给别人看我们的年龄。如果希望我们的属性是私有的,在给属性命名时可以用两个下划线作为开头。代码如下:

class Animal(object):
    def __init__(self,name,color):
        self.name = name

        # 定义一个私有属性
        # 此属性只能在本类才能访问
        self.__color = color

    # 定义一个私有方法,只能在内部使用
    def __dog(self):
        print(f"我是{self.name},我的颜色是{self.__color}")
    def cat(self):
        print(f"{self.name}")


def duck(name):
    print(f"我是{name}")
    animal = Animal("li","black")
    animal.cat()

    # # 在类的外面进行调用时会报错
    # animal.__color      #'Animal' object has no attribute '__color'
    # animal.__dog()      #'Animal' object has no attribute '__dog'

    # 可以通过_Animal__属性名或者方法名进行访问
    animal._Animal__dog()
    print(f"{animal._Animal__color}")

if __name__ == '__main__':
    duck("duck")


我们并不建议将属性设置为私有的,因为这回导致子类无法访问,所以大多数Python程序员会遵循一种命名惯例就是让属性名以单下划线开头来表示属性是受保护的。

封装

在上面其实我们已经展示了封装,封装就是隐藏一切可以隐藏的实现细节,只向外界暴露(提供)简单的编程接口。我们在类中定义的方法其实就是把数据和对数据的操作进行封装起来,在我们创建了对象之后,只需要给对象发送一个消息(调用方法或者属性)就可以执行方法或属性的功能,也就是说我们只需要知道方法的名字和传入的参数,而不需要知道方法内部的实现细节。

继承

在已有类的基础上创建新类,这其中的一种做法就是让一个类从另一个类那里将属性和方法直接继承下来,从而减少重复代码的编写。提供继承信息的我们称之为父类,也称基类;得到继承信息的我们称为子类,也叫派生类或衍生类。子类除了继承父类提供的属性和方法,还可以自定义属性和方法,所以子类比父类拥有更多的能力。具体代码如下:

class Person(object):
    def __init__(self,name):

        self.name = name
    def name1(self):
        print("我是父类中的方法")


# 此时我们的Student类继承了Person类

class Student(Person):
    def age(self):
        print("我是子类中的方法")

# 实例化类
s1 = Student("lisi")

# 访问自己的方法
s1.age()

# 子类继承了父类,所以可以访问父类的方法
s1.name1()

# 也可以访问属性
print(f"我是父类的属性{s1.name}")


练习

from time import sleep

class Clock(object):

    def __init__(self, hour=0, minute=0, second=0):

        self._hour = hour
        self._minute = minute
        self._second = second

    def run(self):
        """走字"""
        self._second += 1
        if self._second == 60:
            self._second = 0
            self._minute += 1
            if self._minute == 60:
                self._minute = 0
                self._hour += 1
                if self._hour == 24:
                    self._hour = 0

    def show(self):
        """显示时间"""
        return '%02d:%02d:%02d' % \
               (self._hour, self._minute, self._second)


def main():
    clock = Clock(23, 59, 58)
    while True:
        print(clock.show())
        sleep(1)
        clock.run()


if __name__ == '__main__':
    main()
04-18 17:33