Python 第八讲 面向对象 第一篇

一、面向对象的介绍

计算机编程中最常被提到的就是类和对象,掌握类和对象,有助于使用Python编程语言快速实现复杂的项目。

早期计算机编程语言都是面向过程的,程序即由数据和算法构成,数据可以构成复杂的数据结构,算法也是由上到下的复杂逻辑控制,这是一个将数据与操作算法分离的编程思想。这种程序设计思想的重点都是在代码中各个方法的执行上。C语言中提供了结构体来解决数据复杂度问题,可将一部分数据或属性包装起来,定义出一个复杂的数据结构,如Person结构体(包括姓名、年龄、身高、体重等一系列数据)。

# include <stdio.h>
int main(){
    //定义结构体Person
    struct Person{
        //结构体包含的变量
        char *name;
        int age;
        float height;
        float weight;    
    };
    //通过结构体来定义变量
    struct Person person;
    //操作结构体的成员
    person.name = "小王";
    person.age = 25;
    person.height = 181.2;
    person.weight = 75.0;

    return 0;
}

上面的代码是C语言设计中的结构体,但是这种结构只能支持复杂的数据结构,对于每个数据的处理都要单独提供方法,而且这些方法与整体的结构体并没有关系。后来在PHP、C++、Java、Python等语言中,人们对C语言中的结构体进行了升级,引入了一种新的编程思想——面向对象编程,即程序操作都是在操作对象。对象不仅可以定义复杂的数据结构,也可以定义复杂的算法方程。对象将数据和方法封装起来,开发者只需要负责对象内部的数据和算法,同时对外暴露接口供调用方使用。而调用方也不需要关心实际对象内部的复杂逻辑,只需要调用接口。下面给出了和PHP相同的Person结构示例,与C语言结构体不同的是加入了算法和方法。

class Person:
    def __int__(self,name,age,height,weight):
        self.name = name
        self.age = age
        self.height = height
        self.weight = weight
    
    def print_person(self):
        print("姓名",self.name)
        print("年龄",self.age)
        print("年龄",self.height)
        print("年龄",self.weight)

person = Person('零壹快学',1,1.8,70)
person.print_person()

开发人员发现,这种编程思想更能解决实际问题,程序是对象的集合,并且能够描述具有高度复杂性的各类模型和算法。在现实生活中,人的思考是抽象的,我们会将遇到的事物抽象化,相同或类似的对象可以进一步进行抽象,这时就出现了对象类型——类。先定义类,然后

由类去创建对象,最后由对象去管理整个程序,就像人类思考一样,先抽象,后实例化,最后去执行,面向对象编程的应用逐渐变得广泛起来。

值得注意的是,类的产生是抽象的结果,人们在认识复杂世界时,会将实物或者可以说是对象的一些近似特征抽出来,并且不考虑其中每个个体的细节。面向对象编程就是一种不断抽象数据和抽象方法的过程。

提示

面向对象编程在软件执行效率上并没有绝对优势,主要是一种方便开发者组织管理代码、快速梳理熟悉各个业务领域逻辑的思想方法,它是一种更为贴近现实生活的编程设计方法。

 1、对象

万物皆对象。现实世界中我们所能见到的、能触摸到的所有人和事物都是对象,如人、猫、狗、汽车等。在计算机的世界里面,我们用虚拟的编程代码将现实世界的事物抽象成对象,然后用面向对象编程思想来解决现实世界中的种种难题。对象可以是有形的,也可以是无形的。人们在认识世界的时候,会将对象简单处理分为两个部分——属性和行为。

对象具有属性,它可以称为变量。正如每个人都有姓名、年龄、身高、体重等属性,我们可以用这些数据来描述对象的属性,如下图所示:

 同一类的对象虽然都具有相同的属性,但是其中每个对象是不同的,这表现为每个对象各自的属性值并不同。如下所示:

 对象具有行为,也可以称为方法,就如同每个人都要吃饭、睡觉、运动一样,如下图所示。面向对象编程将完成某个功能代码块定义为方法,方法可以被其他程序调用,也可以被对象自身调用。举个简单的例子,成人可以自己去吃饭,宝宝可以被成人喂饭。

 同样,每个对象的行为也是不相同的,如图所示:

从上面几个示例中我们可以看到,实际的“小王”和“小刘”对象,都具有“人”属性和行为,这里的“人”就是类。

2、类

前面提到,类是相同类似对象的统称。人就是一种类,每个人——即这类对象,都有姓名、年龄、身高、体重等属性,每个人也都有吃饭、睡觉、运动等行为。类是对象的抽象,对象则是类的实例化、具体化,每个对象都包括了类中定义的属性和行为,如下图所示:

 类是对象的属性和行为被进一步封装的模板,不同的类之间的属性和行为都是不同的,如图所示:

 编程语言中,类的属性是以成员属性(也可称成员变量)来定义的,类的行为是以成员方法来定义的,后续章节小编会向大家逐渐介绍。

二、Python与面向对象

Python从设计之初就已经是一门面向对象的语言了,正因为如此,在Python中创建一个类和对象很容易的。本节我们将详细介绍Python面向对象编程。

1、介绍

接下来我们先来简单地了解一些面向对象的基本特征。

  • 类(Class):用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
  • 类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外,通常不作为实例变量使用。
  • 数据成员:类变量或者实例变量,用于处理类及其实例对象的相关数据。
  • 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程就叫做方法的覆盖(Override),也称为方法的重写。
  • 实例变量:定义在方法中的变量,只作用于当前实例的类。
  • 继承:指一个派生类(Derived Class)继承基类(Bass Class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是一个模拟“是一个(is-a)”关系。
  • 实例化:创建一个类的实例,一个类的具体对象。
  • 方法:类中定义的函数。
  • 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法

2、定义语法

类必须在被定义后才能使用,定义一个类也就是定义这一类对象的模板,定义它的属性和方法。Python中提供了class关键字来声明一个类,class中有成员属性和成员方法。Python中类的定义格式如下:

class  [类名]:

        [语法块]

 注意:类名和变量名一样区分大小写。字母相同但是大小写不同的类会被解释器视为两个不同的类。

定义一个类

class EmptyClass:
    pass

在这个例子中我们定义了一个空类,虽然什么都没有做,但是不影响它的存在。 

3、类的使用

在使用之前需要实例化类,类实例化后会成为常见对象。创建对象和创建变量类似,需要先声明对象是哪个类,同时指明变量名称。

class EmptyClass:
    pass

empty = EmptyClass()
print(type(empty))

执行结果如下: 

<class '__main__.EmptyClass'>

这个例子创建一个EmptyClass对象,变量名为“empty” ,同时在内存中为这个对象分配了内存空间。

4、类的构造方法

在创建实例时,很多类可能都需要有特定的初始状态。所以,一个类可以定义一个特殊的方法,叫做构造函数。在Python中,构造函数就是类__init__方法(init前后都有两个连续的短下划线)。

定义和使用构造函数:

class Dog:
    def __init__(self):
        print("汪汪汪!!!")

dog = Dog()

执行结果如下: 

汪汪汪!!!

当一个类定义了__init__方法,类在实例化时会自动调用__init__方法,用于创建新的类实例。在这个例子中,新的实例被创建,同时执行了构造方法,运行了print()函数。注意:构造函数的第一个参数是“self”,不能漏掉。

还有一点需要注意的是,构造方法的返回值必须是“None”。在定义构造方法的时候解释器不会报错,但是在实例化的时候Python会输出错误提示:“TypeError:__init__() should return None”。

5、类的属性

在构造方法中我们可以初始化一些属性,例如:

class Dog:
    def __init__(self,name):
        self.name - name
        selg.age = 3

dog = Dog("旺财")

print(dog.name)
print(dog.age)

 执行结果如下:

旺财
3

注意:属性(或者叫成员变量、类变量)必须要使用“self”加上点的方式赋值,不能直接定义变量。直接定义的变量的生命周期只会在函数内,函数执行完变量就会被销毁。例如:

class Dog:
    def __init__(self,name):
        self.name = name
        age = 3

dog = Dog("旺财")

print(dog.name)
print(dog.age)

 执行这个例子,Python解释器将会提示我们“ AttributeError:'Dog' object has no attribute 'age' ”,即“Dog”对象没有“age”这个属性。其实函数__init__第一个参数“self”指代的就是实例本身,在C++等语言中对应的就是“this”指针,可以理解为对实例的属性进行赋值。Python在调用__init__函数的时候会自动地添加实例作为函数的第一个参数。

6.类中的方法

在类中定义函数我们称为方法。其实在前面的章节中我们已经多次调用过方法了,例如dict字典中的keys方法就是成员方法。自己定义成员方法也很简单,例如:

class Dog:
    def __init__(self,name):
        self.name = name
    def play(self):
        print("汪汪汪!我是",self.name)

dog = Dog("旺财")
dog.play()

执行结果如下:

汪汪汪!我是旺财

7.私有属性

从前面的例子可以看到,在构造函数中定义了属性,实例可以轻松地获取和修改属性的值。但是有时候我们需要限制实例随意修改属性,这时候就要用到私有属性。定义私有属性很简单。只要在定义属性名字的时候使用两条下划线作为开头,Python解释器就认为这个属性是私有的,外部不能随便访问这个属性。例如:

class Dog:
    def __init__(self,name):
        self.__name = name
    def paly(self):
        print("汪汪汪!我是",self.__name)

dog = Dog("旺财")
dog.paly()

# 错误
print(dog.__name)

执行这段代码,Python解释器会出现一段错误提示“ AttributeError: 'Dog' object has no attribute '__name' ”。虽然我们在构造方法中给“__name”赋值了,但是在实例中并不能直接访问到“__name”这个以两个下划线开头的成员变量。在平时的实际项目中,我们可以使用这个特性保护一些不想让用户随便修改的属性。例如:

class Dog:
    def __init__(self,name):
        self.__name = name
        self.__age = None
        print(self.__name,"生成成功")
    def set_age(self,age):
        if not isinstance(age,int):
            print("输入年龄必须是数字!")
        if age <= 0 :
            print("年龄必须大于0!")
            return False
        self.__age = age

    def play(self):
        print("汪汪汪!我今年",self.__age)

dog = Dog("旺财")
dog.set__age("hello")
dog.set__age("-20")
dog.set__age(3)
dog.play()

执行结果如下:

旺财生成成功

输入的年龄必须是数字!

年龄必须大于0!

汪汪汪!我今年  3

 在这个例子中,“__age”是私有属性,实例化过后只能通过set_age方法设置年龄。在set_age方法中我们限制了“age”只能是“int”并且要大于“0”,有效地限制了实例化后数据内容,保证了“__age”是一个有效可用的数据。

8.私有方法

上面我们讲到私有属性,即只能在类内部被操作的属性。同样地,方法也有私有方法,和私有属性一样,私有方法只能在类内部被调用。实例不直接调用。例如:

class Dog:
    def __say(self,name):
        print(name)
    def play(self):
        self.__say("汪汪汪")

dog = Dog()
dog.play()

# 错误
dog.__say()

执行这段代码可以发现play方法可以正常运行,但是__say方法不能直接被实例“dog”调用,Python解释器会提示错误信息“AttributeError: 'Dog' object has no attribute '__say' ”。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值