Python面向对象程序设计

1.8.1面向对象概述

        Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是很容易的。本章节我们将详细介绍Python的面向对象编程。
        面向对象中的对象(Object),通常是指客观世界中存在的对象,具有唯一性,对象之间不相同,各有各的特点,每一个对象都有自己的运动规律和内部状态,对象与对象之间又是可以相互联系,相互作用的。另外,对象也可以是一个抽象的事物。

1.8.1.1对象

        对象,是一种抽象概念,英文称作”Object”,表示任意存在的事物,世间万物皆对象!现实世界中,随处可见的一种事物就是对象,对象就是事物存在的实际,通常将对象划分为两个部分,即静态部分与动态部分。静态部分称为”属性”,任何对象都具备自身属性,这些属性不仅是客观存在的,而且是不能被忽视的,如人的性别;动态部分指的是对象的行为,即对象执行的动作,在Python中,一切都是对象。即不仅是具体的事物称为对象,字符串、函数等也都是对象。

1.8.1.2 类

        类是封装对象的属性和行为的载体,反过来说具有相同属性和行为的一类实体被成为类
        举例:把大雁比作大雁类,那么大象类就具备了翅膀和爪的属性,觅食、飞行和睡觉等行为,而一只要从北方飞往南方的大雁被视为大雁类的一个对象。
在Python语言中,类是一种抽象概念,如定义一个大雁类(Geese),在该类中,可以定义每个对象共有的属性和方法,而一只要从北方飞往南方的大雁被视为大雁类的一个对象(wildGeese),对象是类的实例

1.8.1.3面向对象程序设计的特点

面向对象程序设计具有三大基本特征:封装、继承和多态
1.封装
        封装是面向对象编程的核心思想,将对象的属性和行为封装起来,其载体就是类,类通常会对客户隐藏其实现细节,这就是封装的思想。
        采用封装思想保证类内部数据结构的完整性,使用该类的用户不能直接看到类中的数据结构,而只能执行允许公开的数据,这样就避免了外部对内部数据的影响,提高了程序的可维护性。说白了就是,提供接口给你使用,但你并不知道接口是如何构成的,不能操作类中的内部数据。
2.继承
        继承是实现重复利用的重要手段,子类通过继承复用了父类的属性和行为的同时又添加了子类特有的属性和行为。
        例:我们定义一个四边形的类,平行四边形继承自四边形,平行四边形即拥有四边类的属性和方法,也可拥有自己的属性和方法
3.多态
        将父类对象应用于子类的特征就是多态。不同的子类继承同一父类,在子类继承父类特征的同时,也具备了自己的特征,并且能够实现不同的效果,这就是多态化的结构。

1.8.2类的定义和使用

1.8.2.1 定义类

在python中,类的定义使用class关键字实现,语法如下:

class ClassName:
‘’’类的帮助信息‘’’   #类文档字符串
statement		  #类体

参数说明:
ClassName:用于指定类名,一般使用大写字母开头,如果类名中包括两个单词,第二个单词的首字母也大写,这种命名方法也称为”驼峰式命名法”
‘’’类的帮助信息‘’’:用于指定类的文档字符串,定义该字符串后,在创建类的对象时,输入类名和左侧的括号后,将显示该信息

statement:类体,主要由类变量(或类成员)、方法和属性等定义语句组成。如果在定义类时,没想好类的具体功能,也可以在类体中直接使用pass语句代替

示例代码:

class  Geese:
    '''
    这是一个大雁类
    '''
	pass

1.8.2.2创建类的实例

        定义完类后,并不会真正的创建一个实例,这有点像一个自行车的设计图,设计图可以告诉你自行车是个什么样子,但设计图本身并不是一个自行车。你并不能骑走它,它只能用来建造真正的自行车,而且可以使用他制造很多的自行车。那么如何创建实例呢?
        class语句本身并不创建该类的任何实例,所以在类定义完成以后,可以创建类的实例,即实例化该类的对象。创建类的实例的语法如下:

ClassName(parameterlist)

ClassName是必选参数,用于指定具体的类
parameterlist是可选参数,当创建一个类时,没有创建__init__()方法,或者__init__()方法只有一个self参数时,parameterlist可以省略。
示例代码:

class  Dog:
    '''
    这是一个狗类
    '''
    pass
wildDog =Dog()  #创建狗类的一个实例
print(wildDoge)

1.8.2.3 创建_ init _()方法

        在创建后,可以手动创建一个 _ _inti_ _()方法。该方法是一个特殊的方法,类似Java语言中的构造方法。每当创建一个类的新实例时,Python都会自动执行它。
         _ _inti_ _()方法必须包含一个self参数,并且必须是第一个参数,self参数时一个指向实例本身的引用,用于访问类中的属性和方法。在方法调用时会自动传递实际参数self,因此当_ _inti_ _()方法只有一个参数时,在创建类时,就不需要指定实际参数了。
示例:下面仍然以狗为例声明一个类,并为其创建_ _inti_ _()方法

class Dog:
    """
    这是一个狗类
    """
    def __init__(self):
        print("这是一个狗类")

wildDog=Dog() #创建狗类的实例

运行结果:

这是一个狗类

从上面的运行结果可以看出,在创建狗类的实例时,虽然没有为__init__()方法指定参数,但是该方法会自动执行。
在__init__()方法中,除了self参数外,还可以自定义一些参数,参数间使用逗号进行分隔。
示例:

class Dog:
    """
    这是一个狗类
    """
    def __init__(self,name):

        print("一个名为"+name+"的狗出生了")
wildDog=Dog("小黑") #创建狗类的实例

结果:

一个名为小黑的狗出生了

1.8.2.4 创建类的成员并访问

        类的主要成员主要是由实例方法数据成员组成的。在类中创建了类的成员后,可以通过类的实例进行访问。
1.创建实例方法并访问
        所谓实例方法是指在类中定义的函数。这个函数是在类的实例上操作的函数。同_ _init_ _()方法一样,实例方法的第一个参数必须是self,并且必须包含一个self。
语法格式:

def functionName(self,parameterlist):
Block

说明:
functionName:用于指定方法名
self:必要参数,表示类的实例(名字可以是其他名字,使用self只是约定俗成的)
parameter:用于指定除self参数以外的参数,各参数使用逗号间隔
block:方法体,实现的具体功能
实例方法在创建完成后,可以通过类的实例名称+点 +方法名(输入参数)进行访问。
示例:给狗创建一个叫的方法

class Dog:
    """
    这是一个狗类
    """

    def __init__(self,name):
        self.name=name
        print("一个名为"+self.name+"的狗出生了")
    def dark(self):
        print(self.name+"汪汪汪")
wildDog=Dog("小黑") #创建狗类的实例
wildDog.dark() #调用dark方法

结果:

一个名为小黑的狗出生了
小黑汪汪汪

类方法
        Python 类方法和实例方法相似,它最少也要包含一个参数,只不过类方法中通常将其命名为 cls,Python 会自动将类本身绑定给 cls 参数(注意,绑定的不是类对象)。也就是说,我们在调用类方法时,无需显式为 cls 参数传参。创建类方法需要使用@classmethod进行修饰
示例:

class Dog:
    """
    这是一个狗类
    """
    __colour="黑"  #定义一个私有属性
    kind="中华田园犬"  #创建类属性  狗的种类是中华田园犬
    def __init__(self,name):
        self.name=name
        self.age="这是个新出生的狗子,0岁"  #创建一个实例变量 年龄为0
        print("一个名为"+self.name+"的狗出生了"+"他的种类是"+self.kind)
    def dark(self):
        print(self.name+"汪汪汪"+self.kind)
    @classmethod #这是一个类方法
    def eat(cls,food):
        print("吃"+food)
xiaohei=Dog("小黑")
Dog.eat("肉")  #推荐使用类名+类方法名进行调用

运行结果:

一个名为小黑的狗出生了他的种类是中华田园犬
吃肉

2.创建数据成员并访问
        类属性是指在类中定义的变量,即属性。属性又分为类属性和实例属性
类属性:
        类属性是指定义在类中,并且在函数体外的属性。类属性可以再类的所有实例之间共享值,也就是在所有实例化的对象中公用。类属性可以提供给类名或者属性名访问,可以通过访问修改类属性,也可以添加类属性。在修改类属性后,该类的所有实例中类属性都会改变
示例:

class Dog:
    """
    这是一个狗类
    """
    kind="中华田园犬"  #创建类属性  狗的种类是中华田园犬
    def __init__(self,name):
        self.name=name
        print("一个名为"+self.name+"的狗出生了"+"他的种类是"+self.kind)
    def dark(self):
        print(self.name+"汪汪汪"+self.kind)
wildDog=Dog("小黑") #创建狗类的实例
print(wildDog.kind)  #使用实例调用类属性
print(Dog.kind)      #使用类名调用类属性
Dog.colour="黑色" #添加类属性
print(wildDog.colour)  #添加后的类属性可以直接调用
Dog.kind="藏獒"  #修改类属性成为藏獒
xiaobai=Dog("小白")
xiaobai.dark()   #构造方法和dark方法中的kind 都变成了藏獒

结果:

一个名为小黑的狗出生了他的种类是中华田园犬
中华田园犬
中华田园犬
黑色
一个名为小白的狗出生了他的种类是藏獒
小白汪汪汪藏獒

实例属性
        实例属性是指定义在类的方法中的属性,只作用于当前实例中,实例属性只能通过实例+实例属性名调用,不能使用类+实例属性名调用,通过实例名修改实例属性后,并不影响该类另一个实例中相应的实例属性的值
示例:

class Dog:
    """
    这是一个狗类
    """
    kind="中华田园犬"  #创建类属性  狗的种类是中华田园犬
    def __init__(self,name):
        self.name=name
        self.age="这是个新出生的狗子,0岁"  #创建一个实例变量 年龄为0
        print("一个名为"+self.name+"的狗出生了"+"他的种类是"+self.kind)
    def dark(self):
        print(self.name+"汪汪汪"+self.kind)
xiaobai=Dog("小白")
xiaohei=Dog("小黑")
#修改xiaobai的age因为小白是个轮回狗 出生就99岁
xiaobai.age="这不是一个正常狗子,一出生就99岁"
print(xiaobai.age)    #调用xiaobai的age实例属性
print(xiaohei.age)    #调用xiaohei的age实例属性,并不会因为xiaobai的age改变而改变

运行结果:

一个名为小白的狗出生了他的种类是中华田园犬
一个名为小黑的狗出生了他的种类是中华田园犬
这不是一个正常狗子,一出生就99岁
这是个新出生的狗子,0

1.8.2.5 访问限制

        在Python中并没有对属性和方法的访问权限进行限制,为了保证类内部的某些属性或方法不被外部所方位,可以在属性或方法名前面添加双下划线或首尾加双下划线线,从而限制访问权限。
(1)首尾双下划线表示定义特殊方法,一般是系统定义名字,如__init__()
(2)双下划线表示private(私有)类型的成员,只允许定义该方法的类本身进行访问,而且也不能通过类的实例进行访问,但是可以通过”类的实例名.类名 _xxx”的方式访问
示例:

class Dog:
    """
    这是一个狗类
    """
    __colour="黑"  #定义一个私有属性
    kind="中华田园犬"  #创建类属性  狗的种类是中华田园犬
    def __init__(self,name):
        self.name=name
        self.age="这是个新出生的狗子,0岁"  #创建一个实例变量 年龄为0
        print("一个名为"+self.name+"的狗出生了"+"他的种类是"+self.kind)
    def dark(self):
        print(self.name+"汪汪汪"+self.kind)
xiaohei=Dog("小黑")

print(xiaohei._Dog__colour)  #正常访问
print(xiaohei.__colour)      #报错,找不到__colour的属性

运行结果:

Traceback (most recent call last):
  File "F:/PYHome/FrameVIP07/Unit7/Unit7class1.py", line 24, in <module>
    print(xiaohei.__colour)
AttributeError: 'Dog' object has no attribute '__colour'
一个名为小黑的狗出生了他的种类是中华田园犬
黑

1.8.3继承

        在编写类时,并不是每次都要从空白开始。当要编写一个类的时候与另外一个类之间存在一定继承关系时,就可以通过继承来达到代码重用的目的。

1.8.3.1继承的基本语法

        继承是面向对象编程最重要的特征之一,在面向对象编程中,被继承的类被称为父类或基类,新的类称为子类或派生类。在python中,新建的类可以继承一个或多个父类。
语法格式:

class ClassName(baseclasslist):
‘’’类的帮助信息‘’
statement  #类体’

参数说明:
ClassName:用于指定类名
baseclasslist:用于指定要继承的基类,可以有多个,类名之间用逗号分隔若不指定,将使用所有Python对象的基类Object
statement:类体

示例代码:

class Fruit:                   #定义一个水果类  (基类)
    color="青色"                #定义类属性
    def harvest(self,color):   #定义方法
        print("水果是"+color+"的!")      #输出的是形式参数color
        print("水果已经收获......")
        print("水果原来是"+Fruit.color+"的!")  #输出的是类属性

class Apple(Fruit):           #定义Apple类
    color='红色'
    def __init__(self):
        print("我是苹果类")

apple=Apple()   #实例化Apple
apple.harvest(Apple.color) #调用父类的harvest方法

运行结果:

我是苹果类
水果是红色的!
水果已经收获......
水果原来是青色的!

1.8.3.2方法重写

        基类的成员都会被派生类继承,当基类中的某个方法不能满足派生类的需求时,就需要在派生类中重写父类的这个方法,这和Java语言中的重写方法是一样的。
示例:

class Fruit:                   #定义一个水果类  (基类)
    color="青色"                #定义类属性
    def harvest(self,color):   #定义方法
        print("水果是"+color+"的!")      #输出的是形式参数color
        print("水果已经收获......")
        print("水果原来是"+Fruit.color+"的!")  #输出的是类属性

class Orange(Fruit):
    def harvest(self,color,num):   #重写 harvest方法
        print("我已经成熟了变成了这个"+color+"了!!!")
        print("一棵橘子树上能有"+num+"个橘子")

orange=Orange()  #创建橘子实例
orange.harvest("红色","260")

运行结果:

我已经成熟了变成了这个红色了!!!
一棵橘子树上能有260个橘子

1.8.3.3派生类中调用基类的__init__()方法

        在派生类中定义_ _init_ _()方法时,不会自动调用基类的_ _init_ _()方法,要想派生类调用基类的_ _init_ _()方法,需要进行初始化,需要在派生类使用super()函数调用基类的_ _init_ _()方法。
示例代码:

class Fruit:  # 定义一个水果类  (基类)

    def __init__(self,name):
        print("我是所有的水果的爸爸"+name)

class Orange(Fruit):
    def __init__(self,name):
        print("我是一颗"+name)

        super().__init__(name)  #如果有参数  传入参数

orange = Orange("橘子")

运行结果:

我是一颗橘子
我是所有的水果的爸爸橘子

1.8.4 类的总结

1.类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
2.类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
3.数据成员:类变量或者实例变量, 用于处理类及其实例对象的相关的数据。
4.方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
5.局部变量:定义在方法中的变量,只作用于当前实例的类。
6.实例变量:在类的声明中,属性是用变量来表示的。这种变量就称为实例变量,是在类声明的内部但是在类的其他成员方法之外声明的。
7.继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。
8.实例化:创建一个类的实例,类的具体对象。
9.方法:类中定义的函数。
10.对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

花落同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值