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)

 

 

 

    

posted @ 2019-04-14 14:28  一如年少模样  阅读(355)  评论(0编辑  收藏  举报