什么是面向对象?
面向对象指的是一门编程的思想,python中一切皆对象。
面向过程 VS 面向对象
- 面向过程编程:
核心是 “过程” 二字,过程指的是做事情的步骤,即先做什么再做什么,
基于该编程思想写程序,就好比一个工厂流水线,一种机械式的思维方式
优点:逻辑清晰,复杂的问题简单化
缺点:可扩展性差
- 面向对象编程:
核心是 “对象” 二字,对象指的是特征和技能的结合体
基于该编程思想写程序,就好比在创造世界,一种上帝式的思维方式
优点:可扩展性高
缺点:编写程序复杂程度高
那么我们在编程的时候优先使用 面向过程思想 呢?还是面向对象思想呢?
通常是两者结合在一起使用
类与对象定义
对象:特征和技能的结合体
类:一系列对象相同的特征和技能的结合体
在现实生活中 先有一个一个对象,然后再有人们对类的概念,
在程序中 必须定义好类,然后调用类来创造对象
定义类:
class 类名
相同的特征
相同的技能
class Stut: # 类名,遵循驼峰体命名规范,首字母大写
# 特征
school = "oldboy"
# 技能
def learn(self):
print("learning...")
定义类发生的两件事情
- 生成一个空的名称空间
- 把类内部所有名字,扔进类的名称空间中
- 注意:类在定义阶段产生好了名称空间,执行py文件时候会执行类内部的代码
创建对象
语法:类名 + () 调用产生对象
-------类调用-------
# 在我们定义好类之后,我们可以调用类的属性和方法
print(Stut.__dict__.get("school")) # 类名.__dict__获取类内部全部属性
Stut.learn(123) # 使用Stut的learn方法,此时由类来调用类内部的函数,该函数只是一个普通的函数,类内部learn函数有一个形参,那么在调用的时候也必须传一个参数才能调用
-------对象调用-------
s1 = Stut() # s1 -》 <__main__.Stut object at 0x0000000009FA9DD8>
#在我们实例化类 创建出来一个s1对象之后,我们可以使用对象.属性来调用
print(s1.school)
s1.learn() # 由对象来调用类内部的方法,self即对象本身,作为第一个参数传入。
创建对象(即调用类) 发生的三件事情
- 生成一个空的对象空间,
- 会自动触发类内部的 __init__函数
- 会把创建的对象本身以及调用类传入的参数一并传入给 init 函数
class OldboyStudend:
"""学生类"""
# 给不同对象添加不同特征的方式二:
def __init__(self,name,age,sex):
# self 就是创建出来的对象本身,对象.属性 可以获取不同对象的属性
self.name = name
self.age = age
self.sex = sex
print("调用类就运行__init__函数",name,age,sex)
school = "oldboy"
def learn(self):
print("正在learn...")
def chooice_course(self):
print("正在chooice_course...")
# print(OldboyStudend.__dict__.get("school"))
s1 = OldboyStudend("qinyj",21,"男") # 创建出一个 名 s1的对象
s2 = OldboyStudend("jack",22,"男") # 创建出一个 名 s2的对象
print(s1.school) # 调用类的特征
print(s2.school) # 调用类的特征
'''
问题:不同的对象特征技能一样,如何能不一样
解决:两种方式:
- 在类内部定义 __init__ 函数
- 创建出对象后单独添加属性
'''
# 给不同对象添加不同特征的方式一:
s1.name = "qinyj"
s1.age = "21"
s1.sex = "female"
s2.name = "jack"
s2.age = "22"
s2.sex = "female"
print(s1.name,s1.age,s1.sex)
print(s2.name,s2.age,s2.sex)
对象与类的查找顺序
对象中属性的查找顺序:
- 对象.属性 若对象本身有,则优先查找对象自己的
- 若对象本身没有,则去类里面找
- 若类没有,则报错
class OldboyStend:
SCHOOL = "oldboy"
NAME = "DDDDDDDD"
def __init__(self,name,age,sex,school):
self.name = name
self.age = age
self.sex = sex
self.SCHOOL = school
s1 = OldboyStend("qinyj",22,"男","oldgirl")
print(s1.SCHOOL)
# oldgirl
print(s1.NAME)
# DDDDDDDD
对象绑定方法
类内部的函数主要是给对象用的
- 类来调用类内部的函数,这时候这个函数就是一个普通的函数,这个函数有一个形参,调用的时候必须传入几个参数
- 对象来调用类内部的函数 称之为对象的绑定方法,不同的对象调用该绑定方法,则会将不同的对象传入该绑定方法中
- 对象的绑定方法 是由对象来调用的,特殊之处就是把对象当做第一个参数传入该方法中
class OldboyStend:
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
def learn(self):
print(f"{self.name} 正在learn...")
s1 = OldboyStend("qinyj",22,"男")
s1.learn()
# qinyj 正在learn...
print(s1.learn) # bound method 称之为对象的绑定方法 不再是一个普通的函数了
# <bound method OldboyStend.learn of <__main__.OldboyStend object at 0x000000000296C400>>
实战-人狗大作战
'''
需求:
人 对象
狗 对象
人狗互咬,如果一方生命值为0,则该程序就结束
定义两个类:
人类
狗类
'''
class People:
def __init__(self,name,damage,life):
# 对象特有的特征
self.name = name
self.damage = damage
self.life = life
# 人咬狗 技能
def bite(self,dog):
if dog.life <= 0:
return True
if self.life == 0:
print(f"{self.name} 死了,{dog.name} 赢了")
return
dog.life -= self.damage
print(f'''
人:[{self.name}] 开始咬狗:[{dog.name}]
狗掉血:[{self.damage}]
狗剩余血量:[{dog.life}]
''')
class Dog:
def __init__(self,name,damage,life):
# 对象特有的特征
self.name = name
self.damage = damage
self.life = life
# 狗咬人 技能
def bite(self, people):
if people.life <= 0:
return True
if self.life == 0:
print(f"{self.name} 死了,{people.name} 赢了")
return
people.life -= self.damage
print(f'''
狗:[{self.name}] 开始咬人:[{people.name}]
人掉血:[{self.damage}]
人剩余血量:[{people.life}]
''')
people = People("qinyj",200,1000)
dog = Dog("哈士奇",500,400)
while True:
flg1 = people.bite(dog)
if flg1:
break
flg2 = dog.bite(people)
if flg2:
break
终端打印结果:
人:[qinyj] 开始咬狗:[哈士奇]
狗掉血:[200]
狗剩余血量:[200]
狗:[哈士奇] 开始咬人:[qinyj]
人掉血:[500]
人剩余血量:[500]
人:[qinyj] 开始咬狗:[哈士奇]
狗掉血:[200]
狗剩余血量:[0]
哈士奇 死了,qinyj 赢了