Python学习中阶:面向对象程序设计

*************************************************************************************************************

终于到了面向对象的编程这部分,看完了基本数据类型、函数以及文件的操作。终于开始 面!向!对!象!的!编!程!啦!、

本部分主要涉及四部分,面向对象的编程、异常处理、进程和线程。重点主要是面向对象的编程、进程和线程

此外,本部分内容是以《Python程序设计:任务式驱动教程》@作者:郑凯梅 这本书为基础对Python相关知识进行介绍,结合网上资料以及相关例程对Python相关知识进行解读和总结,帮助Python学习者步入面向高级的应用

*************************************************************************************************************

#7面向对象编程

python的核心是面向对象,因此Python支持所有面向对象的特征,如封装、继承、多态等。封装的要点是对外隐藏实现的细节,使用类来实现。继承的目的是扩展类,在父类的基础上添加新的属性和方法而生成新类。多态的核心是不同类的对象调用相同的方法时,会根据类型的不同而表现出不同的行为。

7.1面向对象概述

程序设计技术分为面向过程程序设计和面向对象程序设计。

       面向过程程序设计方法的特征是以算法(功能)为中心,程序 = 算法+数据结构,算法和数据结构之间的耦合度很高。因此,当数据结构发生变化后,所有与数据结构相关的语句和函数都需要进行修改。

       面向对象程序设计(Object Oriented Programming,OOP)是将软件结构建立在对象上,而不是功能上,通过对象来逼真地模拟现实世界中的事物,使计算机求解问题更类似于人类的思维活动。面向对象使用类封装程序和数据,对象是类的实例。以对象作为程序的基本单元,提高了软件的重用性、灵活性和扩展性。

       面向对象的特性具有三大基本特征:封装、继承和多态

       封装是面向对象的特征之一,主要包括对象和类。

       类是具有相同属性和行为的一组对象的集合。在面向对象的编程语言中,类是一个独立的程序单元。由类名来标识,包括属性定义和行为定义两个部分。

      对象是系统中用来用来描述客观事物的一个实体。它是一组属性和有权对这些属性进行操作的一组行为的封装体。    

      类与对象的关系就如同模具与铸件的关系,类的实例化结果就是对象,对一类对象的抽象就是类。类描述了一组有相同特性(属性)和相同行为(方法)的对象。

      继承是在现有类的基础上通过添加属性和方法来对现有类进行扩展。通过继承创建的新类称为子类或者派生类,被继承的类称为基类、父类或超类。继承的过程,就是从一般到特殊的过程。

       多态是指相同的操作、方法或者过程可作用于多种类型的对象上并获得不同的结果。

7.2类和对象

在Python中,一切皆为对象。例如:所有字符串是str类的实例,所有列表是list类的实例。尽管每个字符串的实际内容不同,但它们的操作方法都是相同的。前面所学的str、int、float、list、tuple、dictionary、set数据类型,都是定义的内建类

类由属性和方法组成。属性是描述对象特征的集合,方法使对象的行为。

7.2.1类的定义和对象的创建

Python中定义类的语法格式如下:
class 类名:
    [类变量]
    [def __init__(self,paramers):]
    [def 函数名(self,....)]
注意:
(1)直接定义在类体中的变量叫做类变量,是所有对象共享的变量,也称为静态变量或静态数据,
    与所属的类的对象绑定,不依赖于实例对象。
(2)在类的方法中定义的变量叫做实例变量。类的方法的定义和普通函数的定义类似,
    但方法必须以self作为第一个参数。方法调用时,可以不传递self参数。
(3)当创建对象时,self参数指向该对象。这样,当方法调用时,
    会通过self参数得知哪个对象调用了该方法。
(4)实例方法必须绑定到一个实例对象上才能被调用。
(5)当一个类定义完成后,就产生了一个类对象(与类名相同)
(6)实例对象通过类名后跟圆括号来实例化
(7)Python中,对象支持两种操作:引用和实例化。引用是通过类对象来调用类中的属性或者方法;
    实例化是生成对象的实例,通过实例对象来引用类中的属性或者方法。

实例如下:

再举一例,见下:

class fruit:
    totalnum = 0
    def __init__(self,type,ori_num):
        self.type =  type
        self.orinum =ori_num
    def fruitnumbers(self,add_num):
        self.addnum = add_num
        self.totalnum = self.orinum + self.addnum
        print('total numbers is {}'.format(self.totalnum))
    def fruitprint(self):
        print('fruits are {}s' .format(self.type))
        print('there are {0} {1}s' .format(self.totalnum,self.type))

apple = fruit('apple',10)
apple.fruitnumbers(5)
apple.fruitprint()
class fruit:
    totalnum = 0       #类变量,
    def __init__(self,type,ori_num):		#构造方法
        self.type =  type	#实例变量初始化,将接口变量type赋值给实例变量self.type
        self.orinum =ori_num	#同上
    def fruitnumbers(self,add_num):
        self.addnum = add_num#同上
        fruit.totalnum = self.orinum + self.addnum #fruit.totalnum是上面的类变量totalnum
        print('total numbers is {}'.format(fruit.totalnum))
    def fruitprint(self):
        print('fruits are {}s' .format(self.type)) #实例变量可以直接使用
        print('there are {0} {1}s' .format(fruit.totalnum,self.type))#对类变量和实例变量进行

apple = fruit('apple',10)
apple.fruitnumbers(5)
apple.fruitprint()
print(apple.totalnum)

 

值得注意的是: 类中的方法及__init__都要以self作为默认起始参数,在实例方法中,都要以先对变量进行赋值

7.2.2实例变量及封装

实例化之后,每个实例单独拥有的变量叫做实例变量。实例变量是与某个类的实例相关联的数据值,这些值独立于其他实例或者类。当一个实例被释放后,这些变量同时被释放。

在Python中,实例变量的定义如下:
self.变量名
只要以self定义的变量都是实例变量。该变量可以定义在任何实例方法内。
实例变量的初始化方法最好通过定义__init__()或者__new__()构造方法完成。
该方法在定义对象的时候自动调用,如果同时调用这两个方法,则优先使用__new__()方法来完成实例化。
调用实例变量有如下两种方式。
(1)在类外通过对象直接调用。
(2)在类内通过self间接调用。

Python中的封装,其实是使用构造方法将内容封装到对象中,然后通过对象直接或者通过self间接获取被封装的内容
与其他语言不同的是,Python没有提供private、public这样的访问控制符。

如果要实现真正的封装,让实例变量或者方法称为私有的,需要在变量名和方法名前加上双下划线,如_valueName或者__functionName.

7.2.3方法

在Python类中定义的方法通常有3种:实例方法、类方法及静态方法。以下是这三种方法的定义和调用方式。

1、实例方法

实例方法一般都以self作为第一个参数,必须和具体的对象实例绑定才能访问,即必须有对象调用。执行时,自动将调用该方法的对象赋值给self

2、类方法

类方法必须以cls作为第一个参数。cls表示类本身,定义时使用@classMethod装饰器。可以通过类名或实例对象名来调用。执行类方法时,可以通过类名或者实例对象名来调用。执行类方法时,自动将调用该方法的类赋值给cls

3、静态方法

静态方法不需要默认的任何参数,跟一般的普通方法类似,但方法内不能使用任何的实例变量,定义时使用@staticsmethod装饰器。静态方法可以使用类名或者实例对象名来调用

7.2.4属性方法

Python中的属性是普通方法的变种,即把一个方法变成一个静态属性,这样,方法在调用时就不用加小括号了。

属性方法定义有下述两种方式。

(1)装饰器方式:定义方法时,使用@property

(2)静态属性方式:在类中定义值为property对象的静态属性

属性方法格式为:

property(方法名1,方法名2,方法名3,'描述信息')

7.2.5类中的其他内置方法和属性

Python中还提供一些内置方法来完成特定的功能,如表7-1所示。

表7-1 Python内置方法

方法名或属性名                                                                               功能描述

__init__(self,...)                                                                     构造方法。初始化对象,在创建新对象时调用

__del__(self)                                                                        析构方法。释放对象,在对象被删除之前调用

__new__(cls,**args,**kwd)                                                   初始化实例

省略一些表格内容

7.3继承

面向对象编程的优点之一是代码重用,它通过继承机制来实现,继承允许在基类(父类)的基础上,新增特有的方法和属性;也可以把父类的某些方法覆盖重写,以适应子类(派生类)的要求。并且子类可以访问父类的属性和方法,提高代码的扩展性。

7.3.1使用继承

#Python中定义类的继承的语法格式如下:
class 类名(父类名):
    [类变量]
    [def_init__(self,paramers):]
    [super.__init__(paramers)]/[父类名.__init__(paramers)]
    [def 函数名(self, ...)]

#例程如下
class Person:
    def __init__ (self, name, age):
        self.name = name
        self.age = age
    
    def birthday(self):
        self.age = self.age + 1
        print("%d" %self.age)

class Parent(Person):
    def __init__(self,age, name):
        Person.__init__(self,name, age)
        self.age = age
        self.name = name
        
p = Parent(17,"Tom")
p.birthday()

注意:

(1)在类定义中,可以在类名后的圆括号中指定要继承的父类。如果有多个父类,父类之间用逗号隔开,称为多继承。

(2)基类的构造(__init__())方法不会被自动调用,需要在子类的构造方法中显示调用。调用方式为:父类名.__init__(self,参数表);也可以用super().__init__(self,参数表)方式来调用父类构造方法。

(3)在继承关系中,子类继承了父类左右的公有属性和方法,可以在子类中通过父类名来调用。而对于父类中私有的属性和方法,子类不能继承,因此在子类中是无法访问的。

(4)在子类中调用父类的方法,需要父类名.方法名(self,参数表)的方式来调用,并且要传递self参数。调用本类的实例方法时,不需要加self参数。

(5)如果父类中的某些方法的功能不能满足需求时,可以在子类重写父类中的这些方法。要求方法完全相同。

(6)对于多重继承,如果子类中没有重新定义的构造方法,会自动调用第一个父类中的构造方法。另外,若多个父类中有同名的方法,由子类的实例化对象来调用同名方法时,调用的是第一个父类中的方法。

(7)Pyhton总是在本类中查找调用的方法。如果找不到,才到基类中去查找。

7.3.2抽象基类

在面向对象中,抽象类是对一类事物特征和行为的抽象。抽象类由抽象方法组成,接口是特殊的抽象类。接口没有数据成员,而是一组未实现的方法的集合。

Python提供了内置抽象基类模块abc(abstract base class)来模拟现实抽象类。

抽象基类模块定义了一个元类(ABCMeta)、定义抽象方法的装饰器@abstractproperty。

1、抽象类的定义

抽象类定义的格式如下:

from abc import ABCMeta,abstractmethod,abstractproperty
class 类名:
__metaclass__ = ABCMeta        #这句话不可缺,表示通过ABCMeta元类来创建一个抽象类
[@abstractmethod]            #定义抽象方法,无实现语句
def 抽象方法名(self, 其他参数):
    [return]
[@abstractproperty]          #定义抽象属性,无实现语句
def 抽象方法名(self):
    [return]
[其他非抽象方法定义]

7.4运算符的重载

在Python语言中提供了类似于C++的运算符重载功能,使用一些提前内置的内置的方法名来表示,比如与加法对应的方法是__add__(),与减法对应的是__sub__()。

#8异常处理

为处理Python程序在运行中出现的异常和错误,Python提供了异常处理机制和断言机制。

异常是一个事件,会在程序执行过程中发生,并影响程序的正常执行。一般情况下,在Python无法正常处理程序时就会发生一个异常。该异常是一个表示某种错误的Python对象。当Python发生某种异常时,需要将其捕获并处理,否则程序将终止运行。

8.1Python中的异常

异常是指程序中的例外,是违例情况。异常机制是指程序出现错误后,程序的处理方法。当出现错误后,程序的之行流程将发生改变,程序转移到异常处理代码

8.2常用异常处理

1、try/except语句

Python提供了try/except语句来捕获异常。try/except语句可以检测出try语句块中的错误,并让except语句捕获这些异常信息并进行处理。如果不捕获这些异常,程序将被非正常约束。

异常捕获try-except-else的语法格式如下:
try:
    <语句>                         #可能发生异常的代码
except<异常名字>:                 #捕获发生的异常,可跟多个异常名字,并用逗号隔开
    <语句>
except<异常名字> as <异常参数>:    #捕获发生的异常,并获得附加信息
    <语句>
except:              #捕获未列出名字的异常
    <语句>            #处理异常
else:
    <语句>            #如果没有异常发生,则执行语句块

#例程如下:
try:
    with open("/home/pi/Code/Python/exercises/test_CSV.txt",'a',newline="") as f1:
        f1.write("\n")
        f1.write("异常处理与检测")
except IOError:
    print("Error:没有找到文件或读取文件失败")
else:
    print("内容写入成功!")
    f1.close()
    

2、try-finally

try-finally 子句用于如下场合:不管捕捉到的是什么错误,无论错误是不是发生,这些代码“必须运行”。finally子句通常用于关闭异常而不能释放的系统,如关闭文件、释放锁、返还数据库连接等。

try:
    with open("/home/pi/Code/Python/exercises/test_CSV.txt",'a',newline="") as f1:
        f1.write("\n")
        f1.write("This is a test!")
finally:
    f1.close()
    print('清理....关闭文档')

3、raise抛出异常

Python使用raise来抛出一个异常,基本上与Java中的throws关键字相同

raise[Exception[,args[,traceback]]]
try:
    s = None
    if s is None:
        print('s 是空对象')
        #如果引发NameError异常,后面的代码将不能执行
        raise EOFError
    print(len(s))
except TypeError:
    print('空滴没有长度')

4、assert语句

assert语句用于检测某个条件表达式是否为真。assert语句又称断言语句。

assert “表达式” [,参数]

8.3自定义异常

Python允许自定义异常,用于描述Python中没有涉及的异常情况。自定义异常必须继承自Exception类,且自定义异常必须按照命名规范以Error结尾,以便显式的告知这是异常类。自定义异常需要使用raise语句抛出,且必须人工抛出。

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值