面向对象
面向对象(Object Oriented,OO)是软件开发方法。面向对象的概念和应用已超越了程序设计和软件开发,扩展到如数据库系统、交互式界面、应用结构、应用平台、分布式系统、网络管理结构、CAD技术、人工智能等领域。面向对象是一种对现实世界理解和抽象的方法,是计算机编程技术 [1] 发展到一定阶段后的产物。
早期的计算机编程是基于面向过程的方法,例如实现算术运算1+1+2 = 4,通过设计一个算法就可以解决当时的问题。随着计算机技术的不断提高,计算机被用于解决越来越复杂的问题。一切事物皆对象,通过面向对象的方式,将现实世界的事物抽象成对象,现实世界中的关系抽象成类、继承,帮助人们实现对现实世界的抽象与数字建模。通过面向对象的方法,更利于用人理解的方式对复杂系统进行分析、设计与编程。同时,面向对象能有效提高编程的效率,通过封装技术,消息机制可以像搭积木的一样快速开发出一个全新的系统。面向对象是指一种程序设计范型,同时也是一种程序开发的方法。对象指的是类的集合。它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性、灵活性和扩展性。
起初,“面向对象”是专指在程序设计中采用封装、继承、多态等设计方法。
面向对象的思想已经涉及到软件开发的各个方面。如,面向对象的分析(OOA,Object Oriented Analysis),面向对象的设计(OOD,Object Oriented Design)、以及我们经常说的面向对象的编程实现(OOP,Object Oriented Programming)。
面向对象的分析根据抽象关键的问题域来分解系统。面向对象的设计是一种提供符号设计系统的面向对象的实现过程,它用非常接近实际领域术语的方法把系统构造成“现实世界”的对象。面向对象程序设计可以看作一种在程序中包含各种独立而又互相调用的对象的思想,这与传统的思想刚好相反:传统的程序设计主张将程序看作一系列函数的集合,或者直接就是一系列对电脑下达的指令。面向对象程序设计中的每一个对象都应该能够接受数据、处理数据并将数据传达给其它对象,因此它们都可以被看作一个小型的“机器”,即对象。
面向对象的基础语法
当一个类定义完成之后,要使用这个类来创建对象,语法格式如下:
对象变量 = 类名()
类的设计:
在程序开发中,要设计一个类,通常需要满足以下三个要求:
1.类名 这类事物的名字,满足大驼峰命名法
2.属性 这类事物具有什么样的特征
3.方法 这类事物具有什么样的行为
例如:
小明今年18岁,身高1.75,每天早上要跑步,会去吃东西
小美今年17岁,身高1.65,小美不跑步,小美喜欢吃东西
类名:Person( )
属性:name age height
方法:run( ) eat( )
一只黄颜色的狗狗叫大黄
看见生人汪汪叫
看见家人摇尾巴
类名:Dog( )
属性:color name
方法:shout( ) shake( )
需求:
小猫爱吃鱼,小猫要喝水
"""
class Cat():
def eat(self):
print '小猫爱喝水'
def drink(self):
print '小猫要喝水'
tom = Cat()
tom.eat()
tom.drink()
# 需求:
# 小明今年18岁,身高1.75,每天早晨要跑步,会去吃东西
# 小美今年17岁,身高1.65,小美不跑步,喜欢吃东西
# Person()
# name
# age
# height
# run()
# eat()
面向对象的基础语法:
定义简单的类:
定义只包含方法的类:
class 类名:
def 方法1(self,参数列表):
pass
def 方法2(self,参数列表):
pass
当一个类定义完成后,要使用这个类来创建对象,语法格式如下:
对象变量 = 类名 ()
class Cat():
def eat(self):
print '%s 爱喝水 ' %self.name
def drink(self):
print '%s 要喝水' %self.name
# 创建猫对象
tom = Cat()
tom.name = 'tom'
tom.eat()
tom.drink()
print tom
# addr = id (tom)
# print '%x' %addr
# %x:打印格式为十六进制
# print '%d' %addr
# %d:打印格式为十进制
mimi = Cat()
mimi.name = 'lazy_cat'
mimi.eat()
mimi.drink()
print mimi
addr1 = id(mimi)
print 'mimi的地址为 %s' %addr1
lazy_cat2 = mimi
addr2 = id (lazy_cat2)
print 'lazy_cat2的地址为 %s' %addr2
"""
在日常开发中,不推荐在类的外部给对象增加属性
如果在运行时,没有找到属性,程序会报错
"""
self的使用:
万能说法:self 哪一个对象调用的方法,self就是哪一个对象的引用
# self 哪一个对象调用的方法,self就是哪一个对象的引用
def eat(self):
print '%s 爱吃鱼 ' % self.name
def drink(self):
print '%s 要喝水' % self.name
# 创建猫对象
tom = Cat()
tom.name = 'tom'
tom.eat()
tom.drink()
print tom
# addr = id (tom)
# print '%x' %addr
# print '%d' %addr
mimi = Cat()
mimi.name = 'mimi'
mimi.eat()
mimi.drink()
print mimi
# 创建出来的两个猫对象没有任何关系
面向对象初始化
初始化方法
我们现在已经知道了使用类名()就可以创建一个对象
当使用类名()创建对象时,python的 解释器会自动执行以下操作:
1.为对象在内存中分配空间–创建对象
2.调用初始化方法为对象的属性设置初始值–初始化方法(init(self))
这个初始化方法就是init方法,init时对象的内置方法
init方法是专门用来定义一个类具有哪些属性的方法
class Cat():
def __init__(self):
print '__init__(self)是一种初始化方法'
# 使用类名()创建对象的时候,会自动调用初始化方法'__init__(self)'
self.name = 'fentiao'
# self.属性名 = 属性的初始值,此时传入的属性名是固定的
tom = Cat()
print tom.name
Jimmy = Cat()
print Jimmy.name
# 固定的属性名称'fentiao'
class Cat():
def __init__(self,new_name):
# 传入形参new_name
print '__init__(self)是一种初始化方法'
self.name = new_name
# 在类中,任何方法都可以使用self.name
print '%s 爱吃小鱼' %self.name
tom = Cat('tom')
print tom.name
Jimmy = Cat('Jimmy')
print Jimmy.name
内置方法
del方法:
在python中当使用类名()创建对象时,为对象分配空间后,
会自动调用init方法;
当一个对象被从内存中销毁前,会自动调用del方法
class Cat():
def __init__(self,new_name):
self.name = new_name
print '%s 来了' %self.name
def __del__(self):
print '%s 被删除了' %self.name
Tom = Cat('Tom')
print Tom.name
print '~~~~~'
class Cat():
def __init__(self,new_name):
self.name = new_name
print '%s 来了' %self.name
def __del__(self):
print '%s 被删除了' %self.name
Tom = Cat('Tom')
print Tom.name
del Tom
print '~~~~~'
str内置方法
在python中,使用python输出对象变量,
默认情况下,会输出这个变量引用的对象是由哪一个类创建的对象
以及在内存中的地址(十六进制)
如果在开发中,希望使用print输出对象变量时,
能够打印自定义的内容,就可以利用str这个内置方法
class Cat():
def __init__(self,new_name):
self.name = new_name
def __str__(self):
# 必须返回一个字符串
return '我是一只叫%s的小猫咪' %self.name
Tom = Cat('tom')
print Tom
“面向对象”是专指在程序设计中采用封装、继承、多态等设计方法:
下面我们就来学习封装 继承 多态
什么是封装 继承 多态 ?
1.封装
根据职责将属性和方法封装到一个抽象的类中定义类的准则
2.继承
实现代码的重用,相同的代码不需要重复的编写设计类的技巧
子类针对自己特有的需求,编写特定的代码
3.多态
不同的子类(这是之前提到的继承的知识)对象调用相同的方法,产生不同的执行结果
封装
1.封装是面向对象编程的一大特点
2.面向对象编程的第一步 将属性和方法封装到一个抽象的类中
3.外界使用类创建对象,然后让对象调用方法
class Person:
def __init__(self, name, weight):
self.name = name
self.weight = weight
def __str__(self):
return '我的名字是 %s,我的体重为 %.2f' % (self.name, self.weight)
def run(self):
self.weight -= 0.5
print '%s 每次跑步体重减少0.5公斤' % self.name
# 在对象的方法内部,是可以直接访问对象的属性
def eat(self):
self.weight += 1
print '%s每次吃东西体重增加一公斤' % self.name
XX = Person('xiaoming', 75.0)
XX.run()
XX.eat()
XX.eat()
print XX
摆放家具
需求:
1.房子有户型,总面积和家具名称列表
新房子没有任何的家具
2.家具有名称和占地面积,其中
床:占4平方米
衣柜:占2平方米
餐桌:占1.5平米
3.将以上三种家具添加到房子中
4.打印房子时,要求输出:户型,总面积,剩余面积,家具名称列表
设计思路:
1.创建了一个家具类,使用init和str两个内置方法
2.准备了一个add_furniture 方法准备添加家具
3.使用房子类 创建了一个 房子对象
4.让 房子对象 调用三次add_furniture 方法,
将三件家具以实参的形式传递到add_furniture
class Furniture:
def __init__(self, name, area):
#初始化方法
self.name = name
self.area = area
def __str__(self):
return '%s 占地 %.2f' % (self.name, self.area)
# 创建家具
bed = Furniture('bed', 4)
print bed
chest = Furniture('chest', 2)
print chest
table = Furniture('table', 1.5)
print table
class House:
def __init__(self, type, area):
self.type = type
self.area = area
self.free_area = area
# 剩余面积
self.fur_list = []
# 家具名称列表
def __str__(self):
return '房子户型: %s' \
'占地面积:%.2f' \
'剩余面积: %.2f' \
% (self.type, self.area, self.free_area)
def add_furniture(self, fur_name, fur_area):
print '添加 %s,面积为 %s' % (fur_name, fur_area)
# 1.判断家具面积和剩余占地面积
if fur_area > self.free_area:
print '你的%s面积过大,无法添加' %fur_name
return
# 2.将家具名称添加到列表中
else:
self.fur_list.append(fur_name)
# 3.计算剩余面积
self.free_area -= fur_area
# 创建房子
my_home = House('两室一厅', 100)
print House
# 添加家具
my_home.add_furniture('bed', 100)
my_home.add_furniture('chest', 2)
my_home.add_furniture('table', 1.5)
print my_home
士兵开枪问题:
1.士兵瑞恩有一把AK47
2.士兵可以开火(士兵开火扣动的是扳机)
3.枪 能够 发射子弹(把子弹发射出去)
4.枪 能够 装填子弹 –增加子弹的数量
Soldier Gun
——– ———-
name model
gun bullet_count #子弹数量足够多才能完成射击的动作
——– ———-
init(self): init(self):
fire(self): add_bullet(self,count): #填充子弹的方法
shoot(self):
class Gun:
def __init__(self, model):
self.model = model
self.bullet_count = 0
def add_bullet(self, count):
self.bullet_count += count
def shoot(self):
if self.bullet_count <= 0:
print '%s子弹不够' %self.model
return
self.bullet_count-= 1
print '%s tututu 剩余子弹数目为 %d' % (self.model, self.bullet_count)
class Soliar:
def __init__(self, name):
self.name = name
self.Gun = None
def bullet_add(self,count):
self.Gun.add_bullet()
def fire(self):
if self.Gun == None:
print '%s 没枪阿' % self.name
return
print '冲阿'
self.Gun.shoot()
# 1.创建枪对象
ak47 = Gun('AK47')
# 2.创建士兵
ryen = Soliar('RYEN')
ryen.Gun = ak47
ryen.Gun.add_bullet(50)
ryen.Gun.shoot()
ryen.fire()
ryen.fire()
print ryen.Gun
面向对象的三大属性:
封装:根据职责将属性和方法封装在一个抽象的类中
继承:实现代码的重用,相同的代码不需要重复的写
多态:不同的对象调用相同的方法,产生不同的结果,增强代码的灵活度
单继承
1.继承的概念 语法 和 特点
概念:字类拥有父类的所有方法和属性(子类只需封装自己特有的功能属性)
2.继承的语法
class 类名(父类)
def 子类特有的方法
继承的传递性:(爷爷 父亲 儿子)
1.C类从B类继承,B类从A类继承
2.C类具有B类和A类的所有属性和方法
子类拥有父类以及父类的父类中封装的所有属性和方法
class Animal():
def eat(self):
print '吃吃吃'
def drink(self):
print '呵呵呵'
def lue(self):
print '略略略'
class Cat(Animal):
def buy(self):
print '买买买'
class DuolaAmeng(Cat):
def play(self):
print '玩玩玩'
DD = DuolaAmeng()
DD.lue()
DD.buy()
DD.drink()
DD.eat()
DD.play()
重写父类
方法有两种情况:
1.覆盖父类的方法
2.对父类方法进行扩展
覆盖父类的方法
如果在开发中,父类方法的实现和子类方法的实现完全不同,
就可以使用覆盖的方式,在子类中重新编写父类的方法
具体实现方式,就相当于在子类中定义了
一个和父类同名的方法并且实现
重写之后,在运行时,只会调用子类的重写方法,
而不会调用父类封装的方法
class Animal():
def eat(self):
print '吃吃吃'
def drink(self):
print '呵呵呵'
def lue(self):
print '略略略'
class Cat(Animal):
def call(self):
print '喵喵~'
class DuolaAmeng(Cat):
def speak(self):
print '我可以说日语'
def call(self):
print '欧哈有'
dingdang = DuolaAmeng()
# 如果子类中,重写了父类的方法
# 在运行中,只会调用子类中重写的方法,不会调用父类的方法
dingdang.call()
继承重写扩展:
对父类的方法进行拓展
如果在开发中,子类的方法实现包含有父类的方法实现
(父类原本封装的方法实现是子类方法的一部分就可以使用扩展方法)
1.在子类中重写弗雷德方法
2.在需要的位置i使用 父类名.方法(self)来调用父类方法的执行
(使用父类名称调用父类方法)
3.代码其他的位置针对子类的需求,编写子类特有的代码实现
class Animal():
def eat(self):
print '吃吃吃'
def drink(self):
print '呵呵呵'
def lue(self):
print '略略略'
class Cat(Animal):
def call(self):
print '喵喵~'
class DuolaAmeng(Cat):
def speak(self):
print '我可以说日语'
def call(self):
print '欧哈有'
Cat.call(self)
print '卡哇伊'
kt = DuolaAmeng()
kt.call()
当出现重写扩展被初始化需要先继承父类初始化属性,否则被覆盖的属性不能被子类继承调用
class Bird:
def __init__(self):
self.hungry = True
def eat(self):
if self.hungry:
print '饿了,然后吃饱饱了'
else:
print '不饿,谢谢'
class SongBird(Bird):
def __init__(self):
self.sound = 'lalala'
Bird.__init__(self)
def sing(self):
print self.sound
# bird = Bird()
# bird.eat()
Little_bird = SongBird()
# Little_bird .eat() #继承父类时会报错,因为被init初始化时覆盖了,
# 此时需要在之前继承父类的初始化
Little_bird.eat()
Little_bird.sing()
多继承
子类拥有一个父类叫单继承
子类可以拥有多个父类,并且具有所有父类的属性和方法
例如:孩子会继承自己父亲和母亲的特性
语法:
calss 字类名 (父类名1,父类名2…)
pass
class A():
def test(self):
print 'A--test方法'
def demo(self):
print 'A--demo方法'
class B():
def test(self):
print 'B--test方法'
def demo(self):
print 'B--demo方法'
class C(B, A):
pass
# 多继承可以让子类对象,同时具有多个父类的属性和方法
# 当多继承时,不同的父类中有相同的方法或属性,子类继承时,遵循其后跟的父类顺序
# 谁在前,就用谁
c = C()
c.demo()
c.test()
class D(C):
pass
D = C()
D.test()
D.demo()
3.多态
不同的子类(这是之前提到的继承的知识)
对象调用相同的方法,产生不同的执行结果
class Dog(object):
def __init__(self, name):
self.name = name
print '%s 会汪汪叫,自由自在玩' % self.name
def game(self):
print '%s 会玩 2048' % self.name
class Zhuhegou(Dog):
def game(self):
print '%s 会打王者荣耀' % self.name
class Person(object):
def __init__(self, name):
self.name = name
def game_with_dog(self,dog):
# 将 狗 写入游戏和人玩
print '%s 和 %s一起玩游戏' % (self.name, dog.name)
dog.game()
# 创建一个人对象
xiaolin = Person('xiaolin')
# 创建一个狗对象
wangcai = Zhuhegou('汪财')
# 汪财和人玩 汪财会玩王者荣耀
# wangcai = Dog('汪财')
# 汪财和人玩 汪财会玩2048
xiaolin.game_with_dog(wangcai)