合抱之木,生于毫末;九层之台,起于累土;千里之行,始于足下。💪🏻
一、面向对象 ⭐️
(一)类和实例 🍭
1、类的定义 🍉
类的定义: 🦋
class
:表明这是一个类。ClassName
:类的名字。()
:父类集合的开始和结束。object
:父类的名字,定义的类继承自父类,可以不写,默认是object。object是所有类的直接或间接父类。
class ClassName(object):
<statement-1>
.
.
.
<statement-N>
2、类的实例化(创建对象) 🍉
实例名 = 类() 的方式实例化对象,为类创建一个实例
举例: 🌰
# 定义一个名为 Player 的类,继承自基类 object(Python 中所有类的默认基类)
class Player(object): # object 基类
pass # 使用 pass 表示这是一个空类,暂无属性和方法定义
# 创建 Player 类的实例(对象),命名为 tom
tom = Player() # 类的实例化(创建对象)
# 打印 tom 对象的类型(输出其所属的类)
print(type(tom)) # 输出:<class '__main__.Player'>
# 检查 tom 是否是 Player 类的实例,返回布尔值(True/False)
print(isinstance(tom, Player)) # 输出:True
# 检查 tom 是否是 object 类的实例(因为所有类都继承自 object)
print(isinstance(tom, object)) # 输出:True
输出结果: 👇🏻
<class '__main__.Player'>
True
True
3、实例(对象)属性 🍉
在
Python
中,实例(Instance
)就是对象(Object
)。
举例: 🌰
# 定义一个名为Player的类,继承自object基类(Python3中所有类默认继承object,可省略)
class Player(object):
# 定义初始化方法(构造函数),在创建对象时自动调用
# 参数说明:self指实例本身,name/age/city是创建对象时必须传入的参数
def __init__(self, name, age, city): # 初始化函数(构造函数)
# 将传入的参数赋值给实例属性
self.name = name # 创建name属性并赋值
self.age = age # 创建age属性并赋值
self.city = city # 创建city属性并赋值
# 创建Player类的实例mia,传入初始化参数
mia = Player('mia', 18, '上海') # 实例化对象,name='mia', age=18, city='上海'
# 修改mia实例的city属性
mia.city = '重庆' # 将city属性从'上海'改为'重庆'
# 打印mia实例的name、age和city属性
print(mia.name, mia.age, mia.city) # 输出:mia 18 重庆
# 创建另一个Player类的实例tom
tom = Player('tom', 19, '成都') # 实例化对象,name='tom', age=19, city='成都'
# 打印tom实例的name、age和city属性
print(tom.name, tom.age, tom.city) # 输出:tom 19 成都
# 给tom实例动态添加height属性(Python允许给实例动态添加新属性)
tom.height = 180 # 添加height属性并赋值为180
# 打印tom实例的所有属性和值(以字典形式返回)
print(tom.__dict__) # 输出:{'name': 'tom', 'age': 19, 'city': '成都', 'height': 180}
输出结果: 👇🏻
mia 18 重庆
tom 19 成都
{'name': 'tom', 'age': 19, 'city': '成都', 'height': 180}
4、类属性 🍉
举例: 🌰
# 定义一个名为Player的类,继承自object基类
class Player(object):
# 类属性(所有实例共享)
numbers = 0 # 类属性(一般用于统计或共享)
def __init__(self, name, age, city): # 初始化函数(构造函数)
# 实例属性(每个实例独有的属性)
self.name = name # 实例属性:玩家姓名
self.age = age # 实例属性:玩家年龄
self.city = city # 实例属性:玩家城市
# 每创建一个实例,类属性numbers加1
Player.numbers += 1 # 修改类属性,统计玩家数量
# 创建第一个Player实例mia
mia = Player('mia', 18, '上海') # 实例化,触发__init__方法
# 打印mia实例的所有实例属性(以字典形式)
print(mia.__dict__) # 输出:{'name': 'mia', 'age': 18, 'city': '上海'}
# 打印当前玩家数量(通过类属性访问)
print('欢迎第 %d 个玩家注册!' % Player.numbers) # 输出:欢迎第 1 个玩家注册!
# 创建第二个Player实例tom
tom = Player('tom', 19, '成都') # 实例化,触发__init__方法
# 打印tom实例的所有实例属性
print(tom.__dict__) # 输出:{'name': 'tom', 'age': 19, 'city': '成都'}
# 再次打印当前玩家数量(此时已增加为2)
print('欢迎第 %d 个玩家注册!' % Player.numbers) # 输出:欢迎第 2 个玩家注册!
输出结果: 👇🏻
{'name': 'mia', 'age': 18, 'city': '上海'}
欢迎第 1 个玩家注册!
{'name': 'tom', 'age': 19, 'city': '成都'}
欢迎第 2 个玩家注册!
(二)实例(对象)方法 🍭
举例: 🌰
# 定义一个Player类,继承自object基类(Python3中可省略)
class Player(object):
# 类属性(所有实例共享)
numbers = 0 # 用于统计玩家总数
levels = ['青铜','白银','黄金','钻石','王者'] # 所有可能的段位等级
def __init__(self, name, age, city, level): # 初始化方法(构造函数)
# 实例属性(每个玩家独有的属性)
self.name = name # 玩家姓名
self.age = age # 玩家年龄
self.city = city # 玩家所在城市
# 验证传入的段位是否合法
if level not in Player.levels:
raise Exception('段位设置错误!') # 如果段位不在预设列表中,抛出异常
else:
self.level = level # 如果合法,设置玩家段位
Player.numbers += 1 # 每创建一个玩家实例,总数加1
def show(self): # 实例方法:显示玩家信息
# 格式化输出玩家信息
print('我是第 %d 个玩家,我的名字是 %s,%d 岁,我来自 %s,我的段位是 %s' %
(Player.numbers, self.name, self.age, self.city, self.level))
def level_up(self): # 实例方法:段位升级
index1 = Player.levels.index(self.level) # 获取当前段位的索引
if index1 < len(Player.levels) - 1: # 如果不是最高段位
self.level = Player.levels[index1 + 1] # 升级到下一个段位
# 创建一个Player实例mia
mia = Player('mia',18,'成都','钻石') # 实例化一个钻石段位的玩家
# 调用show方法显示mia的信息
mia.show() # 输出:我是第1个玩家...
# 调用level_up方法让mia升级段位
mia.level_up() # 钻石→王者
# 再次显示mia的信息(段位已升级)
mia.show() # 输出:我是第1个玩家...段位是王者
输出结果: 👇🏻
我是第 1 个玩家,我的名字是 mia,18 岁,我来自 成都,我的段位是 钻石
我是第 1 个玩家,我的名字是 mia,18 岁,我来自 成都,我的段位是 王者
(三)类方法 🍭
举例: 🌰
# 定义一个Player类,继承自object基类(Python3中可省略)
class Player(object):
# 类属性(所有实例共享)
numbers = 0 # 用于统计玩家总数
levels = ['青铜', '白银', '黄金', '钻石', '王者'] # 所有可能的段位等级
def __init__(self, name, age, city, level): # 初始化方法(构造函数)
# 实例属性(每个玩家独有的属性)
self.name = name # 玩家姓名
self.age = age # 玩家年龄
self.city = city # 玩家所在城市
# 验证传入的段位是否合法
if level not in Player.levels:
raise Exception('段位设置错误!') # 如果段位不在预设列表中,抛出异常
else:
self.level = level # 如果合法,设置玩家段位
Player.numbers += 1 # 每创建一个玩家实例,总数加1
def show(self): # 实例方法:显示玩家信息
# 格式化输出玩家信息
print('我是第 %d 个玩家,我的名字是 %s,%d 岁,我来自 %s,我的段位是 %s' %
(Player.numbers, self.name, self.age, self.city, self.level))
@classmethod # 装饰器,声明这是一个类方法
def get_players(cls): # 类方法
# cls参数会自动传入当前类(这里是Player)
print('用户数量已经达到了 %d 人' % cls.numbers) # 访问类属性numbers
# 创建一个Player实例mia
mia = Player('mia', 18, '上海','青铜') # 实例化一个青铜段位的玩家
# 调用实例方法show()显示mia的信息
mia.show() # 输出:我是第1个玩家...
# 调用类方法get_players()显示当前玩家总数
Player.get_players() # 输出:用户数量已经达到了1人
输出结果: 👇🏻
我是第 1 个玩家,我的名字是 mia,18 岁,我来自 上海,我的段位是 青铜
用户数量已经达到了 1 人
(四)静态方法 🍭
举例: 🌰
# 定义一个Player类,继承自object基类(Python3中可省略)
class Player(object):
# 类属性(所有实例共享)
numbers = 0 # 用于统计玩家总数
levels = ['青铜', '白银', '黄金', '钻石', '王者'] # 所有可能的段位等级
def __init__(self, name, age, city, level): # 初始化方法(构造函数)
# 实例属性(每个玩家独有的属性)
self.name = name # 玩家姓名
self.age = age # 玩家年龄
self.city = city # 玩家所在城市
# 验证传入的段位是否合法
if level not in Player.levels:
raise Exception('段位设置错误!') # 如果段位不在预设列表中,抛出异常
else:
self.level = level # 如果合法,设置玩家段位
Player.numbers += 1 # 每创建一个玩家实例,总数加1
def show(self): # 实例方法:显示玩家信息
# 格式化输出玩家信息
print('我是第 %d 个玩家,我的名字是 %s,%d 岁,我来自 %s,我的段位是 %s' %
(Player.numbers, self.name, self.age, self.city, self.level))
@classmethod # 装饰器,声明这是一个类方法
def get_players(cls): # 类方法
# cls参数会自动传入当前类(这里是Player)
print('用户数量已经达到了 %d 人' % cls.numbers) # 访问类属性numbers
@staticmethod # 装饰器,声明这是一个静态方法
def isvalid(**kwargs): # 静态方法:验证玩家信息是否有效
# 检查年龄是否大于18岁
if kwargs['age'] > 18: # 如果年龄大于18
return True # 返回验证通过
else:
return False # 返回验证不通过
# 创建玩家信息字典
infos = {'name':'mia','age':12,'city':'北京','level':'白银'}
# 使用静态方法验证玩家信息
if Player.isvalid(**infos): # 如果验证通过(这里age=12会返回False)
mia = Player('mia',24,'北京','白银') # 创建玩家实例
else:
print('请检查') # 输出提示信息(实际会执行这行)
输出结果: 👇🏻
请检查
(五)面向对象的三大特征 🍭
1、继承 🍓
举例: 🌰
class Character: # 父类:游戏角色基类
def __init__(self, name, hp):
self.name = name
self.hp = hp # 生命值
def attack(self):
print(f"{self.name} 发动了普通攻击!")
class Warrior(Character): # 子类:战士(继承Character)
def __init__(self, name, hp, strength):
super().__init__(name, hp) # 调用父类的初始化方法
self.strength = strength # 新增属性:力量
# 重写父类方法
def attack(self):
print(f"{self.name} 用剑造成 {self.strength} 点伤害!")
class Mage(Character): # 子类:法师(继承Character)
def __init__(self, name, hp, magic_power):
super().__init__(name, hp)
self.magic_power = magic_power # 新增属性:法力值
# 新增子类特有方法
def cast_spell(self):
print(f"{self.name} 施放法术,消耗 {self.magic_power} 点法力!")
# 使用
warrior = Warrior("亚瑟", 100, 15)
mage = Mage("梅林", 80, 30)
warrior.attack() # 输出:亚瑟 用剑造成 15 点伤害!
mage.attack() # 输出:梅林 发动了普通攻击!(未重写时继承父类方法)
mage.cast_spell() # 输出:梅林 施放法术,消耗 30 点法力!
输出结果: 👇🏻
亚瑟 用剑造成 15 点伤害!
梅林 发动了普通攻击!
梅林 施放法术,消耗 30 点法力!
2、多态 🍓
多态的核心是:📚
- 同一方法名:不同类可以有相同名称的方法。
- 不同实现:每个类根据自己的需求实现该方法的不同行为。
- 统一调用:通过父类引用调用方法,实际执行的是子类的方法。
举例: 🌰
class Animal: # 父类
def make_sound(self):
pass # 抽象方法(Python中没有真正的抽象方法,这里用pass占位)
class Dog(Animal):
def make_sound(self): # 重写父类方法
print("汪汪汪!")
class Cat(Animal):
def make_sound(self): # 重写父类方法
print("喵喵喵!")
class Duck(Animal):
def make_sound(self): # 重写父类方法
print("嘎嘎嘎!")
# 多态的统一调用
def animal_sound(animal: Animal):
animal.make_sound() # 调用的是实际子类的方法
# 使用
dog = Dog()
cat = Cat()
duck = Duck()
animal_sound(dog) # 输出:汪汪汪!
animal_sound(cat) # 输出:喵喵喵!
animal_sound(duck) # 输出:嘎嘎嘎!
输出结果: 👇🏻
汪汪汪!
喵喵喵!
嘎嘎嘎!
3、封装 🍓
举例: 🌰
class BankAccount:
def __init__(self, account_holder, initial_balance):
# 使用单下划线前缀表示"受保护"的属性(约定俗成,非强制)
self._account_holder = account_holder
# 双下划线前缀会使Python进行名称修饰(name mangling),实现"私有"效果
self.__balance = initial_balance
# 公开的接口方法
def deposit(self, amount):
if amount > 0:
self.__balance += amount
print(f"存款成功,当前余额: {self.__balance}")
else:
print("存款金额必须大于0")
def withdraw(self, amount):
if 0 < amount <= self.__balance:
self.__balance -= amount
print(f"取款成功,当前余额: {self.__balance}")
else:
print("无效的取款金额")
def get_balance(self):
return self.__balance
# 使用示例
account = BankAccount("张三", 1000)
account.deposit(500) # 存款成功,当前余额: 1500
account.withdraw(200) # 取款成功,当前余额: 1300
print(account.get_balance()) # 1300
# 尝试直接访问私有属性(不建议这样做)
print(account._BankAccount__balance) # 1300(通过名称修饰仍可访问)
输出结果: 👇🏻
存款成功,当前余额: 1500
取款成功,当前余额: 1300
1300
1300