Python面向对象

面向对象介绍

面向对象(oop)是一种编程方法,编程思想(即指导如何写代码),适用于中大型项目
面向过程也是一种编程思想,适用于小型项目
面向过程和面向对象 都可以实现某个编程的目的

面向过程考虑的是 实现的细节
面向对象 考虑的是 结果(谁能做这件事)

类和对象

类和对象是面向对象编程中 最重要的两个概念
  • 是对具有相同特征或者行为的事物的一个统称,是抽象的,不能直接使用
    • 指代多个事物
    • 代码中 类是由关键字class定义
  • 对象是由类创建出来的一个具体存在的事物,可以直接使用
    • 指代 一个具体事物
    • 代码中 使用 类去创建(实例化)
苹果  ---->类
红苹果  ---->类
小明手里的那个红苹果    ---->对象

狗  ---->类
大黄狗  ---->类
李四家的那条大黄狗   ---->对象

类的构成

类的构成,类的三要素
1.类名(多个事物 起一个名字,标识符规则,见名知意,类名用例满足大驼峰命名法(所有单词的首字母大写))
2.属性(事物的特征)
3.方法(事物的行为)

面向对象代码的步骤

1.设计类(找类的三要素)
2.定义类
3.创建对象(实例化对象)
4.由对象调用类中的方法

类的设计

类的设计 就是找三要素 属性和方法 可以会有很多 我们只需要找到关注的即可
类名的提取:使用名词提炼法 分析整个业务流程,得出的名词,通常就是类名

需求:

  • 小明 今年18岁身高1.75,每天早上 完步,会去东西

  • 小美 今年17岁身高1.65,小美不跑步,小美喜欢 东西

类名:人类Person,People,Human
属性:姓名(name),年龄(age),身高(height)
方法:跑(run)/吃(eat)

需求:

  • 一只黄颜色的狗狗 叫大黄
  • 看见生人 汪汪叫
  • 看见家人 摇尾巴
类名:狗类(Dog)
属性:颜色(color),名字(name)
方法:叫(bark),摇尾巴(shake)

需求:

  • 进入某Web项目登录页面,输入用户名、密码、验证码之后,点击登录按钮可以登录系统。
类名:LoginPage
属性:用户名(username),密码(password),验证码(verify_code),登录按钮(login_btn)
方法:登录方法(login)

面向对象基本语法

类的基本使用

1、定义类

在Python中定义类使用关键字 class.
class 类名:
  #在class的缩进中定义类的属性和方法
def 方法名(self): #方法的本质是函数
	pass

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

在代码中,对象是由类对象
类名() #就是创建对象
#一般使用变量将创建的对象保存起来
变量=类名() # 一般将这个变量称为是对象,本质,变量中保存的对象的引用地址

3、调用类中的方法

由类创建的对象,可以调用类中的方法
- 语法
对象.方法名()

案例

需求:小猫 爱 吃鱼,小猫 要喝水
类的设计:
类名:猫(Cat)
属性:暂无
方法:吃鱼(eat),喝水(drink)
class Cat:
    def eat(self):#self 暂时不管
        """吃鱼的方法"""
        print('小猫爱吃鱼...')

    def drink(self):
        """喝水的方法"""
        print('小猫要喝水')

#创建对象
tom = Cat()
# 通过对象 调用类中的方法
tom.eat()
tom.drink()

self 参数

1.从函数的语法上来看,self是形参,名字可以任意的变量名,只是我们习惯性叫self
2.特殊点:self是一个普通的参数,按照函数的语法,在调用的时候,我们必须传递实参值,
原因是Python解释器自动的将调用这个方法的对象作为参数传递给self
所以self就是调用这个方法对象
class Cat:
    def eat(self):#self 是调用这个方法的对象
        """吃鱼的方法"""
        print(f"self:{id(self)}")
        print('小猫爱吃鱼...')


#创建对象
tom = Cat()
# 通过对象 调用类中的方法
print(f"tom:{id(tom)}")
tom.eat() #tom 调用,self就是tom

blue_cat=Cat()
print(f"blue:{id(blue_cat)}")
blue_cat.eat()# blue_cat调用,self就是blue_cat

属性

属性表示事物的特征
可以给对象添加属性 或者获取对象的属性值

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

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

在方法中操作属性(self是对象):
self.属性名=属性值
self.属性名
class Cat:
    def eat(self):#self 是调用这个方法的对象
        """吃鱼的方法"""
        print(f"self:{id(self)}")
        print(f'小猫{self.name}爱吃鱼...')


#创建对象
tom = Cat()
# 通过对象 调用类中的方法
print(f"tom:{id(tom)}")
#给Tom 对象添加name 属性
tom.name ='汤姆'
print(tom.name)
tom.eat() #tom 调用,self就是tom

blue_cat=Cat()
print(f"blue:{id(blue_cat)}")
blue_cat.name='蓝猫'
print(blue_cat.name)
blue_cat.eat()# blue_cat调用,self就是blue_cat
  • 练习
Cat 添加属性 姓名,年龄
eat 方法中打印输出,小猫xx xx 岁 爱吃鱼

魔法方法

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

怎么学习:
1.什么情况下会自动调用(自动调用的时机)
2.应用场景
3.注意事项

初始化方法 __init__

1.调用时机
  在创建对象之后,会自动调用
2.应用场景
 初始化对象,给对象添加属性
3.注意事项
  -不要写错
  - 如果属性是会变化的,则可以将这个属性的值作为参数传递,在创建对象的时候,必须传递实参值
class Cat:
    def __init__(self,name):
        print('我是init方法,我被调用了')#验证使用,正式代码不要
        self.name=name

    def eat(self):
        print(f'小猫{self.name}爱吃鱼')

#init方法 创建对象之后 会自动调用
blue_cat=Cat('蓝猫')
blue_cat.eat()

black_cat=Cat('黑猫')
black_cat.eat()

__str__方法

1.调用时机
使用print(对象) 打印对象的时候,会自动调用
	1.如果没有定义__str__方法,默认打印的是 对象的引用地址
	2.如果定义__str__方法,打印的是 方法的返回值
2.应用场景
	使用print(对象) 打印输出对象的属性信息
3.注意事项
		必须返回一个字符串
"""
定义Cat类,包含属性 name和age,打印对象的时候,可以
输出对象的姓名和年龄
类名:Cat
属性:name,age
方法:__str__,__init__
"""
class Cat:
    def __init__(self,name,age):
        self.name=name # 添加name属性
        self.age=age #添加age 属性
    def __str__(self):#一般不使用print 直接返回
        return f"姓名:{self.name},年龄:{self.age}"

#创建对象
tom = Cat('汤姆',3)
print(tom)

封装案例

封装:根据要求将属性和方法 定义到类中(定义类)

案例一 小明爱跑步

需求:

  • 小明 体重75.0公斤
  • 小明每次跑步 会减肥 0.5公斤
  • 小明每次吃东西 体重增加 1 公斤
类名:人类(Person)
属性:体重(weight) 姓名(name)
方法:跑步(run) --->修改属性值
	吃东西(eat) --->修改属性值
__init__定义属性
__str__打印属性信息使用
class Person:
    def __init__(self,name,weight):
        self.name=name #姓名
        self.weight=weight #体重

    def __str__(self):
        return f"{self.name}目前的体重为{self.weight}kg"

    def run(self):
        """跑步的方法"""
        #体重减少0.5kg
        #self.weight=self.weight-0.5
        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__':
    #创建对象
    xming=Person('小明',75.0)
    print(xming)
    xming.run()
    print(xming)
    xming.eat()
    print(xming)
    print('_'*30)
    xmei=Person('小美',45.0)
    print(xmei)
    xmei.run()
    print(xmei)
    xmei.eat()
    print(xmei)

案例二 登录

  • 需求
进入某Web项目登录页面,输入用户名,密码,验证码之后登录系统
  • 类的设计
类名:LoginPage
属性:用户名(username),密码(password),验证码(verify_code)
方法:login
  • 代码实现

class LoginPage:
    """登录页面"""
    def __init__(self,username,password,veriff_code):
        self.username=username #用户名
        self.password=password # 密码
        self.verify_code=veriff_code #验证码

    def login(self):
        print(f"1.输入用户名:{self.username}")
        print(f"2.输入密码:{self.password}")
        print(f"3.输入验证码:{self.verify_code}")
        print(f"4.点击登录")
if __name__ == '__main__':
    admin=LoginPage('admin','123456','8888')
    admin.login()

案例三 摆放家具

  • 需求
1.房子(House)有 户姓、总面积和家具名称列表 -新房子没有任何的家具
2.家具(HouseItem)有名字和占地面积,其中
- 席梦思(bed)占地4平米
- 衣柜(chest)占地2平米
- 餐桌(table)占地1.5平米
3.将以上三件家具添加到房子中
4.打印房子时,要求输出:户型、总面积、剩余面积、家具名称列表

剩余面积
1.在创建房子对象时,定义一个剩余面积的属性,初始值和总面积相等
2.当调用 add_item方法,向房间 添加家具时,让剩余面积 -=家具面积
  • 类的设计
类名:房子类(House)
属性:户型(h_type),
总面积 total_area
剩余面积 free_area =total_area
家具名称列表 item_list = [ ]
方法:__init__ ,__str__
添加家具的方法 add_item(1.修改剩余面积2.判断剩余面积和家具面积的关系
    3.向家具列表中添加家具的名字)
---------------------------
类名: 家具类(HouseItem)
属性: 名字 name
占地面积 area
方法: __str__ , __init__
三个家具对象
– 席梦思(bed) 占地 4 平米
– 衣柜(chest) 占地 2 平米
– 餐桌(table) 占地 1.5 平米
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.total_area = area #总面积
        self.free_area = area #剩余面积和总面积一样
        self.item_list=[]#刚开始没有家具
    def __str__(self):
        return f"户型:{self.h_type}、总面积: {self.total_area}平米、剩余面积:{self.free_area}平米、家具名称列表:{self.item_list}"
    def add_item(self,item):#1.房子对象(self)2.家具对象(传参)
        """添加家具,item家具对象"""
        #1.先判断房子的剩余面积和家具的占地面积的关系
        if self.free_area > item.area: # 对象.属性 获取属性值
            print(f"添加家具:{item.name}")
            self.item_list.append(item.name)
            #修改剩余面积
            self.free_area -= item.area
        else:
            print(f"房子剩余面积不足,换个大房子吧..")

if __name__ == '__main__':
    #创建家具对象
    bed=HouseItem('席梦思',4)
    chest= HouseItem('衣柜',2)
    table = HouseItem('餐桌',1.5)
    print(bed)
    print(chest)
    print(table)

    #创建房子
    house =House('三室一厅',100)
    print(house)
    house.add_item(bed)
    print(house)
    house.add_item(chest)
    print(house)
    house.add_item(table)
    print(house)

继承

1.继承描述的是类与类之间的关系 is ...a
2.继承的好处:减少代码冗余,重复代码不需要多次书写,提高编程效率

语法

#class 类A(object):
#class 类A():
class 类A: # 默认继承object类,object类Python中最原始的类
    pass
class 类B(类A):就是继承,类B继承类A 
	pass

#类A:父类 或 基类
#类B: 子类 或 派生类
子类继承父类之后,子类对象可以直接使用父类中的属性和方法
# 1.定义动物类,动物类有姓名和年龄属性,具有吃和睡的行为

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} 睡觉")

# 2.定义猫类,猫类具有动物类的所有属性和方法,并且具有抓老鼠的特殊行为
class Cat(Animal):
    """猫类"""
    def catch(self):
        print(f"{self.name}会抓老鼠..")

# 3.定义狗类,狗类具有动物类的所有属性和方法,并且具有看门的特殊行为
class Dog(Animal):
    """狗类"""
    def look_the_door(self):
        """看门"""
        print(f"{self.name}正在看家...")

#4.定义哮天犬,哮天犬具有狗类的所有属性和方法,并且具有飞的特殊行为
class XTQ(Dog):
    """哮天犬类"""
    def fly(self):
        """飞"""
        print(f"{self.name} 在天上飞..")

if __name__ == '__main__':

    ani = Animal('佩奇',2)
    ani.eat()
    ani.sleep()

    cat =Cat('黑猫警长',10)
    cat.eat() #调用父类animal中的方法
    cat.sleep()# 调用父类animal中的方法
    cat.catch()#调用自己类的方法

    dog=Dog('旺财',3)
    dog.eat()
    dog.sleep()
    dog.look_the_door()

    xtq=XTQ('哮天犬',100)
    xtq.eat()
    xtq.sleep()
    xtq.look_the_door()
    xtq.fly()


继承具有传递性:C继承B,B继承A,C可以使用A类中的属性和方法
对象调用方法的顺序:对象.方法名()
1.会先在自己的类中查找,找到直接使用
2.没有找到 去父类中查找,找到直接使用
3.没有找到 在父类的父类中查找,找到直接使用
4.没有找到..
5.直到object类,找到直接使用,没有找到 报错

重写(override)

1.什么是重写?
    重写是在子类中定义了和父类中名字一样的方法
2.重写的原因?为什么重写?
   父类中的代码不能满足子类对象的需要
3.重写的方式
3.1 覆盖式重写
3.2 扩展式重写

覆盖式重写

父类中的功能全部不要
直接在子类中定义和父类中方法名字一样的方法接口,直接书写新的代码
class Dog:
    def bark(self):
        print('汪汪的叫...')

class XTQ(Dog):
    #需要哮天犬 嗷嗷叫 父类中bark方法 不能满足子类对象的需要,覆盖式重写
    def bark(self):
        print("嗷嗷嗷叫")
if __name__ == '__main__':
    xtq = XTQ()
    xtq.bark()

扩展式重写

父类中的功能还需要,只是添加了新的功能
方法:
1.先在子类中定义和父类中名字相同的方法
2.在子类的代码中 使用super().方法名() 调用父类中的功能
3.书写新的功能
class Dog:
    def bark(self):
        print('汪汪的叫...')
        print('汪汪的叫...')

class XTQ(Dog):
    #需要哮天犬 嗷嗷叫 父类中bark方法 不能满足子类对象的需要,覆盖式重写
    def bark(self):
        #调用父类中的功能
        super().bark()
        print("嗷嗷嗷叫")
        print("嗷嗷嗷叫")
if __name__ == '__main__':
    xtq = XTQ()
    xtq.bark()

多态

多态:调用代码的技巧
多态:不同的子类对象调用相同的方法,产生不同的执行结果
class Dog:
    def game(self):
        print("普通狗简单的玩耍..")

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

class Person:
    def play_with_dog(self,dog):
        """dog是狗类或者其子类的对象"""
        print("人和狗在玩耍..",end = '')
        dog.game()

if __name__ == '__main__':

    dog1=Dog()
    xtq = XTQ()
    xw=Person()
    xw.play_with_dog(dog1)
    xw.play_with_dog(xtq)

私有和公有

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

公有权限

  • 定义

    直接定义的属性和方法就是公有的
    
  • 特点

可以在任何地方访问和使用,只要有对象就可以访问和使用

私有权限

  • 定义
1.只能在类内部定义(class关键字的缩进中)
2.只需要在 属性名或者方法名前边加上两个下划线,这个方法或者属性就变为私有的
  • 特点
私有 只能在当前类的内部使用,不能在类外部和子类直接使用
  • 应用场景
一般来说,定义的属性和方法 都为公有的
某个属性 不想在外部直接使用 定义为私有
某个方法 是内部的方法(不想在外部使用),定义为私有
"""定义人类 name属性 age属性(私有)"""

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):# 定义公有方法,修改私有属性
        if age < 0 or age>120:
            print('提供的年龄信息不对')
            return
        self.__age= age

if __name__ == '__main__':
    xw=Person('小王',18)
    print(xw)
    xw.__age =10000 #添加一个公有属性__age
    print(xw)
    xw.set_age(10000)
    print(xw)

对象 属性 方法

对象分类

  • python 中一切皆对象

类对象

类对象 就是类 就是使用class定义的类
在代码执行的时候,解释器会自动的创建
作用:
1.使用类对象创建 实例对象
2.存储一些类的特征值 (类属性)

实例对象

1.创建对象也称为实例化 所有由类对象(类)创建的对象 称为是实例对象,简称实例
2.一般来说,没有特殊强调,我们所说的对象都是指 实例对象(实例)
3.实例对象 可以保存实例的特征值(实例属性)
4.就是使用 类名() 创建的对象

属性的划分

使用实例对象.属性 访问属性的时候,会先在实例属性中查找,如果找不到,就去类属性中查找
找到就使用,找不到就报错
即:每个实例对象 都有可能访问类属性值(前提 实例属性和类属性不重名)
实例属性
  • 概念
是每个实例对象 具有的特征(属性),每个实例对象的特征
  • 定义
一般都是在init方法中,使用self.属性名 = 属性值 来定义
  • 特征(内存)
每个实例对象 都会保存自己的 实例属性 即内存中存在多份
  • 访问和修改
# 可以认为是通过self
实例对象.属性 = 属性值 #修改
实例对象.属性 #访问

类属性

  • 概念
是类对象具有的 特征,是整个类的特征
  • 定义
一般在类的内部(class缩进中),方法的外部(def的缩进外部)定义的变量
  • 特征(内存)
只有类对象保存一份,即在内存中只有一个
  • 访问和修改
# 即通过类名
类对象.属性 = 属性值
类对象.属性

什么时候 定义类属性?

代码中 使用的属性 基本上都是实例属性,即都通过self定义

当某个属性值描述的信息是整个类的特征(这个值变动,所有的这个类的对象这个特征都会发生变化)

案例

1.定义一个 工具类
2.每件工具都有自己的 name
3.需求  知道使用这个类 创建了多少个工具对象?
类名:Tool
属性: name(实例属性) count(类属性)
方法: init方法
class Tool:
    #定义类属性count,记录创建对象的个数
    count = 0
    def __init__(self,name):
        self.name = name #实例属性,工具的名字
        # 修改类属性的值
        Tool.count +=1

if __name__ == '__main__':
    #查看创建对象的个数
    print(Tool.count)#查看类属性
    tool1=Tool('锤子')
    print(Tool.count)
    tool2=Tool('扳手')
    print(Tool.count)
    print(tool2.count)#先找实例属性count,找不到,找类属性count 找到 使用

方法的划分

实例方法
  • 定义时机
如果方法中需要使用 实例属性,则这个方法 必须定义为实例方法
  • 定义
#直接定义的方法就是实例方法
class 类名:
	def 方法名(self)pass
  • 参数
参数一般写作self,表示的是实例对象
  • 调用
实例对象.方法名()
类方法
  • 定义时机
如果方法中 不需要使用 实例属性,但需要使用类属性,则这个方法可以定义为类方法(建议)
  • 定义
#定义类方法,需要在方法名上方 书写@classmethod,即使用@classmethod装饰器装饰
class 类名:
    @classmethod
    def 方法名(cls):
        pass
  • 参数
参数一般写作 cls 表示类对象,即类名 同样不需要手动传递 python解释器会自动传递
  • 调用
方法一
类名.方法名()

方法二
实例对象.方法名()

静态方法

  • 定义时机
方法中既不需要使用实例属性,也不需要使用 类属性,可以 将这个方法定义为静态方法
  • 定义
# 定义静态方法,需要使用装饰器@staticmethod装饰方法

class 类名:
    @staticmethod
    def 方法名():
        pass
  • 参数
静态方法 对参数没有要求 一般没有
  • 调用
方法一
类名.方法名()

方法二
实例对象.方法名()
class Tool:
    #定义类属性count,记录创建对象的个数
    count = 0
    def __init__(self,name):
        self.name = name #实例属性,工具的名字
        # 修改类属性的值
        Tool.count +=1
    @classmethod
    def show_tool_count(cls):#cls 就是类对象 类名
        return cls.count

if __name__ == '__main__':
    #查看创建对象的个数
    print(Tool.show_tool_count())#查看类属性
    tool1=Tool('锤子')
    print(Tool.show_tool_count())
    tool2=Tool('扳手')
    print(Tool.show_tool_count())

案例

需求:
1. 设计一个 Game 类
2. 属性:
    • 定义一个 top_score 类属性 -> 记录游戏的历史最高分
    • 定义一个 player_name 实例属性 -> 记录当前游戏的玩家姓名
3. 方法:
    • 静态方法 show_help() -> 显示游戏帮助信息
    • 类方法 show_top_score() -> 显示历史最高分
    • 实例方法 start_game() -> 开始当前玩家的游戏
        - ① 使用随机数 生成 10-100 之间数字 作为本次游戏的得分
        - ② 打印本次游戏等分 : 玩家 xxx 本次游戏得分 ooo
        - ② 和历史最高分进行比较, 如果比历史最高分高, 修改历史最高分
4. 主程序步骤: main
    1 查看帮助信息
    2 查看历史最高分
    3 创建游戏对象,开始游戏
    4 再一次游戏
类名:Game
属性:
	top_score = 0 类属性
	player_name 实例属性 init

import  random
class Game:
    #定义类属性,保存历史最高分
    top_score = 0
    def __init__(self,name):
        self.player_name = name #实例属性


    #静态方法
    @staticmethod
    def show_help():
        print('这是游戏的帮助信息')
    #类方法
    @classmethod
    def show_top_score(cls):
        print(f'历史最高分为:{cls.top_score}')

    def start_game(self):
        print(f'玩家{self.player_name}开始游戏...')
        score = random.randint(10,100)#本次游戏得分
        print(f"玩家{self.player_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()
    Game.show_top_score()
    player.start_game()
    Game.show_top_score()
  • 18
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值