目录
面向对象
基本介绍
面向对象是⼀个编程思想 ( 写代码的套路 )
编程思想:
1. 面向过程
2. 面向对象
以上两种都属于写代码的套路(方法),最终目的都是为了将代码书写出来,只不过过程和思考方法不太⼀样
- 面向过程
- 关注的是具体步骤的实现,所有的功能都自己书写
- 亲力亲为
- 定义⼀个个函数,最终按照顺序调用函数
- 面向对象
- 关注的是结果,谁(对象)能帮我做这件事
- 偷懒
- 找⼀个对象(),让对象去做
类和对象
面向对象的 核心思想 是找⼀个对象去帮我们处理事情
在程序代码中 对象是由 类 创建的
类和对象,是面向对象编程思想中非常重要的两个概念
- 类
- 抽象的概念,对 多个 特征和行为相同或者相似事物的统称
- 泛指的(指代多个,而不是具体的⼀个)
- 对象
- 具体存在的⼀个事物,看得见摸得着的
- 特指的,(指代⼀个)
苹果 ---> 类
红苹果 ----> 类
张三嘴⾥正在吃的那个苹果 ---> 对象
类的组成
- 类名(给这多个事物起⼀个名字,在代码中满足大驼峰命名法(每个单词的首字母大写))
- 属性(事物的特征,即有什么,⼀般文字中的名词)
- 方法(事物的行为,即做什么事,⼀般是动词)
类的抽象(类的设计)
类的抽象,其实就是找到 类的 类名,属性 和方法
类名 :⼈类 ( Person , People )
属性 :名字 ( name ) , 年龄 ( age ) , 身高 ( height )
方法 :跑步 ( run ) 吃 ( eat )
面向代码的步骤
- 定义类,在定义类之前先设计类
- 创建对象,使用第⼀步定义的类创建对象
- 通过对象调用方法
面向对象基本代码的书写
1.定义类
先定义简单的类,不包含属性,在 python 中定义类需要使用关键字 class
方法:方法的本质是在类中定义的函数,只不过,第⼀个参数是 self
class 类名:
# 在缩进中书写的内容,都是类中的代码
def 方法名( self): # 就是⼀个方法
pass
2.创建对象
创建对象是使用类名 () 进行创建 , 即
类名 () # 创建⼀个对象, 这个对象在后续不能使用
# 创建的对象想要在后续的代码中继续使用, 需要使用⼀个变量 , 将这个对象保存起来
变量 = 类名 () # 这个变量中保存的是对象的地址, ⼀般可以成为这个变量为对象
# ⼀个类可以创建多个对象, 只要出现 类名 () 就是创建⼀个对象, 每个对象的地址是不⼀样的
3.调用方法
对象 .方 法名 ()
列表 . sort ()
列表 . append ()
self 的说明
class Cat :
# 在缩进中书写 方法
def eat ( self ) : # self 会自动出现 , 暂不管
print ( '小 猫爱吃鱼 ... ' )
black_cat . eat ()
1. 从函数的语法上讲 , self 是形参 , 就可以是任意的变量名 , 只不过我们习惯性将这个形参写作 self
2. self 是普通的形参,但是在调⽤的时候没有传递实参值,原因是,Python 解释器在执行代码的时候,自动的将调用这个方法的对象传递给了 self,即 self 的本质是对象
3. 验证,只需要确定通过哪个对象调用,对象的引用和 self 的引用是⼀样的
4. self 是函数中的局部变量 , 直接创建的对象是全局变量
#1.需求:⼩猫爱吃⻥,⼩猫要喝⽔, 定义不带属性的类
class Cat:
# 在缩进中书写 ⽅法
def eat(self): # self 会⾃动出现,暂不管
print(f'{id(self)}, self')
print('⼩猫爱吃⻥...')
# 2. 创建对象
blue_cat = Cat()
print(f'{id(blue_cat)}, blue_cat')
# 3. 通过对象调⽤类中的⽅法
blue_cat.eat() # blue_cat 对象调⽤ eat ⽅法, 解释器就会将 blue_cat 对象传给 self
print('_*_' * 30)
# 创建对象
black_cat = Cat()
print(f"{id(black_cat)}, black_cat")
black_cat.eat() # black_cat 对象调⽤ eat ⽅法, 解释器就会将 black_cat 对象传给 self
对象的属性操作
添加属性
对象 . 属性名 = 属性值
- 类内部添加
在内部⽅法中,self 是对象
self . 属性名 = 属性值
# 在类中添加属性⼀般写在 _ _init __ 方法中
- 类外部添加
对象.属性名 = 属性值 # ⼀般不使用
获取属性
对象 . 属性名
- 类内部
在内部方法中 , self 是对象
self . 属性名
- 类外部
对象 . 属性名 # ⼀般很少使用
class Cat:
# 在缩进中书写 ⽅法
def eat(self): # self 会⾃动出现,暂不管
print(f'{id(self)}, self')
print(f'⼩猫{self.name} 爱吃⻥...')
# 2. 创建对象
blue_cat = Cat()
print(f'{id(blue_cat)}, blue_cat')
# 给 蓝猫添加 name 属性
blue_cat.name = '蓝猫'
# 3. 通过对象调⽤类中的⽅法
blue_cat.eat() # blue_cat 对象调⽤ eat ⽅法, 解释器就会将 blue_cat 对象传给 self
print('_*_' * 30)
# # 创建对象
black_cat = Cat()
black_cat.name = '⿊猫'
print(f"{id(black_cat)}, black_cat")
black_cat.eat() # black_cat 对象调⽤ eat ⽅法, 解释器就会将 black_cat 对象传给 self
魔法方法
python 中有⼀类方法 , 以两个下划线开头 , 两个下划线结尾 , 并且在满足某个条件的情况下 , 会自动调用 , 这类方法称为魔法方法
学习:
- 什么情况下自动调用
- 有什么用,用在哪
- 书写的注意事项
__init__ 方法 **
- 什么情况下自动调用
- 创建对象之后会自动调用
- 有什么用,用在哪
- 给对象添加属性的,(初始化方法,构造方法)
- 某些代码,在每次创建对象之后,都要执行,就可以将这行代码写在 __init__ 方法
- 书写的注意事项
- 不要写错了
- 如果 init 方法中,存在出了 self 之外的参数,在创建对象的时候必须传参
#猫类, 属性 name, age , show_info(输出属性信息)
class Cat:
# 定义添加属性的⽅法
def __init__(self, name, age): # 这个⽅法是创建对象之后调⽤
self.name = name # 给对象添加 name 属性
self.age = age # 给对象添加 age 属性
# 输出属性信息
def show_info(self):
print(f'⼩猫的名字是: {self.name}, 年龄是:{self.age}')
# 创建对象,不要在⾃⼰类缩进中创建
# Cat() # 创建对象 ,会输出
blue_cat = Cat('蓝猫', 2)
blue = blue_cat
blue.show_info()
# 创建⿊猫
black_cat = Cat('⿊猫', 3)
black_cat.show_info()
__str__ 方法 *
- 什么情况下自动调用
- 使用 print(对象) 打印对象的时候会自动调用
- 有什么用,用在哪
- 在这个方法中⼀般书写对象的属性信息的,即打印对象的时候想要查看什么信息,在这个方法中进行定义的
- 如果类中没有定义 __str__ 方法, print(对象) ,默认输出对象的引用地址
- 书写的注意事项
- 这个方法必须返回⼀个字符串
class Cat:
# 定义添加属性的⽅法
def __init__(self, n, age): # 这个⽅法是创建对象之后调⽤
self.name = n # 给对象添加 name 属性
self.age = age # 给对象添加 age 属性
def __str__(self):
# ⽅法必须返回⼀个字符串, 只要是字符串就⾏,
return f'⼩猫的名字是: {self.name}, 年龄是:{self.age}'
# 创建对象,不要在⾃⼰类缩进中创建
# Cat() # 创建对象 ,会输出
blue_cat = Cat('蓝猫', 2)
print(blue_cat)
# 创建⿊猫
black_cat = Cat('⿊猫', 3)
print(black_cat)
__del__ 方法 【了解】
_ _init __ 方法,创建对象之后,会自动调用 (构造方法)
_ _del __ 方法,对象被删除销毁时,自动调用的(遗言,处理后事)(析构方法)
1. 调用场景 , 程序代码运行结束 , 所有对象都被销毁
2. 调用场景 , 直接使用 del 删除对象 ( 如果对象有多个名字 ( 多个对象引⽤⼀个对象 ), 需要把所有的对象都删除才行 )
class Demo:
def __init__(self, name):
print('我是 __init__, 我被调⽤了 ')
self.name = name
def __del__(self):
print(f'{self.name} 没了, 给他处理后事...')
# Demo('a')
a = Demo('a')
b = Demo('b')
del a # 删除销毁 对象,
print('代码运⾏结束')
案例
类名:人类 Person
属性:姓名 name , 体重 weight
方法:跑步 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):
print(f'{self.name} 跑步 5 km, 体重减少了')
# 减体重, 即修改属性
self.weight -= 0.5
def eat(self):
print(f'{self.name} ⼤餐⼀顿, 体重增加了')
# 修改体重
self.weight += 1
xm = Person('⼩明', 75.0)
print(xm)
xm.run()
print(xm)
xm.eat()
print(xm)
封装案例
# 定义家具类
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, name, area):
self.name = name # 户型
self.total_area = area # 总面积
self.free_area = area # 剩余面积
self.item_list = [] # 家具名称列表
def __str__(self):
return f"户型: {self.name}, 总面积:{self.total_area}平米, 剩余面积{self.free_area} 平米, " \
f"家具名称列表: {self.item_list}"
def add_item(self, item): # item 表示的家具的对象
# 判断房子的剩余面积(self.free_area)和家具的占地面积(item.area)之间的关系
# self 表示的 房子对象, 缺少一个家具对象使用传参解决
if self.free_area > item.area:
# 添加家具, ---> 向列表中添加数据
self.item_list.append(item.name)
# 修改剩余面积
self.free_area -= item.area
print(f'{item.name} 添加成功')
else:
print('剩余面积不足, 换个大房子吧')
# 创建家具对象
bed = HouseItem('席梦思', 4)
chest = HouseItem('衣柜', 2)
table = HouseItem('餐桌', 1.5)
print(bed)
print(chest)
print(table)
# 创建房子对象
house = House('三室一厅', 150)
print(house)
# 添加 床
house.add_item(bed)
print(house)
案例二
需求 : 某 Web 项目登录页面包含 : 用户名 , 密码 , 验证码 , 登录按钮 和登录的方法 书写代码实现以上功能 , 登录方法中使用 print 输出即可 类名 : LoginPage 属性 : 用户名 ( username ) , 密码 ( password ) , 验证码 ( code ) , 登录按钮 ( button ) 方法 : 登录 ( login ) _ _init __
class LoginPage:
def __init__(self, username, password, code):
self.username = username
self.password = password
self.code = code
self.btn = '登录'
def login(self):
print(f'1. 输入用户名 {self.username}')
print(f'2. 输入密码 {self.password}')
print(f'3. 输入验证码 {self.code}')
print(f"4. 点击按钮 {self.btn}")
login = LoginPage('admin', '123456', '8888')
login.login()
私有和公有
- 在 Python 中定义的方法和属性,可以添加访问控制权限(即在什么地方可以使用这个属性和方法)
- 访问控制权限分为两种,公有权限,私有权限
- 公有权限
- 直接书写的方法和属性,都是公有的
- 公有的方法和属性,可以在任意地方访问和使用
- 私有权限
- 在类内部,属性名或者方法名 前边加上两个 下划线 ,这个属性或者方法 就变为 私有的
- 私有的方法和属性,只能在当前类的内部使用
- 什么时候定义私有
- 某个属性或者方法,不想在类外部被访问和使用,就将其定义为私有即可
- 测试中,一般不怎么使用,直接公有即可
- 开发中,会根据需求文档,确定什么作为私有
- 如果想要在类外部操作私有属性,方法是,在类内部定义公有的方法,我们通过这个公有方法去操作
案例
定义一个 Person 类 , 属性 name , age ( 私有 )class Person:
def __init__(self, name, age):
self.name = name # 姓名
# 私有的本质, 是 Python 解释器执行代码,发现属性名或者方法名前有两个_, 会将这个名字重命名
# 会在这个名字的前边加上 _类名前缀,即 self.__age ===> self._Person__age
self.__age = age # 年龄, 将其定义为私有属性, 属性名前加上两个 _
def __str__(self): # 在类内部可以访问私有属性的
return f'名字: {self.name}, 年龄: {self.__age}'
xm = Person('小明', 18)
print(xm)
# 在类外部直接访问 age 属性
# print(xm.__age) # 会报错, 在类外部不能直接使用私有属性
# 直接修改 age 属性
xm.__age = 20 # 这个不是修改私有属性, 是添加了一个公有的属性 __age
print(xm) # 名字: 小明, 年龄: 18
print(xm._Person__age) # 能用但是不要用 18
xm._Person__age = 19
print(xm) # 名字: 小明, 年龄: 19
继承
1. 继承描述的是类与类之间的关系 2. 继承的好处:减少代码的冗余(相同的代码不需要多次重复书写),可以直接使用
语法
术语:# class A(object):
class A : # 没有写父类 , 但也有父类 , object, object 类是 Python 中最顶级 ( 原始 ) 的类 pass class B ( A ): # 类 B, 继承类 A pass
- A 类,称为是 父类(基类)
- B 类,称为是 子类(派生类)
案例
- 定义一个 动物类,吃
- 定义一个 狗类,继承动物类,吃,叫
- 定义一个 哮天犬类,继承 狗类
# 1. 定义一个 动物类, 吃
class Animal:
def eat(self):
print('要吃东西')
# 2. 定义一个 狗类, 继承动物类, 吃, 叫
class Dog(Animal):
def bark(self):
print('汪汪汪叫....')
# 3. 定义一个 哮天犬类, 继承 狗类
class XTQ(Dog):
pass
# 创建 动物类的对象
# ani = Animal()
# ani.eat()
# 创建狗类对象
# dog = Dog()
# dog.eat() # 调用父类中的方法
# dog.bark() # 调用自己类中方法
# 创建哮天犬类对象
xtq = XTQ()
xtq.bark() # 调用 父类 Dog 类的方法
xtq.eat() # 可以调用 父类的父类中的方法
结论
python 中 对象 . 方法 () 调用方法
- 现在自己的类中的去找有没有这个方法 如果有,直接调用
- 如果没有去父类中 查找,如果有,直接调用
- 如果没有,去父类的父类中查找,如果有直接调用
- ...
- 如果 object 类中有,直接调用,如果没有,代码报错
重写
- 重写:在子类中定义了和父类中名字相同的方法,就是重写
- 重写的原因:父类中的方法,不能满足子类对象的需求,所以重写
- 重写之后的特点:调用子类字节的方法,不再调用父类中的方法
重写的方式:
- 覆盖(父类中功能完全抛弃,不要,重写书写)
- 扩展(父类中功能还调用,只是添加一些新的功能)(使用较多)
覆盖
- 直接在子类中 定义和父类中名字相同的方法
- 直接在方法中书写新的代码
class Dog:
def bark(self):
print('汪汪汪叫.....')
class XTQ(Dog):
# XTQ 类bark 方法不再是汪汪汪叫, 改为 嗷嗷嗷叫
def bark(self):
print('嗷嗷嗷叫...')
xtq = XTQ()
xtq.bark()
扩展父类中的功能
- 直接在子类中 定义和父类中名字相同的方法
- 在合适的地方调用 父类中方法 super().方法()
- 书写添加的新功能
class Dog:
def bark(self):
print('汪汪汪叫.....')
print('汪汪汪叫.....')
class XTQ(Dog):
# XTQ 类bark 方法不再是汪汪汪叫, 改为
# 1. 先 嗷嗷嗷叫(新功能) 2, 汪汪汪叫(父类中功能) 3. 嗷嗷嗷叫 (新功能)
def bark(self):
print('嗷嗷嗷叫...')
# 调用父类中的代码
super().bark() # print() 如果父类中代码有多行呢?
print('嗷嗷嗷叫...')
xtq = XTQ()
xtq.bark()
多态【了解】
- 是一种写代码,调用的一种技巧
- 同一个方法,传入不同的对象,执行得到不同的结果,这种现象称为是多态
- 多态 可以 增加代码的灵活度
属性和方法
Python 中一切皆对象 . 即 使用 class 定义的类 也是一个对象
对象的划分
实例对象(实例)
1. 通过 类名 () 创建的对象 , 我们称为实例对象 , 简称实例 2. 创建对象的过程称为是类的实例化 3. 我们平时所说的对象就是指 实例对象 ( 实例 ) 4. 每个实例对象 , 都有自己的内存空间 , 在自己的内存空间中保存自己的属性 ( 实例属性 )类对象(类)
1. 类对象 就是 类 , 或者可以认为是 类名 2. 类对象是 Python 解释器在执行代码的过程中 创建的 3. 类对象的作用 : ① 使用类对象创建实例 类名 () , ② 类对象 也有自己的内存空间 , 可以保存一些属性值信息 ( 类属性 ) 4. 在一个代码中 , 一个类 只有一份内存空间属性的划分
实例属性
- 概念:是实例对象 具有的属性
- 定义和使用
在 init 方法中 , 使用 self . 属性名 = 属性值 定义 在方法中是 使用 self . 属性名 来获取 ( 调用 )
- 内存
实例属性,在每个实例中 都存在一份
- 使用时机
1. 基本上 99 % 都是实例属性 , 即通过 self 去定义 2. 找多个对象 , 来判断这个值是不是都是一样的 , 如果都是一样的 , 同时变化 , 则一般定义为 类属性 , 否则定义为 实例属性
类属性
- 概念:是 类对象 具有的属性
- 定义和使用
在类内部 , 方法外部 , 直接定义的变量, 就是类属性 使用 : 类对象 . 属性名 = 属性值 or 类名 . 属性名 = 属性值 类对象 . 属性名 or 类名 . 属性名
- 内存
只有 类对象 中存在一份
方法的划分
方法,使用 def 关键字定义在类中的函数就是方法
实例方法(最常用)
- 定义
# 在类中直接定义的方法 就是 实例方法 class Demo : def func ( self ): # 参数一般写作 self, 表示的是实例对象 pass
- 定义时机(什么时候用)
如果在方法中需要使用实例属性 ( 即需要使用 self ), 则这个方法必须定义为 实例方法
- 调用
对象 . 方法名 () # 不需要给 self 传参
类方法(会用)
- 定义
# 在方法名字的上方书写 @classmethod 装饰器 ( 使用 @classmethod 装饰的方法 ) class Demo : @classmethod def func ( cls ): # 参数一般写作 cls, 表示的是类对象 ( 即类名 ) class pass
- 定义时机(什么时候用)
1. 前提 , 方法中不需要使用 实例属性 ( 即 self ) 2. 用到了类属性 , 可以将这个方法定义为类方法 , ( 也可以定义为实例方法 )
- 调用
# 1. 通过类对象调用 类名 . 方法名 () # 也不需要给 cls 传参, python 解释器自动传递 # 2. 通过实例对象调用 实例 . 方法名 () # 也不需要给 cls 传参, python 解释器自动传递
静态方法(基本不用)
- 定义
# 在方法名字的上方书写 @staticmethod 装饰器 ( 使用 @staticmethod 装饰的方法 ) class Demo : @staticmethod def func (): # 一般没有参数 pass
- 定义时机(什么时候用)
1. 前提 , 方法中不需要使用 实例属性 ( 即 self ) 2. 也不使用 类属性 , 可以将这个方法定义为 静态方法
- 调用
# 1. 通过类对象调用 类名 . 方法名 () # 2. 通过实例对象调用 实例 . 方法名 ()标签:__,python,self,必学,面向对象,对象,print,方法,属性 From: https://blog.csdn.net/isun1/article/details/140722556