Python面向对象程序设计讲座

面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。

面向过程的程序设计把计算机程序视为一系列的命令集合,即一组函数的顺序执行。为了简化程序设计,面向过程把函数继续切分为子函数,即把大块函数通过切割成小块函数来降低系统的复杂度。

而面向对象的程序设计把计算机程序视为一组对象的集合,而每个对象都可以接收其他对象发过来的消息,并处理这些消息,计算机程序的执行就是一系列消息在各个对象之间传递。

在Python中,所有数据类型都可以视为对象,当然也可以自定义对象。自定义的对象数据类型就是面向对象中的类(Class)的概念。

首先简单了解一下何为面向对象编程:

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

【附、面向过程、面向对象编程与函数式编程

过程式程序设计(英语:Procedural programming),又称过程式编程、过程化编程,一种编程典范,有时会被视为是指令式编程的同义语。派生自结构化编程(Structured programming),主要采取过程调用(procedure call)或函数调用(function call)的方式来进行流程控制。流程则由包涵一系列运算步骤的过程(Procedures),例程(routines),子程序(subroutines), 方法(methods),或函数(functions)来控制。在程序运行的任何一个时间点,都可以调用某个特定的程序。任何一个特定的程序,也能被任意一个程序或是它自己本身调用。

面向对象程序设计(英语:Object-oriented programming,缩写:OOP)是种具有对象概念的程序编程典范,同时也是一种程序开发的抽象方针。它可能包含资料、属性、代码与方法。对象则指的是类的实例。它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性、灵活性和扩展性,对象里的程序可以访问及经常修改对象相关连的资料。在面向对象程序编程里,计算机程序会被设计成彼此相关的对象。

面向对象程序设计可以看作一种在程序中包含各种独立而又互相调用的对象的思想,这与传统的思想刚好相反:传统的程序设计主张将程序看作一系列函数的集合,或者直接就是一系列对电脑下达的指令。面向对象程序设计中的每一个对象都应该能够接受数据、处理数据并将数据传达给其它对象,因此它们都可以被看作一个小型的“机器”,即对象。目前已经被证实的是,面向对象程序设计推广了程序的灵活性和可维护性,并且在大型项目设计中广为应用。此外,支持者声称面向对象程序设计要比以往的做法更加便于学习,因为它能够让人们更简单地设计并维护程序,使得程序更加便于分析、设计、理解。反对者在某些领域对此予以否认。

当我们提到面向对象的时候,它不仅指一种程序设计方法。它更多意义上是一种程序开发方式、设计思想。在这一方面,我们必须了解更多关于面向对象系统分析和面向对象设计(Object Oriented Design,简称OOD)方面的知识。许多流行的编程语言是面向对象的,它们的风格就是会由对象来创出实例。

面向对象(Object Oriented)它是一种设计思想。从20世纪60年代提出面向对象的概念到现在,它已经发展成为一种比较成熟的编辑思想。

顺便提及,不要误认为使用了函数就是函数式编程。函数式编程(英语:functional programming)或称函数程序设计、泛函编程,是一种编程范式(programming paradigm),它将电脑运算视为函数运算,并且避免使用程序状态以及易变对象。其中,λ演算(lambda calculus)为该语言最重要的基础,λ演算的函数可以接受函数当作输入(引数)和输出(传出值),主要思想是把运算过程尽量写成一系列嵌套的函数调用。举例来说,现在有这样一个数学表达式:

  (1 + 2) * 3 - 4

传统的过程式编程,可能这样写:

  var a = 1 + 2;

  var b = a * 3;

  var c = b - 4;

函数式编程要求使用函数,我们可以把运算过程定义为不同的函数,然后写成下面这样:

  var result = subtract(multiply(add(1,2), 3), 4);

函数式编程允许把函数本身作为参数传入另一个函数,还允许返回一个函数!函数式编程强调没有"副作用"(side effect),意味着函数要保持独立,所有功能就是返回一个新的值,没有其他行为,尤其是不得修改外部变量的值。

在函数式编程中,函数是第一类对象(first class),指的是函数与其他数据类型一样,处于平等地位,可以赋值给其他变量,也可以作为参数,传入另一个函数,或者作为别的函数的返回值。

 

一些专业术语概念

类(Class): 用来描述具有相同属性(描述数据特性)和方法(定义如何存取、操作这些数据)的对象的集合。它定义了该集合中每个对象所共有的属性和方法。其中的对象被称作类的实例。

☆实例(Instance):也称对象Object)。通过类定义的初始化方法,赋予具体的值,成为一个”有血有肉的实体”。

☆实例化:创建类的实例的过程或操作。

☆实例变量:定义在实例中的变量,只作用于当前实例。

☆类变量:类变量是所有实例公有的变量。类变量定义在类中,但在方法体之外。

☆数据成员:类变量、实例变量、方法、类方法、静态方法和属性等的统称。

☆方法:类中定义的函数。

☆静态方法:不需要实例化就可以由类执行的方法

☆类方法:类方法是将类本身作为对象进行操作的方法。

☆方法重写:如果从父类继承的方法不能满足子类的需求,可以对父类的方法进行改写,这个过程也称覆盖(override)。

☆封装:将内部实现包裹起来,对外透明,提供api接口进行调用的机制

☆继承:即一个派生类(derived class)继承父类(base class)的变量和方法。

☆多态:根据对象类型的不同以不同的方式进行处理。多态意味着可以对不同的对象使用同样的操作,但它们可能会以多种形态呈现出结果。在Python中,任何不知道对象到底是什么类型,但又需要对象做点什么的时候,都会用到多态。方法是多态的,运算符也是多态的。

 

面向对象的三大特性是指:封装、继承和多态。

 

面向过程和面向对象编程的不同之处

下面以一个例子来说明面向过程面向对象在程序设计上的不同之处。

处理学生的成绩情况,为突出重点对问题进行了简化。

先看面向过程编程(也称为结构化程序设计)情况:

可以用一个dict表示表示一个学生的成绩:

std1 = { 'name': 'Michael', 'score': 98 }

std2 = { 'name': 'Bob', 'score': 81 }

def print_score(std):

    print('%s: %s' % (std['name'], std['score']))

 

print_score(std1)

print_score(std2)

 

运行之,参见下图:

Python面向对象程序设计讲座

 

如果采用面向对象的程序设计思想,我们首选思考的不是程序的执行流程,而是Student这种数据类型应该被视为一个对象,这个对象拥有name和score这两个属性(Property)。如果要打印一个学生的成绩,首先必须创建出这个学生对应的对象,然后,给对象发一个print_score消息,让对象自己把自己的数据打印出来。

定义一个类如下

class Student(object):

    def __init__(self, name, score):

        self.name = name

        self.score = score

 

    def print_score(self):

        print('%s: %s' % (self.name, self.score))

 

bart = Student('Michael',98)

lisa = Student('Bob',81)

bart.print_score()

lisa.print_score()

 

运行之,参见下图:

Python面向对象程序设计讲座

 

 

创建类

使用 class 语句来创建一个新类,class 之后为类的名称并以冒号结尾:

class ClassName:

   '类的帮助信息'   #类文档字符串

   class_suite  #类体

 

面向对象最重要的概念就是类(Class)和实例(Instance),在类的内部,使用 def 关键字来定义一个方法,与一般函数定义不同,类方法必须包含参数 self, 且为第一个参数,self 代表的是类的实例。

下面给出一个例子

#类定义

class people:

    #定义基本属性

    name = ''

    age = 0

    #定义私有属性,私有属性在类外部无法直接进行访问

    __weight = 0

    #定义构造方法

    def __init__(self,n,a,w):

        self.name = n

        self.age = a

        self.__weight = w

    def speak(self):

        print("%s 说: 我 %d 岁。" %(self.name,self.age))

 

# 实例化类

p = people('runoob',10,30)

p.speak()

 

运行之,参见下图:

Python面向对象程序设计讲座

【方法是定义在类对象中的函数。方法与函数的区别在于:

定义方法时,方法的第一个形参表示调用该方法的实例对象,第一个形参的名称是self,也可以是其他名称。

调用方法时,系统自动将调用该方法的实例对象作为实参传递给第一个形象,第一个实参会传递给第二个形参,第二个实参会传递给第三个形参,依次类推。】

类实例化后,可以使用其属性和方法,语法:obj.name即对象名.属性名或方法名。

前面的例子的类中有一个名为 __init__() 的特殊方法(构造方法),是类的专有方法之一,该方法在类实例化时会自动调用,注意,__init__方法的第一个参数永远是self,表示创建的实例本身,因此,在__init__方法内部,就可以把各种属性绑定到self,有了__init__方法,在创建实例的时候,就不能传入空的参数了,必须传入与__init__方法匹配的参数,但self不需要传,Python解释器自己会把实例变量传进去。并且,self就指向创建的实例本身,self.__class__ 则指向类。参见下例:

class Complex:

    #定义类的特殊方法,即构造方法

    def __init__(self, realpart, imagpart):

        self.r = realpart

        self.i = imagpart

    #定义类的方法

    def prt(self):

        print("self代表的是类的实例,代表当前对象的地址:",self)

        print("self.__class__指向类:",self.__class__)

 

x = Complex(8.3, 10)   #实例化类

 

print(x.r, x.i)

x.prt()

运行之,参见下图:

Python面向对象程序设计讲座

 

【类的特殊方法:

__init__ : 构造函数,在生成对象时调用

__del__ : 析构函数,释放对象时使用

__repr__ : 打印,转换

__setitem__ : 按照索引赋值

__getitem__: 按照索引获取值

__len__: 获得长度

__cmp__: 比较运算

__call__: 函数调用

__add__: 加运算

__sub__: 减运算

__mul__: 乘运算

__truediv__: 除运算

__mod__: 求余运算

__pow__: 乘方

注意:前后分别有两个下划线!

Python内置类属性

当创建一个类之后,系统就自带了一些属性,叫内置类属性。常见的内置类属性:

__dict__ : 类的属性(包含一个字典,由类的数据属性组成)

__doc__ :类的文档字符串

__name__: 类名

__module__: 类定义所在的模块(类的全名是'__main__.className',如果类位于一个导入模块mymod中,那么className.__module__ 等于 mymod)

__bases__ : 类的所有父类构成元素(包含了一个由所有父类组成的元组)

 

 

 

 

 

 

相关文章:

  • 2021-10-16
  • 2022-12-23
  • 2021-08-23
猜你喜欢
  • 2021-10-20
  • 2021-06-25
  • 2021-11-02
  • 2021-07-02
  • 2022-12-23
  • 2022-12-23
  • 2021-11-07
相关资源
相似解决方案