Comparison is the thief of joy.
攀比是盗取快乐的贼
声明
仅作为个人学习使用,仅供参考
区分对象与类
小贝 喜欢 猫咪,今年领养了一只名叫 Kitty 的 布偶猫。则下列哪项是 对象 呢?
小贝 Kitty >对象
闻闻 更喜欢 犬科 动物,家里养了两只 萨摩耶犬,一只名叫 丁丁,另一只名叫 当当。则下列哪项是 类 呢?
犬科动物 萨摩耶犬 >类
因此
具体的是对象 具有抽象概念的是类
这两道题目中出现了 小贝 和 闻闻 这两位具体的人,提到了 Kitty、丁丁、当当 这三只具体的动物,他们都是 对象。这其中的人(Human)、猫咪(Cat)、布偶猫(Dagdoll)、萨摩耶(Samoyed)、犬科(Dog)几个 抽象概念 则是 类。
isinstance()函数
isinstance(object, classinfo)
参数
- object -- 实例对象。
- classinfo -- 可以是直接或间接类名、基本类型或者由它们组成的元组
接受两个参数 第一个参数是实例对象,第二次参数为某个类,检查实例对象是否是第二个参数的实例,返回 True 或 False
isinstance演示
class Dog:pass #定义类:狗
dingding = Dog() #dingding是一条狗
print(isinstance(dingding,Dog))
输出 True 即表示 dingding 是 Dog类 的实例对象
Dog
类中只包含一条 pass
语句,此时 pass
语句可以直接跟在 class xxx:
之后,
写成一行是一种简便写法
类的继承
class 子类名(父类名):
的方式实现类的继承
萨摩耶是狗的种类,丁丁是萨摩耶,那么丁丁是狗 非常缜密的逻辑推理
class Dog:pass
class Samoyed(Dog):pass
dingding = Samoyed() #dingding是萨摩耶
print(isinstance(dingding,Samoyed)) #dingding是萨摩耶
print(isinstance(dingding,Dog)) #那dingding 也是狗咯~
class 子类名(父类名):
的方式实现类的继承
class Samoyed(Dog):pass
即表示 Samoyed 是 Dog 的 子类 ,Dog是 Samoyed 的父类
Samoyed继承了 Dog类
即表示 是Samoyed类的 也一定是Dog类
那如果已知dingding是Dog类 用 isinstance() 判断是否是 Samoyed 类 ,当然会输出 False
这就是
继承 的第一个好处
它能够让 Python 理解 类 与 类 之间的范围关系(父类与子类)
子类调用父类方法
class Dog:
def run(self):
print('今天天气真好,让我想飞快的跑')
class Samoyed(Dog):pass
dingding = Samoyed()
dingding.run()
输出:今天天气真好,让我想飞快的跑
可以看到 run 函数定义在 Dog 父类里,dingding是子类 Samoyed 的实例
我们依然能够通过子类调用父类的方法
其实是 子类Samoyed 继承了 父类Dog 的所有属性与方法
Python 在执行到 dingding.run()
时,会先检查 dingding
自身类型 Samoyed
中有没有 run()
方法,发现没有,再去 Samoyed
的父类 Dog
中寻找 run()
方法。这时它找到了 run()
方法,就执行了。
这就是
继承 的第二个好处
当我们约定 A
类继承自 B
类后,子类 A
将 自动获得 B
类中定义的 所有属性与方法
再次强调一下 类中的属性与方法 就是 定义在类内的变量与def函数
多态
上文提到 因为 子类Samoyed 找不到 run 方法 就去 父类 Dog 找,找到了然后执行
那如果 子类Samoyed 有 run 方法呢 即存在与父类的同名方法呢?
这就是 多态
子类重写父类方法
子类与父类中有 相同名称的方法 但是执行的东西不一样,那么子类可以重写父类中的同名方法
class Dog:
def run(self):
print('今天天气真好,让我想飞快的跑')
class Samoyed(Dog):
def run(self):
print('今天天气真好,但是萨摩耶不想飞快的跑')
dingding = Samoyed()
dingding.run()
输出:今天天气真好,但是萨摩耶不想飞快的跑
输出发生了变化 ,是因为 子类Samoyed 也定义了run 方法
当 dingding 调用 run 方法 时候,run 方法 在子类中存在 就不去执行父类的 run 方法了
子类新增方法
给子类定义方法 不一定要与父类同名重写方法 ,你也可以定义新的方法
道理是一样的
继承 与 多态 的好处
它们的存在,让我们能够在 不改变犬科动物共性 前提下,为不同品种的狗狗赋予个性,使我们的代码结构清晰
继承 就是 子类与父类 相同的地方 || 多态 就是 子类与父类不同的地方
狼人杀项目
1.random.choice()的使用
2.对于roles = [Villager(), Prophet()]代码的解释
这行代码 分别创造了1个 Villager() 和 Prophet() 的实例,但是没有命名
3.为什么Villager().show_card()还是可以调用方法
有效,但并不推荐,但它确实做了以下几件事
创建实例:Villager() 调用了 Villager 类的构造函数,创建了一个新的 Villager 实例。
调用方法:紧接着,.show_card() 在这个新创建的实例上调用了 show_card 方法。
销毁实例:由于这个 Villager 实例没有被赋值给任何变量,因此在 show_card 方法执行完毕后,这个实例将变得不可达,随后Python的垃圾回收机制会将其回收。
就是说Villager().show_card()
确实既创造了Villager的实例又调用了show_card方法,但是一般只用于测试