python基础之面向对象1

时间:2023-12-17 09:18:38

一、面向对象VS面向过程

  1、面向过程

    python基础之面向对象1

  2、面向对象

  python基础之面向对象1

    python基础之面向对象1

二、类与对象

  1、类和对象

    (1)基本概念

      python基础之面向对象1

       python基础之面向对象1

    类和对象的内存图如下:

    python基础之面向对象1

    python基础之面向对象1

    python基础之面向对象1

  2、实例成员

    (1)实例变量

      python基础之面向对象1

    (2)实例方法:

      python基础之面向对象1

  3、类成员:

    (1)类变量

      python基础之面向对象1

     (2)类方法

        python基础之面向对象1

  4、静态方法:

    python基础之面向对象1

三、基本代码:

    

"""
面向对象:考虑问题,从对象的角度出发.
类:模板  抽象
对象:具体 
""" class Wife:
"""
老婆
""" # 1.数据成员 姓名 年龄 性别 ...
def __init__(self, name, age, sex):
# self "自己",调用当前方法的对象
print(id(self))
self.name = name
self.age = age
self.sex = sex # 2.方法成员 做饭 ...
def cooking(self):
print(id(self))
print(self.name + "做饭") # 创建对象(实例化)
# 调用 __init__(self,name,age,sex) 方法
w01 = Wife("丽丽", 21, "女")
print(id(w01))
# 调用对象的方法 w01 将自身传入方法
w01.cooking() w02 = Wife("芳芳", 22, "男")
w02.cooking()
print(id(w02)) # 在内存中,方法只有一份.而对象有多份.
"""
实例成员
""" # 创建实例成员,可以不在类中.(在实际项目中,仍然会在__init__方法中)
# class Wife01:
# pass
#
#
# w01 = Wife01()
# w01.name = "丽丽"
# print(w01.name)
# print(w01.__dict__)# 此时实例变量是:{'name': '莉莉'}
#
# w01 = Wife01()
# print(w01.__dict__) # 此时实例变量是:{} class Wife02:
def __init__(self,name):
self.name = name w01 = Wife02("丽丽")
w01.name = "莉莉"
print(w01.__dict__)# 此时实例变量是:{'name': '莉莉'}
print(w01.name) w01 = Wife02("丽丽")
print(w01.__dict__)# 此时实例变量是:{'name': '丽丽'} # 创建实例成员,可以不在__init__中.(在实际项目中,仍然会在__init__方法中)
class Wife03:
def __init__(self,name):
self.name = name def fun01(self):
self.age = 10
print("fun01执行喽") w01 = Wife03("丽丽")
# 通过对象调用实例方法,会自动传递对象地址.
w01.fun01()
# 通过类名调用实例方法,
Wife03.fun01(w01)
print(w01.age)
"""
类成员
"""
class ICBC:
"""
工商银行
"""
# 类变量 相当于被大家共享的"饮水机",
moneys = 9999999 # 类方法
@classmethod
def print_total_moneys(cls):
# print(ICBC.moneys)
print("总行金额:",cls.moneys) # 实例方法
def __init__(self,name,money):
# 实例变量:相当于每个人的"杯子"
self.money = money
self.name = name
# 从总行中,扣除当前支行的现金
ICBC.moneys -= money i01 = ICBC("广渠门支行",100000)
# 调用类变量
# print("总行金额:",ICBC.moneys)
# 调用类方法,此时会自动传递类名进入方法
ICBC.print_total_moneys() i02 = ICBC("磁器口支行",100000)
# print("总行金额:",ICBC.moneys)
ICBC.print_total_moneys()
"""
静态方法引入
00 01 02 03
10 11 12 13
20 21 22 23 需求:在某个元素基础上,获取每个方向,指定数量的元素.
10 向右     3    --> 11 12 13
21 向上     2    -->11 01
.....
""" class Vector2:
"""
向量
""" def __init__(self, x=0, y=0):
self.x = x
self.y = y # # 实例方法
# def fun01(self):
# pass
#
# # 类方法
# @classmethod
# def fun02(cls):
# pass
#
# # 静态方法:得不到对象地址/也得不到类名
# @staticmethod
# def fun03():
# pass # v01 = Vector2()
# v01.fun01()# 隐式传递对象地址
#
# Vector2.fun02()# 隐式传递类名
#
# Vector2.fun03() def right():
return Vector2(0,1) def up():
return Vector2(-1,0) # ... # 在某个元素基础上,获取每个方向,指定数量的元素.
def get_elements(list_target, v_pos, v_dir, count):
result = []
for i in range(count):
# 位置 += 方向
# 1 0 0 1 --> 1 1
# 1 1 0 1 1 2
# 1 2 0 1 1 3
v_pos.x += v_dir.x
v_pos.y += v_dir.y
result.append(list_target[v_pos.x][v_pos.y])
return result list01 = [
["", "", "", ""],
["", "", "", ""],
["", "", "", ""],
] # 10 向右     3    --> 11 12 13
# re01 = get_elements(list01,Vector2(1,0),Vector2(0,1),3)
# 21 向上     2    -->11 01
# re02 = get_elements(list01,Vector2(2,1),Vector2(-1,0),2) # 10 向右     3    --> 11 12 13
re01 = get_elements(list01,Vector2(1,0),right(),3)
print(re01)
re02 = get_elements(list01,Vector2(2,1),up(),2)
print(re02)

五、实例:

  练习1

  

"""
(1)学生student是一个类,具有姓名,年龄等数据;
具有学习study,工作work等行为。
对象:悟空同学,28岁。
八戒同学,29岁。 """
class Student:
"""
学生类
"""
def __init__(self,name,age):
self.name = name
self.age = age def study(self):
print(str(self.age) + "学习") def work(self):
print(self.name+"工作") # s01 悟空对象的地址
s01 = Student("悟空",28)
s02 = Student("八戒",29) # 通过对象地址,调用对象方法,会自动传递对象地址.
s01.study()
s02.work()

  练习2:

  

# 1. 在控制台中输入3个敌人,存入列表.
# 2. 将敌人列表输出(调用print_self)到控制台 class Enemy:
"""
敌人类
"""
def __init__(self,name='',hp=0,atk=0,atk_speed=0):
"""
构造函数
:param name: 敌人姓名
:param hp: 血量
:param atk: 攻击力
:param atk_speed:攻击速度
"""
self.name = name
self.hp = hp
self.atk = atk
self.atk_speed = atk_speed def print_self(self):
"""
打印对象
:return:
"""
print(self.name,self.hp,self.atk,self.atk_speed,sep='--') def input_control(msg):
"""
控制输入数据
:param msg: 提示信息
:return: 返回正确的录入值
"""
while True:
try:
return int(input(msg))
except:
print('输入有误!') def get_enemy_list(n):
"""
获取敌人列表
:param n: 敌人个数
:return: 敌人列表
"""
result_list = []
for i in range(n):
enemy = Enemy()
enemy.name = input('请输入姓名:')
enemy.hp = input_control('请输入血量')
enemy.atk = input_control('请输入攻击力')
enemy.atk_speed = input_control('请输入攻击速度')
result_list.append(enemy)
return result_list def get_enemy_by_name(name_value):
lst = []
for item in enemy_list:
if item.name == name_value:
lst.append(item)
for i in lst:
i.print_self() enemy_list = get_enemy_list(3)
for item in enemy_list:
item.print_self() get_enemy_by_name('张三')

  

  练习3:

"""
二维列表工具
""" class Vector2:
"""
向量
""" def __init__(self, x=0, y=0):
self.x = x
self.y = y # 将函数转移到类中,就是静态方法.
@staticmethod
def right():
return Vector2(0, 1) @staticmethod
def up():
return Vector2(-1, 0) @staticmethod
def left():
return Vector2(0, -1) @staticmethod
def down():
return Vector2(1, 0) @staticmethod
def right_up():
return Vector2(-1, 1) class DoubleListHelper:
"""
二维列表助手类
定义:在开发过程中,所有对二维列表的常用操作.
""" @staticmethod
def get_elements(list_target, v_pos, v_dir, count):
result = []
for i in range(count):
v_pos.x += v_dir.x
v_pos.y += v_dir.y
result.append(list_target[v_pos.x][v_pos.y])
return result # 测试.............
list01 = [
["", "", "", ""],
["", "", "", ""],
["", "", "", ""],
] # 10 向右     3    --> 11 12 13
re01 = DoubleListHelper.get_elements(list01, Vector2(1, 0), Vector2.right(), 3)
print(re01) # 练习1:在二维列表中,获取23位置,向左,3个元素.
re02 = DoubleListHelper.get_elements(list01, Vector2(2, 3), Vector2.left(), 3)
# 练习2:在二维列表中,获取02位置,向下,2个元素.
re02 = DoubleListHelper.get_elements(list01, Vector2(0, 2), Vector2.down(), 2)
# 练习3:在二维列表中,获取20位置,右上,2个元素.
re02 = DoubleListHelper.get_elements(list01, Vector2(2, 0), Vector2.right_up(), 2)
print(re02)

  练习4:

  

"""
练习: 对象计数器 
 创建老婆类(名字...),随意实例化对象.
   统计老婆数量(定义方法)
 画出内存图
""" class Wife:
# 计数器
count = 0 @classmethod
def get_count(cls):
return Wife.count def __init__(self,name):
# 实例变量
self.name = name
# 统计
Wife.count += 1 w01 = Wife("王超")
w02 = Wife("马汉")
# 通过类名,访问类方法
print(Wife.get_count())

  

    练习5:

      

"""
以面向对象的思想,描述下列场景.
提示:对象与对象数据不同,类与类行为不同.
  张三 教 李四 学习python
李四 教 张三  玩游戏
张三 工作 挣了8000元
李四 工作 挣了3000元
""" class Person:
def __init__(self, name):
# 人的姓名
self.name = name
# 人会的所有技能
self.__skills = []
self.__total_money = 0 # 只读属性
@property
def skills(self):
# return self.__skills # 返回可变对象地址,意味着类外仍然可以操作可变对象
return self.__skills[:] # 返回新的可变对象地址,意味着类外仍然操作的是新可变对象,不影响原对象.
# 备注:每次通过切片返回新对象,都会另外开辟空间创建新对象,占用过多内存. # 只读属性
@property
def total_money(self):
return self.__total_money @property
def name(self):
return self.__name @name.setter
def name(self,value):
self.__name = value def teach(self, person_other, str_skill):
# person_other 的技能列表,增加str_skill
person_other.__skills.append(str_skill)
print(self.name, "教了", person_other.name, str_skill) def work(self, money):
self.__total_money += money
print(self.name, "工作挣了", money, "元") zs = Person("张三")
ls = Person("李四")
# 张三 教 李四 学习python
zs.teach(ls, "python")
# 李四 教 张三  玩游戏
ls.teach(zs, "游戏") zs.work(8000)
ls.work(4000) #************************
zs = Person("张三")
# zs.skills = [] # 不能改
# 如果skills属性,返回的是__skills,那么仍然可以操作私有列表
# __skills[:],那么操作的是新列表
zs.skills.append("python")
print(zs.skills)

    练习6:

    

"""
创建技能类(技能名称,冷却时间,持续时间,攻击距离......)
要求:使用属性封装变量
创建技能列表(技能对象的列表)
-- 查找名称是"降龙十八掌"的技能对象
-- 查找名称是持续时间大于10秒的的所有技能对象
-- 查找攻击距离最远的技能对象
-- 按照持续时间,对列表升序排列.
""" class SkillData:
def __init__(self, name, cd, time, distance):
self.name = name
self.cd = cd
self.time = time
self.atk_distance = distance @property
def name(self):
return self.__name @name.setter
def name(self, value):
self.__name = value @property
def cd(self):
return self.__cd @cd.setter
def cd(self, value):
self.__cd = value @property
def time(self):
return self.__time @time.setter
def time(self, value):
self.__time = value @property
def atk_distance(self):
return self.__atk_distance @atk_distance.setter
def atk_distance(self, value):
self.__atk_distance = value def print_self(self):
print(self.name, self.cd, self.time, self.atk_distance) list_skills = [
SkillData("降龙十八掌", 60, 10, 5),
SkillData("如来神掌", 50, 5, 15),
SkillData("六脉神剑", 80, 20, 8),
SkillData("一阳指", 20, 50, 15),
SkillData("冷酷追击", 15, 30, 9),
] # -- 查找名称是"降龙十八掌"的技能对象
for item in list_skills:
if item.name == "降龙十八掌":
item.print_self() # -- 查找名称是持续时间大于10秒的的所有技能对象
result = []
for item in list_skills:
if item.time > 10:
result.append(item) # -- 查找攻击距离最远的技能对象
result = list_skills[0]
for i in range(1, len(list_skills)):
# 后面的技能对象
if result.atk_distance < list_skills[i].atk_distance:
result = list_skills[i]
# result.atk_distance = list_skills[i].atk_distance result.print_self() # -- 按照持续时间,对列表升序排列.
for r in range(len(list_skills) - 1):
for c in range(r + 1, len(list_skills)):
if list_skills[r].time > list_skills[c].time:
list_skills[r],list_skills[c] = list_skills[c],list_skills[r] # 请用调试,查看列表的取值.
print(list_skills)