Python面向对象基础
一、面向过程和面向对象
-
面向过程:面向过程的程序设计的核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西。
优点:极大的降低了写程序的复杂度,只需要顺着要执行的步骤,堆叠代码即可。
缺点:一套流水线或者流程就是用来解决一个问题,代码牵一发而动全身。
-
面向对象:面向对象的程序设计的核心是对象,要理解对象为何物,必须把自己当成上帝,上帝眼里世间存在的万物皆为对象,不存在的也可以创造出来。
优点:解决了程序的扩展性。对某一个对象单独修改,会立刻反映到整个体系中,如对游戏中一个人物参数的特征和技能修改都很容易。
缺点:可控性差,无法向面向过程的程序设计流水线式的可以很精准的预测问题的处理流程与结果,面向对象的程序一旦开始就由对象之间的交互解决问题,即便是上帝也无法预测最终结果。
简单理解面向对象:就拿设计西游记来举个例子。如来佛祖要解决的问题是想把经书传给东土大唐,如来考虑到解决这件事情需要4个人即孙悟空,猪八戒,沙僧,唐僧,他们四个人就对应面向对象中的对象。而作为取经人他们也有各自不同的特征和技能,这里的特征和技能就对应这对象的属性和方法。在取经途中,如来为了玩的更happy一点,就安排了一群妖魔鬼怪去阻拦他们取经,然后又觉得难度太大,接着安排了一群神仙去保驾护航,这里面的妖魔鬼怪和神仙都是面向对象中的对象。如来他不看重师徒四人怎么去取经这个过程,他只看重完成取经送到东土大唐这个结果。
二、类和对象
- 类:就是具有相同属性和功能的一类事物。
- 对象:就是类的具体表现。
具体一些:
- 猫是一类,你养的那只猫就是猫的一个对象
- 狗是一类,隔壁天天拆家的二哈也是狗的一个对象
类的结构:类的结构从大方向来说就分为两部分:1、静态变量 2、动态方法
class Human:
# 第一部分:静态变量、静态属性、静态字段
culture = "有文化"
mind = "有思想"
# 第二部分:动态方法、动态变量
def work(self):
print("人类会工作")
# class 是关键字与def用法相同,定义一个类。
# Human是此类的类名,类名使用驼峰(CamelCase)命名风格,首字母大写,私有类可用一个下划线开头。
三、从类名的角度探讨类
-
类名操作静态属性
-
类名.__dict__:查看类中所有的内容
class Human: culture = "有文化" mind = "有思想" def work(self): print("人类会工作") print(Human.__dict__) ''' {'__module__': '__main__', 'culture': '有文化', 'mind': '有思想', 'work': <function Human.work at 0x000001C6D70E9BF8>, '__dict__': <attribute '__dict__' of 'Human' objects>, '__weakref__': <attribute '__weakref__' of 'Human' objects>, '__doc__': None} ''' print(Human.__dict__["culture"]) # 有文化 # 注意:使用__dict__只能对类中的内容进行查操作,而不能进行增删改
-
类名.静态变量
class Human: culture = "有文化" mind = "有思想" def work(self): print("人类会工作") print(Human.mind) # 查 Human.culture = "没文化" # 改 Human.language = "多样化语言" # 增 del Human.culture # 删 print(Human.__dict__) # 通过万能的点,可以对类中的单个属性进行增删改查操作
总结:如果想查看类中的所有内容,使用__dict__方法。如果想对类中的某个单一的属性进行增删改查操作,是可以使用万能的"点"进行操作。
-
-
类名操作动态方法
__dict__["work"](111):没什么卵用,也基本上没什么人会用类名去操作动态方法。
四、从对象的角度探讨类
-
对象的实例化
对象是从类中出来的,只要是类名加上(),这就是一个实例化过程,这个就会实例化一个对象。
class Human: culture = "有文化" mind = "有思想" def __init__(self, name, age): self.name = name self.age = age print(self) def work(self): print("人类会工作") person = Human("dogfa", 18) # 实例化了一个对象person,只要实例化对象,它就会自动执行__init__()方法 print(person) # <__main__.Human object at 0x000002B0EBFB7B00> # <__main__.Human object at 0x000002B0EBFB7B00> # 打印person和__init__()中的self发现内存地址是一样的,说明它们是同一个对象
实例化对象过程中发生了三件事:
- 在内存中开辟了一个对象的内存空间
- 自动执行__init__()方法,并将对象本身的内存地址传递给了__init__()中第一个位置参数self
- 在__init__()中通过self给对象内存空间中添加属性
-
对象操作对象空间中的属性
-
对象.__dict__:查询对象中所有的属性
class Human: culture = "有文化" mind = "有思想" def __init__(self, name, age): self.name = name self.age = age def work(self): print("人类会工作") person = Human("dogfa", 18) print(person.__dict__) # {'name': 'dogfa', 'age': 18}
-
对象.属性
class Human: culture = "有文化" mind = "有思想" def __init__(self, name, age): self.name = name self.age = age def work(self): print("人类会工作") person = Human("dogfa", 18) person.gender = "男" # 增 del person.age # 删 person.name = "oldniu" # 改 print(person.name) # 查 print(person.__dict__) # oldniu # {'name': 'oldniu', 'gender': '男'}
-
-
对象操作类空间中的属性
class Human: culture = "有文化" mind = "有思想" def __init__(self, name, age): self.name = name self.age = age def work(self): print("人类会工作") person = Human("dogfa", 18) print(person.culture) # 有文化 print(person.mind) # 有思想 # 对象只能查看类中的属性,不能对类中的属性进行增删改操作 # 尝试修改类中的静态属性 person.culture = "没文化" print(Human.__dict__) # 打印类中的全部内容 '''{'__module__': '__main__', 'culture': '有文化', 'mind': '有思想', '__init__': <function Human.__init__ at 0x000001C230149BF8>, 'work': <function Human.work at 0x000001C230149AE8>, '__dict__': <attribute '__dict__' of 'Human' objects>, '__weakref__': <attribute '__weakref__' of 'Human' objects>, '__doc__': None}''' print(person.__dict__) # 打印对象空间中的全部内容 # {'name': 'dogfa', 'age': 18, 'culture': '没文化'} # 最后我们发现,类中的属性并没有被修改,而是在对象本身内存空间新增加了一个属性,由此推出对象不能对类中的属性进行增删改操作
-
对象操作类空间中的方法
class Human: culture = "有文化" mind = "有思想" def __init__(self, name, age): self.name = name self.age = age def work(self): print("人类会工作") def tools(self): print("人类会使用工具") person = Human("dogfa", 18) person.work() person.tools() # 类中的方法一般都是通过对象执行的(除去类方法,静态方法外),并且对象执行这些方法都会自动将对象空间传给方法中的第一个参数self。
五、类的空间问题
-
何处可以添加对象属性
# 何处可以添加对象属性 class A: def __init__(self, name): self.name = name def func(self, age): self.age = age # 1、在__init__()方法里添加 # 2、在类外面添加 obj = A("dogfa") obj.gender = "男" print(obj.__dict__) # {'name': 'dogfa', 'gender': '男'} # 3、在类内部添加 obj = A("dogfa") obj.func(18) print(obj.__dict__) # {'name': 'dogfa', 'gender': '男', 'age': 18}
总结:对象的属性不仅可以在__init__里面添加,还可以在类的其他方法或者类的外面添加。
-
何处可以添加类的静态属性
# 何处可以添加类的静态属性 class A: def func(self): A.age = self A.name = "dogfa" A.func(18) print(A.__dict__)
总结:类的静态属性不仅可以在类外部添加,还可以在类的内部添加。
-
对象如何找到类的属性
- 对象查找属性的顺序:先从对象本身内存空间查找 --> 再从类的内存空间中查找 --> 再从父类内存空间中查找
- 类查找属性的顺序:先从类本身的内存空间中查找 --> 再从父类内存空间中查找
注意:
- 以上流程都是单向不可逆的
- 类不可能找到对象的属性
- 对象之间是相互独立的
六、类与类的组合关系
组合:将一个类的对象封装到另一个类的对象的属性当中,就叫组合。
class Person:
def __init__(self, name, aggressivity, life_value):
self.name = name
self.aggressivity = aggressivity
self.life_value = life_value
# 不装备武器攻击
def fight(self, p):
'''
不装备武器进行攻击
:param p:攻击发起者
'''
p.life_value = p.life_value - self.aggressivity
print("{0}不带装备攻击了{1}一下,{1}掉了{2}hp,还剩{3}hp".format(self.name, p.name, self.aggressivity, p.life_value))
# 装备武器
def equip_weapon(self, weapon):
self.weapon = weapon # 组合:给Person类对象封装一个Weapon类的对象的属性
class Weapon:
def __init__(self, name, aggressivity):
self.name = name
self.aggressivity = aggressivity
# 使用武器进行攻击
def weapon_attack(self, p1, p2):
'''
使用武器进行攻击
:param p1: 攻击的发起者
:param p2: 攻击的承受者
'''
p2.life_value = p2.life_value - self.aggressivity
print("{0}装备了{1}攻击了{2},{2}掉了{3}hp,还剩{4}hp".format(p1.name, self.name, p2.name, self.aggressivity, p2.life_value))
# 实例化两个铁憨憨对象
p1 = Person("盲僧", 100, 800)
p2 = Person("剑圣", 60, 1200)
# 实例化两把武器
w1 = Weapon("黑色切割者", 200)
w2 = Weapon("无尽之刃", 400)
# 盲仔不装备武器打了剑圣一哈
p1.fight(p2)
# 输出:盲僧不带装备攻击了剑圣一下,剑圣掉了100hp,还剩1100hp
# 剑圣不装备武器打了回去
p2.fight(p1)
# 输出:剑圣不带装备攻击了盲僧一下,盲僧掉了60hp,还剩740hp
# 盲仔有钱了买了一把黑切再去找剑圣单挑
p1.equip_weapon(w1)
# 盲仔装备了黑切打了剑圣一下
p1.weapon.weapon_attack(p1, p2)
# 输出:盲僧装备了黑色切割者攻击了剑圣,剑圣掉了200hp,还剩900hp
# 剑圣也有钱了买了一把无尽干好偶遇盲仔
p2.equip_weapon(w2)
# 剑圣用无尽看了盲仔一刀
p2.weapon.weapon_attack(p2, p1)
# 输出:剑圣装备了无尽之刃攻击了盲僧,盲僧掉了400hp,还剩340hp