#####python面向对象的三大特征#####

面向对象程序设计具有许多优点:

1、开发时间短,效率高,可靠性高,所开发的程序更强壮。由于面向对象编程的可重用性,可以在应用程序中大量采用成熟的类库,从而缩短了开发时间。

2、应用程序更易于维护、更新和升级。继承和封装使得应用程序的修改带来的影响更加局部化。

1.面向对象的三大特征:封装(Encapsulation)、继承(Inheritance)、多态(Polymorphism)
在这里插入图片描述
.继承:  继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法。对象的一个新类可以从现有的类中派生,这个过程称为类继承。新类继承了原始类的特性,新类称为原始类的派生类(子类),而原始类称为新类的基类(父类)。派生类可以从它的基类那里继承方法和实例变量,并且类可以修改或增加新的方法使之更适合特殊的需要。这也体现了大自然中一般与特殊的关系。继承性很好的解决了软件的可重用性问题。比如说,所有的Windows应用程序都有一个窗口,它们可以看作都是从一个窗口类派生出来的。但是有的应用程序用于文字处理,有的应用程序用于绘图,这是由于派生出了不同的子类,各个子类添加了不同的特性。

  • 最大的好处是子类获得父类全部功能,实现代码重用
class Animal:
   def eat(self):
      print('%s爱吃' %(self.name))
   def drink(self):
      print('%s要喝水' %(self.name))
class Cat(Animal):
   def __init__(self,name):
      self.name = name
   def sleep(self):
      print('%s爱睡觉' %(self.name))
class Dog(Animal):
   def __init__(self,name):
      self.name = name
   def dance(self):
      print('%s爱跳' %(self.name))
cat1 = Cat('tom')
cat1.sleep()
cat1.drink()
cat1.eat()

dog1 = Dog('Jeck')
dog1.drink()
dog1.dance()
运行:
tom要喝水
tom爱吃
Jeck要喝水
Jeck爱跳

Process finished with exit code 0

class Animal():  #定义动物类
    def run(self):
        print('running~~')
    def call(self):
        print('hahahah')   # 动物类中存在两个方法

class Cat(Animal):   # 定义猫类,继承动物类
    pass  
tom = Cat()  # 常见一个猫类实例
tom.run()  # 该实例可以直接调用动物类的方法

#输出结果:
running~~

可以在子类中添加自己特定功能的一些方法


class Animal():
    def run(self):
        print('running~~')
    def call(self):
        print('hahahah')
class Cat(Animal):
    def eat(self):
        print('爱吃鱼')
tom = Cat()
tom.run()  # 调用父类的方法
tom.eat()  # 使用自己类的方法

#输出结果:
running~~
爱吃鱼

当父类方法的实现不能满虚子类的需求的时候可以对方法进行重写,我们说,子类的方法覆盖了父类的方法,在代码运行的时候,总是会调用子类的该方法。

class Animal():
    def run(self):
        print('running~~')   #父类中存在run方法
    def call(self):
        print('hahahah')
class Cat(Animal):
    def run(self):
        print('跑得快')    # 子类中也存在run方法
    def eat(self):
        print('爱吃鱼')
tom = Cat()
tom.run()   # 当实例调用run方法的时候,总是调用的子类中的程序

#运行结果:
跑得快

可以对父类方法进行扩展。保留父类方法的内容,在其基础上增加新的内容。只需要子子类中定义和父类中相同的方法,并且在该方法中写入super().call()(父类.方法(self) python2.x通过个该实现),然后添加需要扩展的内容即可。

在这里插入代码片

class Animal():
def run(self):
print(‘running~~’)
def call(self):
print(‘hahahah’)
class Cat(Animal):
def run(self):
super().run() # 继承父类给方法的内容,同时添加扩展的内容
print(‘跑得快’)
def eat(self):
print(‘爱吃鱼’)
tom = Cat()
tom.run()

#输出结果:
running~~
跑得快
当父类中使用了初始化方法,在子类中也想使用初始化方法的时候,需要使用在子类初始化方法中使用super().init(),表示对父类初始化方法的继承扩展,如若没有,会出现冲突报错。

class Animal():
    def __init__(self,name):
        self.name = name
    def run(self):
        print('running~~')
    def call(self):
        print('hahahah')
class Cat(Animal):
    def __init__(self,color,name):
        super().__init__(name)   #在子类中必须使用该语句,表示继承父类中的属性。
        self.color = color
    def run(self):
        super().run()
        print('跑得快')
    def eat(self):
        print('爱吃鱼')
tom = Cat('tom','red')
print(tom.name)
print(tom.color)

#输出结果:
red
tom


当子类继承子多个父类的时候,并且多个父类中存在相同的方法,这时候该子类的实例取调用这个方法的时候,就会出现那个被继承的父类写在前面,就使用哪一个父类的方法。建议在定义方法的时候,尽量不要使用相同的名称

class A:   #定义A 类
    def lala(self):
        print('lala')
    def toto(self):
        print('toto')  # 其中由来两个方法
class B:  # 定义B类
    def lala(self):
        print('LALA')
    def toto(self):
        print('TOTO')   # 其中由两个方法,并且方法名称和A中方法名称一致
class C(A,B):   #定义类C 继承A,B 两个类
    pass
class D(B,A):   # 定义类D 继承B,A 两个类
    pass

c = C()
d = D()

c.lala()  
d.lala()

c.toto()
d.toto()    # 当继承父类的顺序不同的时候,导致调用的方法是不同的内容,默认调用位置靠前的父类方法

#输出结果:
lala
LALA
toto
TOTO

.封装:

封装是面向对象的特征之一,是对象和类概念的主要特性。封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。一旦定义了一个对象的特性,则有必要决定这些特性的可见性,即哪些特性对外部世界是可见的,哪些特性用于表示内部状态。在这个阶段定义对象的接口。通常,应禁止直接访问一个对象的实际表示,而应通过操作接口访问对象,这称为信息隐藏。事实上,信息隐藏是用户对封装性的认识,封装则为信息隐藏提供支持。封装保证了模块具有较好的独立性,使得程序维护修改较为容易。对应用程序的修改仅限于类的内部,因而可以将应用程序修改带来的影响减少到最低限度。

class Person:  ##定义一个类
    def __init__(self,name,age,gender):  #类属性有姓名、年龄和性别
        self.name = name
        self.age = age
        self.gender = gender
    def eat(self):
        print("%s今年%s岁%s,喜欢布娃娃" %(self.name,self.age,self.gender))  #构造类方法将其封装到对象中,通过对象调取
    def study(self):
        print("%s今年%s岁%s,爱学习" % (self.name, self.age, self.gender))
    def paint(self):
        print("%s今年%s岁%s,爱画画" % (self.name, self.age, self.gender))
name = Person("lily",10,"女")  #创建的对象
name.eat()
name.study()
name.paint()

1 示例说明:满足以下需求
需求
1.小明体重75.0公斤
2.小明每次跑步都会减肥0.5公斤
3.小明每次吃东西体重都会增加1公斤

需求
1.小明和小美都爱跑步
2.小美体重45.0公斤
2.每次跑步都会减肥0.5公斤
3.每次吃东西体重都会增加1公斤

class Person:
    def __init__(self,name,weight):
        self.name = name
        self.weight = weight
    def __str__(self):
        return 'this is %s ,my weight is %.2f ' %(self.name,self.weight)
    def eat(self):
        print('%s 吃饭' %self.name)
        self.weight += 1
    def run(self):
        print('%s 跑步' %self.name)
        self.weight -= 0.5
#将属性和方法都封装在一个类中


xiaoming = Person('xiaoming',70)  # 使用列创建对象
xiaoming.eat()  # 使用对象调用方法
xiaoming.run()
print(xiaoming)
xiaohua = Person('xiaohua',45)
xiaohua.eat()
xiaohua.run()
print(xiaohua)

#输出结果:
xiaoming 吃饭
xiaoming 跑步
this is xiaoming ,my weight is 70.50 
xiaohua 吃饭
xiaohua 跑步
this is xiaohua ,my weight is 45.50 

2 根据学生的成绩得到成绩的等级

class Student:
    def __init__(self,name,score):
        #初始化方法,当使用类创建实例的时候都会调该方法
        self.name = name
        self.score = score
    def get_grade(self):
        #对数据封装
        if self.score > 90:
            print('A')
        elif self.score >80:
            print('B')
        else:
            print('C')

toto = Student('toto',95)  # 创建对象
toto.get_grade()  # 直接使用对象调用方法,得到结果

#输出结果:
A

一个对象的属性 可以是另一个对象创建的类

需求:
1.房子有户型,总面积和家具名称列表
新房子是没有家具的
2.家具有名字和占地面积,其中
床:5
桌子:4
椅子:6
3.将以上三件家具添加到房子中
4.打印房子的时候,要求输出:户型 总面积 剩余面积 家具名称列表

class Furniture:   # 限定义家具类
    def __init__(self,name,area):
        self.name = name
        self.area = area
    def __str__(self):
        return 'this is %s, %d square '

#使用类创建好对象之后,该对象可以作为参数用于其他函数调用。

class House:  #在定义房子类
    def __init__(self,type,squa):
        self.fu_list = []
        self.type = type
        self.leftsqua = self.allsqua = squa
    def __str__(self):
        return ' 户型是: %s\n 总面积是: %.2f\n 剩余面积: %.2f\n 家具列表:%s' \
               %(self.type,self.allsqua,self.leftsqua,self.fu_list)
    def add_furn(self,item):  # 在房子类的方法中使用的参数是家具类的一个实例
        if item.area<self.allsqua:
            self.fu_list.append(item.name)
            self.leftsqua -=item.area
        else:
            return
bed = Furniture('bed',5)
desk = Furniture('desk',4)
chair = Furniture('cabinet',6)   # 先实例化 家具

house1 = House('三室',120)  # 在实例化房子
house1.add_furn(bed)   # 再使用房子对象的方法,传入的参赛是家具实例
house1.add_furn(desk)
house1.add_furn(chair)
print(house1)

#输出结果:
 户型是: 三室
 总面积是: 120.00
 剩余面积: 105.00
  家具列表:['bed', 'desk', 'cabinet']

1.士兵瑞恩有一把AK47
2.士兵可以开火(士兵开火扣动的是扳机)
3.枪 能够 发射子弹(把子弹发射出去)
4.枪 能够 装填子弹 --增加子弹的数量

class Gun:   # 定义枪类
    def __init__(self,name):
        self.name = name
        self.count = 3   # 属性:枪名称以及子弹数量
    def add_bullet(self):  # 方法:添加子弹,将子弹数充值3
        self.count = 3
    def launch_bullet(self):   # 发射子弹
        if self.count <= 0:
            self.add_bullet()   #如果没有子弹,先进行添加子弹
        self.count -= 1   # 然后子弹减少一个
        print('%s 已经成功发射子弹 剩余子弹%d' %(self.name,self.count))

class Solair:   # 定义士兵类
    def __init__(self,name):
        self.name = name   # 设置属性 :name
    def shoot(self,gun):  # 定义方法:直接调用枪对象的方法
        gun.launch_bullet()


AK47 = Gun('AK47')   # 实例化一个枪对象
ryan = Solair('Ryan')   #实例化一个士兵对象
ryan.shoot(AK47)  # 士兵对象调用开火方法
ryan.shoot(AK47)
ryan.shoot(AK47)
ryan.shoot(AK47)

#结果:
AK47 已经成功发射子弹 剩余子弹2
AK47 已经成功发射子弹 剩余子弹1
AK47 已经成功发射子弹 剩余子弹0
AK47 已经成功发射子弹 剩余子弹2

多态性:

多态性是指允许不同类的对象对同一消息作出响应。比如同样的加法,把两个时间加在一起和把两个整数加在一起肯定完全不同。又比如,同样的选择编辑-粘贴操作,在字处理程序和绘图程序中有不同的效果。多态性包括参数化多态性和包含多态性。多态性语言具有灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题。
  以封装和继承为前提,存在一个函数,需要一个参数,不用对函数进行修改当参数是不同的对象的时候输出的结果不同,

就是指一个类实例的相同方法在不同情形有不同表现形式。多态机制使具有不同内部结构的对象可以共享相同的外部接口。这意味着,虽然针对不同对象的具体操作不同,但通过一个公共的类,它们(那些操作)可以通过相同的方式予以调用。

不同的子类对象调用相同的方法,产生不同的执行结果

首先要对数据类型再作一点说明。当我们定义一个class的时候,我们实际上就定义了一种数据类型。我们定义的数据类型和Python自带的数据类型,比如str、list、dict没什么两样

class Animal(object):
    def run(self):
        print('Animal is running...')

class Dog(Animal):
    pass

class Cat(Animal):
    pass

a = list()
b = Animal()
c = Dog()
d = Cat()

print(isinstance(a,list))
print(isinstance(b,Animal))
print(isinstance(c,Dog))
print(isinstance(d,Cat))

#输出结果:
True
True
True
True

同时子类实例化出来的对象,不仅是子类类型,同时还是父类类型。在继承关系中,如果一个实例的数据类型是某个子类,那它的数据类型也可以被看做是父类。例如Animal是Dog的父类,使用Dog实例化一个实例,该实例既是Dog类型,也是Animal类型。

class Animal(object):
    def run(self):
        print('Animal is running...')

class Dog(Animal):
    pass

b = Animal()
c = Dog()

print(isinstance(b,Animal))
print(isinstance(c,Dog))
print(isinstance(c,Animal))

#输出结果:
True
True
True

首先存在三个类:Animal、Dog、Cat;Dog、Cat 都继承自Animal类,并且都存在run方法。

class Animal(object):
    def run(self):
        print('Animal is running...')
class Dog(Animal):
    def run(self):
        print('Dog is running')
class Cat(Animal):
    def run(self):
        print('Cat is running')

理解多态的好处,我们还需要再编写一个函数,这个函数接受一个Animal类型的变量:

def run_twice(animal):
    animal.run()
    animal.run()

当我们传入Animal类的实例时,run_twice()就打印出:

def run_twice(animal):
    animal.run()
    animal.run()

run_twice(Animal())

#输出结果:
Animal is running...
Animal is running...

由于Dog类的实例以及Cat类的实例都可以是Animal数据类型,同样也可以作为参数传入该函数,当传入Dog类的实例以及Cat类的实例时候,函数的输出:


def run_twice(animal):
    animal.run()
    animal.run()

run_twice(Dog())
run_twice(Cat())

#输出结果:
Dog is running
Dog is running

Cat is running
Cat is running

现在可以在定义一个以Animal作为父类的子类,并将其实例作为参数,函数run_twice可以正常的运行。


class Tortoise(Animal):
    def run(self):
        print('Tortoise is running slowly~~~')
run_twice(Tortoise())

#输出结果:
Tortoise is running slowly~~~
Tortoise is running slowly~~~

猜你喜欢

转载自blog.csdn.net/weixin_44821839/article/details/92375444