面向对象

一、面向对象基本概念

  1、面向对象编程:oop

  2、面向过程:根据需求将某些独立功能封装为一个又一个函数,最后完成的代码,就是顺序地调用不同函数

  3、面向对象:相比较函数,面向对象就是更大的封装,根据职责在一个对象中封装多个方法,根据职责确定不同对象,在对象内部封装不同方法。

 

二、类 和 对象(面向对象中最重要的两个内容)

  1、类:是对具有相同特征或者行为的事物的一个统称,是抽象的,不能直接使用。(指代多个事物,由 class 关键字定义)

      特征(静态)--- 属性

      行为(动态)--- 方法

  2、对象:是由类创建出来的一个具体存在的事物,可以直接使用。(指代一个具体事物,代码中使用 类 区创建实例化)

     是由哪一个类创建出来的对象,就拥有在哪一个类中定义的属性和方法

  3、类的构成

     类的三要素:

      类名(多个事物起的名字,满足大驼峰命名法,所有单词首字母大写)

      属性(事物的特征)

      方法(事物的行为)

 三、面向对象代码的步骤

  1、设计类(找类的三要素)

  2、定义类

  3、创建对象(实例化对象)

  4、由对象调用类中方法

四、类的设计

  1、类的设计:就是找三要素,属性、方法 可能会很多,需要找到关注的即可

  2、类名的提取:使用名词提炼法分析整个业务流程,得出的名词通常就是类名

 

五、面向对象的基本语法

  1、定义类

class Person:    #Person为类名
    def func(self):    #func为方法名,本质为函数
        pass    

  2、创建对象(实例化对象)

    在代码中,对象由类对象

    类名()   #就是创建对象,一般使用变量将创建的对象保存起来

    变量 = 类名()   一般将这个变量称为对象,变量中保存的是对象的引用地址

  3、调用类中的方法

    由类创建的对象,可调用类中的方法

      对象 . 方法名()

class Cat:
    def eat(self):
        print("小猫爱吃鱼")
    def drink(self):
        print("小猫要喝水")
#创建对象并实例化
tom = Cat()     #以变量接收对象
#调用
tom.eat()
tom.drink()

 

六、属性和方法

  1、属性的使用

    属性表示事物特征

    可以给对象添加属性,或者获取对象属性值

    给对象添加属性:对象 . 属性名 = 属性值    #添加或者修改

    获取对象属性值:对象 . 属性名

    方法中添加属性名: self . 属性名 = 属性值

    例子:在外部添加属性名

class Cat:
    def eat(self):
        print(f"{self.name}小猫爱吃鱼")
    def drink(self):
        print(f"{self.name}小猫要喝水")
#创建对象并实例化
tom = Cat()     #以变量接收对象
tom.name = '唐木木'    #给tom对象添加属性值
#调用
tom.eat()
tom.drink()

  2、属性(魔法方法)

    在Python中存在一类方法,以两个下划线开头,两个下划线结尾,在满足某个条件的情况下,会自动调用。这类方法称为魔法方法

    1、初始化方法:__init__

      调用时机:创建对象后会自动调用

      应用场景:初始化对象,给对象添加属性

      例子

class Cat:
    def __init__(self):
        print("我是init,我已经调用")
        self.name = "Tom"
    def eat(self):
        print(f"{self.name}小猫爱吃鱼")
    def drink(self):
        print(f"{self.name}小猫要喝水")
#创建对象并实例化
tom = Cat()     #以变量接收对象,此时执行init方法
b = tom #此时不会执行init,这只是引用,不是创建对象####只有加括号的才是创建对象

    

    2、__str__ 方法

      调用方法:使用print(对象),打印对象的时候,会自动调用

           如果没有 str 方法,默认打印的是对象的引用地址

           如果定义 str 方法,打印的是方法的返回值

      应用场景:使用print(对象),打印输出对象的属性信息

      注意:必须返回一个 字符串

      例子

class Cat:
    def __init__(self,name,age):
        #创建添加属性
        self.name = name
        self.age = age
    def __str__(self):
        return f"姓名:{self.name},年龄:{self.age}"
#创建对象并实例化
tom = Cat("Tom",12)     #以变量接收对象,此时执行init方法
print(tom)    #<__main__.Cat object at 0x0000012EDDBF92B0>(无str方法时)
#姓名:Tom,年龄:12 (有str方法时)

    

  3、dir() 函数

    可以查看对象内的 所有属性及方法

    不具有输出功能,需要配合 print 连用

class Cat:
    def __init__(self, name, age):
        # 创建添加属性
        self.name = name
        self.age = age
    def eat(self):
        print(f"{self.name}小猫爱吃鱼")
    def drink(self):
        print(f"{self.name}小猫要喝水")

if __name__ == "__main__":
#创建对象并实例化
    tom = Cat("Tom",12)     #以变量接收对象,此时执行init方法
    print(dir(tom))   #<__main__.Cat object at 0x0000012EDDBF92B0>(无str方法时)
#姓名:Tom,年龄:12 (有str方法时)

 

七、面向对象的案例

  封装案例

class Person:
    def __init__(self, name, weight):
        # 创建添加属性
        self.name = name
        self.weight = weight
    def __str__(self):
        return f"{self.name} 目前体重为 {self.weight}"
    def run(self):
        #体重减少0.5kg
        self.weight -= 0.5
        print(f"{self.name} 跑步了,体重减少0.5kg")
    def eat(self):
        #体重增加1kg
        self.weight += 1
        print(f"{self.name} 跑步了,体重增加1kg")
if __name__ == "__main__":
    #创建对象并实例化
    xiaoming = Person("小明",12)
    xiaomei = Person("小美",30)
    print(xiaoming)
    print(xiaomei)
    xiaomei.run()
    xiaoming.eat()

 

  家具、房子案例

class HouseItem:
    '''家具类'''
    def __init__(self, name, area):
        self.name = name
        self.area = area
    def __str__(self):
        return f"{self.name} 占地面积 {self.area} 平方米"
class House:
    '''房子类'''
    def __init__(self,h_type,area):
        self.h_type = h_type
        self.area = area
        self.free_area = area
        self.item_list = []               #设置为空
    def __str__(self):
        return f"户型:{self.h_type} 面积:{self.area} 剩余面积:{self.free_area} 家具名称列表:{self.item_list}"

    def add_item(self,item):   #添加房子对象,添加家居对象
        #item为家具对象
        if self.free_area > item.area:        #将家居类的对象属性获取
            print(f"添加家具{item.name}")
            self.item_list.append(item.name)
            #修改剩余面积
            self.free_area -= item.area
        else:
            print("房子剩余面积不足")

if __name__ == "__main__":
    #创建家具
    bed = HouseItem("席梦思",4)
    chest = HouseItem("衣柜",2)
    print(bed)
    print(chest)
    #创建房子
    house = House("三室一厅",100)
    print(house)
    #添加家具
    house.add_item(bed)
    print(house)
    house.add_item(chest)
    print(house)

 

 八、面向对象的三大特征(继承、封装、多态)

  1、继承:如果多个类中存在相同的代码逻辑,则可考虑将相同逻辑的代码封装到父类中,在通过继承关系。直接实例化子类对象并调用父类中的方法即可。避免反复编写相同逻辑代码。

       在继承关系中,子类可以拥有并直接使用父类所有方法和属性

   案例:(继承具有传递性)(先在自己类中找,找到直接使用,没找到就去父类找,父类没找到就去父类的父类找。以下往上。直到找到object父类)

class Animal:
    '''动物类'''
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def eat(self):
        print(f"{self.name} 在吃饭")
    def sleep(self):
        print(f"{self.name} 在睡觉")

class Cat(Animal):          #此时继承Animal,Animal为父类
    '''猫类'''
    def catch(self):
        print(f"{self.name} 会抓老鼠")

class Dog(Animal):
    '''狗类'''
    def look_for_door(self):
        print(f"{self.name} 正在看门")

class XTQ(Dog):
    '''哮天犬'''
    def fly(self):
        print(f"{self.name} 在飞")

if __name__ == "__main__":
    ani = Animal("佩奇",3)
    ani.eat()    #佩奇 在吃饭

    cat = Cat("黑猫",4)           #此时Cat继承了Animal则可以使用父类的方法。如下
    cat.eat()          #黑猫 在吃饭
    cat.sleep()        #黑猫 在睡觉
    cat.catch()        #调用自己的方法。黑猫 会抓老鼠

    dog = Dog("旺财",5)
    dog.eat()

    xtq = XTQ("哮天犬",100)     #继承了Animal,Dog可同时使用他们的方法
    xtq.look_for_door()
    xtq.eat()

 

  2、重写

    定义:在子类中定义了和父类中一样的方法

    为什么要重写:父类中的方法不能满足子类对象的需要

    方式:

      覆盖式重写:父类中的代码功能全部不要(直接在子类中定义和父类中方法名字一样的方法接口,直接重新写新的代码)

class Dog:
    def bark(self):
        print("汪汪叫")

class XTQ(Dog):
    '''覆盖父类方法'''
    def bark(self):
        print("嗷嗷叫")

if __name__ == "__main__":
    xtq = XTQ()
    xtq.bark()          #嗷嗷叫

      

      扩展式重写:保留父类中的功能,在此基础上添加新功能(在子类代码中使用 super() . 方法名() 调用父类中的新功能,然后再写新功能)

class Dog:
    def bark(self):
        print("汪汪叫")

class XTQ(Dog):
    '''覆盖父类方法'''
    def bark(self):
        #调用父类功能
        super().bark()    #先调用父类中的方法
        print("嗷嗷叫")

if __name__ == "__main__":
    xtq = XTQ()
    xtq.bark()          # 先 汪汪叫  再 嗷嗷叫

 

  3、多态

    不同的子类对象调用相同的方法,产生不同的执行结果

    可以增加代码的灵活度,以继承和重写父类方法为前提,是调用方法的技巧,不会影响类的内部设计

    案例

class XTQ(Dog):
    def game(self):
        print("哮天犬天上玩")

class Person:
    def play_with_dog(self,dog):
        '''dog 是狗类或者其子类的对象'''
        print("人和狗一起玩")
        dog.game()     #使用上面类的方法

if __name__ == "__main__":
    #实例化对象
    dog1 = Dog()
    xtq = XTQ()
    xiaowang = Person()

    xiaowang.play_with_dog(dog1)   #先 人和狗一起玩    再 简单的玩啥
    xiaowang.play_with_dog(xtq)     #先 人和狗一起玩    再 哮天犬天上玩

 

九、私有和公有

  在Python中,定义类的时候,可以给 属性和方法 设置访问权限,即规定在什么地方使用 该权限分为两种:公有和私有

  1、公有

    定义:直接定义的属性和方法,就是公有的。可以在任何地方访问和使用。只要有对象就可以访问和使用

  2、私有

    定义:只能在类内部定义 (class 关键字的缩写中)。只需要在属性或者方法名前面加上两个下划线,就会变成私有。只能在当前类的内部使用。不能在外部和子类中使用

  应用场景:

    一般定义的属性和方法都为公有。当某个属性和方法不想被外界直接使用,就定义为私有。

class Person:
    def __init__(self,name,age):
        self.name = name
        self.__age = age
    def __str__(self):
        return f"{self.name},{self.__age}"

    def set_age(self,age):    #定义公有方法去修改私有方法
        self.__age = age

if __name__ == "__main__":
    #实例化对象
    xw = Person("小王",20)
    print(xw)  #小王,20
    xw.age = 100
    print(xw)   #小王,100

    #设为私有后(在age前面加__)
    xw.age = 100
    print(xw)         #小王,20   此时就无法使用age ,不能改变

    #修改
    xw.set_age(10000)
    print(xw)              #小王,10000   通过类里面的公有方法修改私有方法

 

十、对象划分

  Python中一切皆对象

  1、类对象:就是类。在代码执行的时候,解释器会自动创建,

    作用:使用类对象创建实例化对象。存储一些类的特征值(类属性)

  2、实例化对象:创建对象也称为实例化,由类对象创建的对象 称为实例对象,简称实例。(类名 ())

    作用:保存实例的特征值(实例属性)

 

十一、属性的划分

  1、实例属性

    是每个实例对象 具有的特征(属性)

    定义:一般都是在 init 方法中,使用 self .属性名 = 属性值

    特征:每个实例对象 都会保存自己的实例属性 即内存中存在多份

    访问和修改:实例对象 . 属性 = 属性值 (修改)                  实例对象 . 属性(访问)

  2、类属性

    是类对象具有的特征,是整个类的特征

    定义:一般在类里面(class 缩进中),方法 def 外部   定义的变量

    特征:只有类对象保存一份,即在内存中只有一个

    访问和修改:类对象 . 属性 = 属性值 (修改)                  类对象 . 属性(访问)            #类对象就是类名

class Tool:
    #定义类属性
    count = 0

    def __init__(self,name):
        self.name = name    #实例属性
        Tool.count += 1     #每执行一次,计数一次对象数
if __name__ == "__main__":
    #查看创建对象的个数
    print(Tool.count)    #查看类属性    0
    tool1 = Tool("锤子")
    print(Tool.count)          #  1

 

十三、方法的划分

  1、实例的方法  

    定义:如果方法中 需要使用 实例属性,则这个方法 必须 定义为实例方法

    调用:实例对象 . 方法名()

class Tool:
    def bark(self):
        pass

  2、类方法

    定义:如果方法中 不需要使用 实例属性,但需要使用类属性 , 则这个方法可以定义为类方法(即在方法上方加@classmethod)

    调用:类名 . 方法名()      或者     实例对象 . 方法名()

class Tool:
    @classmethod
    def bark(cls):
        pass

  3、静态方法(了解)

    定义:在方法中既不使用 实例属性,也不使用类属性 可以将该方法定义为静态方法(需要使用装饰器@staticmethod

    调用:类名 . 方法名()      或者     实例对象 . 方法名()

class Tool:
    @staticmethod
    def bark():
        pass

 

  例子:类方法调用

class Tool:
    #定义类属性
    count = 0
    def __init__(self,name):
        self.name = name    #实例属性
        Tool.count += 1     #每执行一次,计数一次对象数

    @classmethod
    def show_tool_count(cls):
        return cls.count
if __name__ == "__main__":
    #查看创建对象的个数
    print(Tool.show_tool_count())    #通过类对象调用    0
    tool1 = Tool("锤子")
    tool2 = Tool("刀子")
    print(tool2.show_tool_count())   #通过实例对象调用  2

 

  案例:总结

import random
class Game:
    #定义类属性,保存历史最高分
    top_score = 0

    def __init__(self,name):
        self.paly_name = name   #实例属性

    #静态方法
    @staticmethod
    def show_help():
        print("游戏的帮助信息")

    #类方法
    @classmethod
    def show_top_score(cls):
        print(f"历史最高分为{cls.top_score}")

    def start_game(self):
        score = random.randint(10,100)
        print(f"玩家{self.paly_name} 本次得分 {score}")
        if score > Game.top_score:
            Game.top_score = score
if __name__ == "__main__":
    Game.show_help()
    Game.show_top_score()
    player = Game("小王")
    player.start_game()
    '''
    游戏的帮助信息
    历史最高分为0
    玩家小王 本次得分 27
    '''

 

        

 

  

    

  

 

posted @ 2023-04-02 09:54  新入世界的小白  阅读(49)  评论(0编辑  收藏  举报