8.python笔记之面向对象基础
面向对象思维导图 (来自11期罗天帅学长)
一、面向对象技术简介
类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。
方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
实例变量:定义在方法中的变量,只作用于当前实例的类。
继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是
模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。
实例化:创建一个类的实例,类的具体对象。
方法:类中定义的函数。
对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
二、面向对象基本使用
1)创建类:
class Role(object): #创建一个类名是Role,object是新式类的写法 语法规定必须写
def __init__(self,name,role,weapon,lif_value):
self.name = name
self.role = role
self.weapon = weapon
self.lif_value = lif_value
class是关键字,表示类
创建对象,类名称后加括号即可
__init__()
方法是一种特殊的方法,被称为类的构造函数或初始化方法,当创建了这个类的实例时就会调用该方法,当类被调用的时候就自动执行这个函数
object是新式类 如果不加 直接是()是旧式类
如下:
class Role():
def __init(self,name,role):
self.name = name
self.role = role
案例:
#创建类 类名是Role
class Role(object):
def __init__(self,name,role,weapon,lif_value):
self.name = name
self.role = role
self.weapon = weapon
self.lif_value = lif_value
#self为特殊参数,必填
def buy_weapon(self,weapon):
print('用户%s 购买了%s'%(self.name,weapon))
self.weapon = weapon
def add_blood(self,lif_value):
print('用户%s 加了%s'%(self.name,lif_value))
self.lif_value = lif_value
#根据类创建对象P1 这个步骤就是属于实例化的过程
P1= Role('liuyao','aoteman','b11',100)
#执行类提供的buy_weapon方法
P1.buy_weapon("ak47")
#执行类提供的add_blood方法
P1.add_blood('100')
三、面向对象三大特性
1、封装
封装,顾名思义就是将内容封装到某个地方,以后再去调用被封装在某处的内容。
所以,在使用面向对象的封装特性时,需要:
1)将内容封装到某处
#创建一个类
class Role(object):
#构造方法
def __init__(self,name,age,job,salary):
self.name = name
self.age = age
self.job = job
self.salary = salary
#将变量封装到类里的name,age,job,salary里面
user1 = Role('liuyao','21','IT','1000')
user2 = Role('mayun','22','IT','2100')
self 是一个形式参数,当执行 user1 = Role('liuyao','21','IT','1000') 时,
self 等于user1, 当执行 user2 = Role('mayun','22','IT','2100') 时,
self 等于 user2
所以,内容其实被封装到了对象 obj1 和 obj2 中,
每个对象中都有 name,age,job,salary 属性
2)从某处调用
#创建一个类
class Role(object):
#构造方法
def __init__(self,name,age,job,salary):
self.name = name
self.age = age
self.job = job
self.salary = salary
#将变量封装到类里的name,age,job,salary里面
#实例化
user1 = Role('liuyao','21','IT','1000')
user2 = Role('mayun','22','IT','2100')
#调用name
print (user1.name)
#调用age
print (user1.age)
#调用name
print (user2.name)
#调用age
print (user2.age)
2.继承
继承,面向对象中的继承和现实生活中的继承相同,即:子可以继承父的内容
面向对象编程 (OOP) 语言的一个主要功能就是“继承”。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。
通过继承创建的新类称为“子类”或“派生类”。
被继承的类称为“基类”、“父类”或“超类”。
继承的过程,就是从一般到特殊的过程。
要实现继承,可以通过“继承”(Inheritance)和“组合”(Composition)来实现。
在某些 OOP 语言中,一个子类可以继承多个基类。但是一般情况下,一个子类只能有一个基类,要实现多重继承,可以通过多级继承来实现。
继承概念的实现方式有三类:实现继承、接口继承和可视继承。
Ø 实现继承是指使用基类的属性和方法而无需额外编码的能力;
Ø 接口继承是指仅使用属性和方法的名称、但是子类必须提供实现的能力;
Ø 可视继承是指子窗体(类)使用基窗体(类)的外观和实现代码的能力。
如果我们要分别为猫和狗创建一个类,那么就需要为 猫 和 狗 实现他们所有的功能,如下所示:
class 猫:
def 叫(self):
print '喵喵叫'
def 吃(self):
# do something
def 喝(self):
# do something
def 拉(self):
# do something
def 撒(self):
# do something
class 狗:
def 叫(self):
print 汪汪叫'
def 吃(self):
# do something
def 喝(self):
# do something
def 拉(self):
# do something
def 撒(self):
# do something
那么可以如下:
动物:吃、喝、拉、撒
猫:喵喵叫(猫继承动物的功能)
狗:汪汪叫(狗继承动物的功能)
代码:
class Animal:
def eat(self):
print "%s 吃 " %self.name
def drink(self):
print "%s 喝 " %self.name
def shit(self):
print "%s 拉 " %self.name
def pee(self):
print "%s 撒 " %self.name
class Cat(Animal):
def __init__(self, name):
self.name = name
self.breed = '猫'
def cry(self):
print '喵喵叫'
class Dog(Animal):
def __init__(self, name):
self.name = name
self.breed = '狗'
def cry(self):
print '汪汪叫'
所以,对于面向对象的继承来说,其实就是将多个类共有的方法提取到父类中,子类仅需继承父类而不必一一实现每个方法。
注:除了子类和父类的称谓,你可能看到过 派生类 和 基类 ,他们与子类和父类只是叫法不同而已。
#!/usr/bin/evn python3
class Animal:
def __init__(self,name):
self.name = name
def eat(self):
print ("%s 吃 " %self.name)
def drink(self):
print ("%s 喝 " %self.name)
class cat(Animal):
def __init__(self,name):
self.name = name
Cat =cat('猫')
#调用父类的方法
Cat.eat
3.多继承
Python的类如果继承了多个类,那么其寻找方法的方式有两种,分别是:深度优先和广度优先
当类是经典类时,多继承情况下,会按照深度优先方式查找
当类是新式类时,多继承情况下,会按照广度优先方式查找
经典类和新式类,从字面上可以看出一个老一个新,新的必然包含了跟多的功能,也是之后推荐的写法,从写法上区分的话,如果 当前类或者父类继承了object类,那么该类便是新式类,否则便是经典类。
#!/usr/bin/evn python3
class D:
def bar(self):
print ('D.bar')
class C(D):
pass
def bar(self):
print ('C.bar')
class B(D):
pass
def bar(self):
print ('B.bar')
class A(B, C):
pass
def bar(self):
print ('A.bar')
a = A()
# 执行bar方法时
# 首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,
# 则继续去D类中找,如果D类中么有,则继续去C类中找,如果还是未找到,则报错
# 所以,查找顺序:A --> B --> D --> C
# 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了
a.bar()
3.多态
多态性(polymorphisn)是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。
那么,多态的作用是什么呢?我们知道,封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类);它们的目的都是为了——代码重用。而多态则是为了实现另一个目的——接口重用!多态的作用,就是为了类在继承和派生的时候,保证使用“家谱”中任一类的实例的某一属性时的正确调用。
Pyhon不支持多态并且也用不到多态,多态的概念是应用于Java和C#这一类强类型语言中
class Animal:
def __init__(self, name):
self.name = name
def talk(self):
raise NotImplementedError("Subclass must implement abstract method")
class Cat(Animal):
def talk(self):
return '猫'
class Dog(Animal):
def talk(self):
return '狗'
animals = [Cat('Missy'),
Dog('Lassie')]
for animal in animals:
print (animal.name + ': ' + animal.talk())