面向对象(类编程)
简介:全称Object Oriented Programing(OOP) ,是一种程序设计思想,面向对象编程
面向对象名词简介
借鉴菜鸟教程
- 类(class):类事抽象的模板,用来描述具有相同属性和方法的对象的集合。定义了集合中每个对象所拥有的方法,对象是类的实例
- 方法:类中自定义的函数
- 类变量:类变量在整个实例化的对象中是公用的,每个对象都可以调用类变量。类变量定义在类中且函数体之外。类变量通常不作为实例变量使用
- 数据成员:类变量或者实例变量用于处理类及实例对象所使用的相关数据
- 方法重写:如果从父类继承的方法不能满足子类的需求,可以对齐进行重新,这个过程叫做方法的覆盖,也叫做方法的重写
- 局部变量:定义在方法中的变量,只作用与当前实例的类
- 实例变量:在类的声明中,属性是用变量来表示的。这种变量也叫做实例变量
- 继承:既一个派生类(同有的方法调用另一个类),继承基类(例如Person)的字段和方法。例如:A类和B类都需要调用相同的方法,既创建C类,把相同的方法放到C类,A类和B类继承C类,A类和B类就可以直接调用C类的方法了
- 实例化:创建一个类的实例,类的具体对象,例如:人类是一个类的集合,你不知道里边有谁谁谁,但是我如果说马云,你肯定就想到了他的身高,长相,money等等,这个过程也叫做实例化
- 对象:也叫做实例,通过类定义的数据结构实例,对象包括两个数据成员(类变量和实例变量)和方法,例如:你就知道人类,但是你不知道某个人,如果给这某个人来一个定义,他是马云,那么马云就是一个对象,它是人类的对象。
面向对象最重要的概念就是类(class)和实例(Instance),必须牢记类是抽象的模板,比如Student类,而实例是根据类创建出来的一个个具体的“对象”,每个对象都具有相同的方法,但各自的数据不同
类的相关知识
- 类名一共有三个作用:
- 可以调用类中的变量
Fruits.discount
- 实例化创建一个对象 Fruits('苹果',5)
- 调用一个方法(现在不常用):类名.方法名()
- 可以调用类中的变量
- 对象名
- 查看对象的属性 对象名.属性
- 调用对象的方法 对象名.方法名()
- 类和对象和实例和实例化
- 什么是类 ? Dog Person Fruits
- 什么是对象 ?
alex
二饼 旺财 苹果 李子 - 什么是实例 ? 对象就是实例
- 实例化 是一个动词 类创造实例的过程叫做实例化
- 对象 = 类名() 实例化
属性引用(类名.属性)
'''
class 类名:
'类的文档及字符串'
'类体'
'''
# 我们创建一个类
class Person:
pass
# 创建一个人类
class Person: # 创建一个Person类
role = 'person' # 人的属性都是人
def walk(self): # 人可以走路,定义一个方法
print("Person is walking...")
print(Person.role) # 查看人的属性
print(Person.walk) # 引用人的走路方法,注意这里不是调用,函数需要后面加括号,才算调用
实例化:(类名加括号就是实例化,会自动触发__init__
函数的运行,可以用它来为每个实例定义自己的特征)
# 创建一个人类
class Person: # 创建一个Person类
role = 'person' # 人的属性都是人
def __init__(self,name):
self.name = name # 每一个角色都有属于自己的名字
def walk(self): # 人可以走路,定义一个方法
print("Person is walking...")
print(Person.role) # 查看人的属性
print(Person.walk) # 引用人的走路方法,注意这里不是调用,函数需要后面加括号,才算调用
实例化的过程就是类-->对象的过程
原本我们只有一个Person类,但在这个过程中,产生了一个mhy
对象,他有自己的名字等等
语法:对象 = 类名(参数)
查看属性及调用方法
mhy = Person('mhy') # 类名()就等于执行Person.__init__
print(mhy.name) # 查看属性直接 对象名.属性名
print(Person.walk()) # 调用方法,对象名.方法名()
关于self
self:在实例化过程中自动将对象/实例本身传给__init__
函数的第一个参数,你也可以起别的名称,但是不要用,这是一种开发规范
类属性的补充:
一:我们定义的类的属性到底存到哪里了?有两种方式查看
dir(类名):查出的是一个名字列表
类名.__dict__:查出的是一个字典,key为属性名,value为属性值
二:特殊的类属性
print(Person.__name__) # 类的名字(字符串)
# 结果 Person
print(Person.__doc__) # 类的注释文档
# 结果 这是一个人类
print(Person.__base__) # 查看类的第一个父类(在讲继承时会讲)
# 结果
print(Person.__bases__) # 类所有父类构成的元组(在讲继承时会讲)
# 结果 (,)
print(Person.__dict__) # 类的字典属性
# 结果 {'__module__': '__main__', '__doc__': '这是一个人类', 'role': 'person', '__init__': , 'walk': }
print(Person.__module__) # 类定义所在的模块
# 结果 __main__
print(Person.__class__) # 实例对应的类(仅新式类中)
# 结果
例子:人狗大战
class Person: # 定义一个人类
role = 'person'
def __init__(self,name,hp,ad,sex,job):
self.username = name # 每一个角色都有自己的昵称;
self.hp = hp # 每一个角色都有自己的hp;
self.ad = ad # 每一个角色都有自己的攻击力;
self.sex = sex # 每一个角色都有自己的性别;
self.job = job # 每一个角色都有自己的职业;
def attack(self,dog): # 攻击狗的方法
# 人可以攻击狗,这里的狗也是一个对象。
# 人攻击狗,那么狗的生命值就会根据人的攻击力而下降
dog.hp -= self.ad
print('%s攻击了%s,%s掉了%s点血'%(self.username,dog.name,dog.name,self.ad))
class Dog: # 定义一个狗类
role = 'dog'
def __init__(self,name,kind,hp,ad): # 初始化方法
self.name = name # 每一只狗都有自己的昵称;
self.kind = kind # 每一只狗都有自己的品种;
self.hp = hp # 每一只狗都有自己的血量
self.ad = ad # # 每一只狗都有自己的攻击力
def bite(self,person): # 狗咬人的方法
# 狗可以咬人,这里的狗也是一个对象。
# 狗咬人,那么人的生命值就会根据狗的攻击力而下降
person.hp -= self.ad
print('%s咬了%s,%s掉了%s点血'%(self.name,person.username,person.username,self.ad)) # 谁在类的外部调用了这个方法,方法中的第一个self参数就是谁
alex = Person('alex',100,5,'不详','乞丐') # 实例化一个人对象
wangcan = Dog('旺财','teddy',2000,300) # 实例化一个狗 对象
erbing = Dog('二饼','哈士奇',10000,500) # 不同的对象
erbing.bite(alex) # Dog.bite(二饼,alex) # 狗对象调用狗的咬人方法攻击了人
print(alex.hp) # 查看人的血量
例子:求圆的面积及体积
from math import pi # 导入3.14
class Circle:
'''
定义了一个圆形类;
提供计算面积(area)和周长(perimeter)的方法
'''
def __init__(self,radius):
self.radius = radius
def area(self):
return pi * self.radius * self.radius
def perimeter(self):
return 2 * pi *self.radius
circle = Circle(10) #实例化一个圆
area1 = circle.area() #计算圆面积
per1 = circle.perimeter() #计算圆周长
print(area1,per1) #打印圆面积和周长
类命名空间与对象、实例的命名空间
创建一个类,就好创建一个类的名称空间,用来存储类中定义的名称,这些名称称之为类的属性
而类有两种属性:静态属性和动态属性
- 静态属性就是直接在类中的变量
- 动态属性就是定义在类中的方法
其中类的属性是共享给所有对象的
print(id(erbing.role))
47994208
print(id(Dog.role))
47994208
而类的动态属性是绑定到所有对象的
print(alex.attack)
print(Person.attack)
# 结果
>
创建一个对象/实例就会创建一个对象/实例的名称空间,存放对象/实例的名字,称为对象/实例的属性
例如:obj.name
会先在obj
自己的命名空间中查找name,查找不到则回去类里去找,类也找不到会去父类找..最后都找不到会抛出异常
组合用法
软件的重要用法除了继承之外还有另一种方式,既 组合
组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合
class arms:
def prick(self): # 这是该装备的主动技能,扎死对方
print('我靠 居然使用了无尽')
# obj.life_value -= 500 # 假设攻击力是500
class Person: # 定义一个人类
'''这是一个人类'''
role = 'person' # 人的角色属性都是人
def __init__(self, name):
self.name = name # 每一个角色都有自己的昵称;
self.arms = arms() # 给角色绑定一个武器;
mhy = Person('mhy')
mhy.arms.prick()
# mhy组合了一个武器的对象,可以直接mhy.arms来使用组合类中的所有方法
组合例子
圆环是由两个圆组成的,圆环的面积是外面圆的面积减去内部圆的面积。圆环的周长是内部圆的周长加上外部圆的周长。
这个时候,我们就首先实现一个圆形类,计算一个圆的周长和面积。然后在"环形类"中组合圆形的实例作为自己的属性来用
from math import pi
class Circle:
'''
定义一个圆形类,
提供计算面积(area)和周长(perimeter)的方法
'''
def __init__(self,radius):
self.radius = radius
def area(self):
'''计算圆形面积公式:πr²'''
return pi* self.radius * self.radius
def perimeter(self):
'''计算圆的周长公式:2πr'''
return 2 * pi * self.radius
ret_object = Circle(5) # 实例化一个圆
print(ret_object.area()) # 打印圆计算的面积
print(ret_object.perimeter()) # 打印圆计算的周长
class Ring:
'''
定义一个圆环类,
提供了圆环的面积和周长的方法
'''
def __init__(self,radius_outside,radius_inside):
self.radius_inside = Circle(radius_inside)
self.radius_outside = Circle(radius_outside)
def ring_area(self):
return self.radius_outside.area() - self.radius_inside.area()
def ring_perimeter(self):
return self.radius_outside.perimeter() + self.radius_inside.perimeter()
ring = Ring(10, 5) # 实例化一个圆环
print(ring.ring_area()) # 打印圆环计算的面积
print(ring.ring_perimeter()) # 打印圆环计算的周长
当类之间有显著不同,并且较小的类是较大的类所需要的组件时,用组合比较好
初识面向对象小结
定义一个人类
class Person: # 定义一个人类
role = 'person' # 人的角色属性都是人
def __init__(self, name, aggressivity, life_value, money):
self.name = name # 每一个角色都有自己的昵称;
self.aggressivity = aggressivity # 每一个角色都有自己的攻击力;
self.life_value = life_value # 每一个角色都有自己的生命值;
self.money = money
def attack(self,dog):
# 人可以攻击狗,这里的狗也是一个对象。
# 人攻击狗,那么狗的生命值就会根据人的攻击力而下降
dog.life_value -= self.aggressivity
定义一个狗类
class Dog: # 定义一个狗类
role = 'dog' # 狗的角色属性都是狗
def __init__(self, name, breed, aggressivity, life_value):
self.name = name # 每一只狗都有自己的昵称;
self.breed = breed # 每一只狗都有自己的品种;
self.aggressivity = aggressivity # 每一只狗都有自己的攻击力;
self.life_value = life_value # 每一只狗都有自己的生命值;
def bite(self,people):
# 狗可以咬人,这里的狗也是一个对象。
# 狗咬人,那么人的生命值就会根据狗的攻击力而下降
people.life_value -= self.aggressivity
创建一个武器类
class Weapon:
def __init__(self,name, price, aggrev, life_value):
self.name = name
self.price = price
self.aggrev = aggrev
self.life_value = life_value
def update(self, obj): #obj就是要带这个装备的人
obj.money -= self.price # 用这个武器的人花钱买所以对应的钱要减少
obj.aggressivity += self.aggrev # 带上这个装备可以让人增加攻击
obj.life_value += self.life_value # 带上这个装备可以让人增加生命值
def prick(self, obj): # 这是该装备的主动技能,扎死对方
obj.life_value -= 500 # 假设攻击力是500
测试交互
lance = Weapon('长矛',200,6,100)
egg = Person('egon',10,1000,600) #创造了一个实实在在的人egg
ha2 = Dog('二愣子','哈士奇',10,1000) #创造了一只实实在在的狗ha2
#egg独自力战"二愣子"深感吃力,决定穷毕生积蓄买一把武器
if egg.money > lance.price: #如果egg的钱比装备的价格多,可以买一把长矛
lance.update(egg) #egg花钱买了一个长矛防身,且自身属性得到了提高
egg.weapon = lance #egg装备上了长矛
print(egg.money,egg.life_value,egg.aggressivity)
print(ha2.life_value)
egg.attack(ha2) #egg打了ha2一下
print(ha2.life_value)
egg.weapon.prick(ha2) #发动武器技能
print(ha2.life_value) #ha2不敌狡猾的人类用武器取胜,血槽空了一半
继承
什么是继承
继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类
python中类的继承分为:单继承和多继承
class ParentClass1: #定义父类
pass
class ParentClass2: #定义父类
pass
class SubClass1(ParentClass1): #单继承,基类是ParentClass1,派生类是SubClass
pass
class SubClass2(ParentClass1,ParentClass2): #python支持多继承,用逗号分隔开多个继承的类
pass
提示:如果没有指定基类,python的类会默认继承object类,object是所有python类的基类,它提供了一些常见方法(如__str__
)的实现
>>> ParentClass1.__bases__
(,)
>>> ParentClass2.__bases__
(,)