类和对象
python
# 与其他支持面向对象的编程语言一样,
# 定义类使用 class 关键字
class Animal:
# 普通属性(类似其他编程语言的 public 修饰符)
name = None
# 私有属性(以__开头 类似其他编程语言的 private)
# 与其他面向对象不同的是: 没有 protected 修饰符
__age = 0
def __init__(self, name, kind):
# 构造方法
self.name = name
self.kind = kind
def __str__(self):
# 魔术方法 类似 js 的 toString,必须返回一个字符串
# 当对象被当成字符串使用时会自动调用
return f"{self.name} is a {self.kind}"
def eat(self, food):
# 普通方法(实例方法)
print(f"i am {self.name}, i like to eat {food}")
@property
def age(self):
# 访问器: 定义 getter
return self.__age
@age.setter
def age(self, age):
# 修改器: 定义 setter
# 你的 @property 修饰的属性名(age), 那么修改器的
# 名字就必须是 @age.setter
if age > 150:
print("设置失败, 你设置的年龄太大了")
else:
self.__age = age
def show_age(self):
# 利用普通方法来查看, 访问器设置器是否设置成功
# __age: 是在类的内部直接访问属性
# age: 是通过访问器来访问属性
print(f"查看年龄:__age = {self.__age}, age = {self.age}")
@classmethod
def is_animal(cls, obj):
# 类方法: 有 cls 参数但是没有 self 参数
# 可以访问到 Animal 这个类, 但是无法访问到实例
return isinstance(obj, cls)
@staticmethod
def breath():
# 静态方法: 没有 cls 参数也没有 self 参数
# 虽然是通过类来调用这个方法,
# 但是他和类并没有关系, 因为他无法访问
# 类中的任何属性和方法(也就是无法访问 self)
print("动物都需要呼吸")
# 实例化
tom = Animal("tom", "cat") # 给构造方法传值
# 魔术方法 __str__
print(f"toString: {tom}")
# 访问器(getter) 设置器(setter)
print(f"tom is {tom.age} years old")
tom.age = 22
tom.show_age()
# 普通方法
tom.eat("fish")
# 类方法
print("tom 是 Animal 的实例吗?", Animal.is_animal(tom))
print("123 是 Animal 的实例吗?", Animal.is_animal(123))
# 静态方法
# 注: 静态方法和类方法都是通过类名来调用的
Animal.breath()
装饰器
在 python 中 可以使用装饰器来定义类中不同类型的属性和方法
魔术方法
在 python 中有许多魔术方法来定义对象的行为, 比如对象被当做字符串时会自动调用 __str__
, 有的资料也将这些行为称之为 运算符重载
- __str__
- __add__
- __sub__
- __or__
- __getitem__
- __setitem__
- __len__
- __repr__
- __gt__
- __lt__
- __le__
- __ge__
- __eq__
- __ne__
- __contains__
继承
- 单继承: 子类只继承一个基类
- 多继承: 子类继承多个基类
py
# 动物类
class Animal:
def __init__(self, name):
self.name = name
def eat(self):
# 父类方法
print("动物都需要吃东西")
# 猫类
class Cat(Animal):
def catchMouse(self):
# 添加子类自己的方法
print("猫可以抓老鼠")
def eat(self):
# 重载父类的方法, 先调用父类的方法
super().eat();
print("猫吃鱼")
# 鱼类
class Fish(Animal):
def eat(self):
# 重载父类的方法, 不调用父类方法
print("鱼吃草")
def swim(self):
# 添加子类的方法
print("鱼会游泳")
tom = Cat("tom")
tom.eat()
tom.catchMouse()
print("="*20)
jerry = Fish("jerry")
jerry.eat()
jerry.swim()
py
class Phone:
def call(self):
print("手机可以打电话")
class Camera:
def take_photo(self):
print("照相机可以照相")
class RemoteController:
def control(self):
print("遥控器可以控制空调")
# 多继承
class XiaoMiPhone(Phone, Camera, RemoteController):
def ai_assistant(self):
print("小爱同学 AI 助手")
def control(self):
# 重载父类方法
print("手机可以控制空调")
xiaomi8 = XiaoMiPhone()
xiaomi8.call()
xiaomi8.take_photo()
xiaomi8.control()
xiaomi8.ai_assistant()
类型注解与多态
什么是类型注解? 为什么使用类型注解?
就如同 js 和 ts 的关系, 拥有类型注解可以获得更好的编码体验, 减少出错概率
python
class Animal:
def move(self):
print("动物可以移动")
class Cat(Animal):
def move(self):
print("猫在地上跑")
class Fish(Animal):
def move(self):
print("鱼在水里游")
# 多态: 猫在动,鱼在动 都可以理解为 动物在动
def run(animal: Animal):
animal.move()
animal = Animal()
cat = Cat()
fish = Fish()
run(animal)
run(cat)
run(fish)