python基础之面向对象1
一、面向对象VS面向过程
1、面向过程
2、面向对象
二、类与对象
1、类和对象
(1)基本概念
类和对象的内存图如下:
2、实例成员
(1)实例变量
(2)实例方法:
3、类成员:
(1)类变量
(2)类方法
4、静态方法:
三、基本代码:
""" 面向对象:考虑问题,从对象的角度出发. 类:模板 抽象 对象:具体 """ 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 = [ ["00", "01", "02", "03"], ["10", "11", "12", "13"], ["20", "21", "22", "23"], ] # 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 = [ ["00", "01", "02", "03"], ["10", "11", "12", "13"], ["20", "21", "22", "23"], ] # 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)