面向对象概述
1、什么是面向对象? what
面向对象是一种编程思想,是一种通过多个对象互相协作完成功能处理流程的编程思路,在核心处理过程中,又主要区分为类的声明定义、对象的创建使用。
面向对象的三大特征——
封装:体现了对象对于敏感数据的保护特征
继承:体现了代码的复用和功能的扩展
多态:体现了不同操作环境中代码的多样性【程序的健壮性】
2、为什么要使用面向对象?why
程序的开发-> 软件开发-> 解决问题-> 处理数据-> 增删改查
面向过程:它也是一种编程思想;函数式编程是面向过程编程思想的一种实现方式;专门用于处理重在过程的问题解决方案。整体业务流程并不会特别复杂,需要按照一定的功能流程逐步处理即可,完成功能数据的结果展现。
业务流程较为复杂、业务流程互相影响互相依赖。通过面向过程的方式可以实现,但是业务处理代码会较为繁琐~同时代码冗余较多。通过面向对象的操作手段可以很好的解决这样的问题。
面向对象编程思想,是对面向过程编程思想的一种补充和完善,在企业项目开发过程中,面向过程和面向对象一样重要,使用过程中~混合开发!
没有过时的技术~只有适用的场景!
3、哪里使用面向对象?where
业务流程较为复杂,在项目开发过程中出现了大量的相似数据,互相依赖和影响的情况下,完成业务流程,此时使用面向对象的编程思想~类和对象的实现,可以很好的解决代码编程的问题【繁琐、冗余】。
4、怎么认知面向对象?how
项目开发的过程~ 认知项目功能复杂度 和改造项目
类和对象
类和对象
(1) hello world
"""
面向对象入门程序
认识什么是类型和对象
"""
class HelloWorld:
"""这是一个类型"""
def say(self):
print("hello world, 面向对象")
# 创建该类型的一个具体的对象
hw = HelloWorld()
# 调用对象的行为
hw.say()
(2) 类的声明定义
类:类型的简称,是一种称呼、一个代码、一类事物的抽象出来的名称。如人、电脑、水杯…
可以将一类事物通过编程的方式,使用代码表示出来。
声明一个类型就是表示生活中的一个事物(特征和行为)。
(3) 对象的操作
对象的操作是对数据的处理。类型只是一个声明,类似于函数的存在,并不包含具体数据。对象是通过类型创建的,包含具体的数据。
创建对象的同时给对象属性赋值。
面向对象特征— 封装
(1)关于封装
为什么要封装?
为了保护敏感属性数据,让外界访问当前对象中的属性数据时,可以按照我们指定的条件进行访问,提高属性数据的安全性。
什么地方使用封装?
任何出现在类型中的属性,理论上都要使用封装。
什么是封装?
零散数据的统一处理
多种相似方法的统一整理
数据的保护
(2)封装的属性访问
class Person:
"""人的类型"""
def __init__(self, name, _age, __money):
self.name = name
self._age = _age
self.__money = __money
def set_money(self, money):
"""给属性设置值的方法"""
self.__money = money
def get_money(self):
"""获取属性值的方法"""
return self.__money
# 创建对象的同事初始化数据
p = Person("jerry", 18, 1000)
# 1、直接操作对象的属性,对于对象的属性,破坏性访问
p.name = "tom"
print(p.name)
# 2、约定如果一个属性的名称是一个下划线开头的,表示它是私有数据,不让直接操作。
p._age = 80
print(p._age)
# 警告Access to a protected member _age of class
# 这里访问了类型中一个受到保护的成员属性_age
# 3、私有化类型中的属性,通过添加两个开头的下滑线,将属性更改为私有属性。
# 提供访问该私有属性的方法【获取数据的方法,设置数据的方法】
print(p.__money)
# 报错Unresolved attribute reference _-money for class Person
# 在python类型中,查询不到属性__money
(3)封装的步骤
1: 将当前类型中所有属性私有化。
2:给每个属性提供访问属性数据的set/get方法。
3:给敏感属性的访问方法中,添加访问限制条件。
class Person:
"""人的类型"""
def __init__(self, name, age):
self.__name = name
self.__age = age
def set_name(self, name):
self.__name = name
def get_name(self):
return self.__name
def set_age(self, age):
if 18 <= age <= 40:
self.__age = age
else:
print("年龄输入不合法")
def get_age(self):
return self.__age
# 创建用户对象
p = Person("jerry", 18)
print(p.get_name(), p.get_age())
# 修改对象的属性特征
p.set_name("tom")
p.set_age(111)
print(p.get_name(), p.get_age())
面向对象特征——继承
(1)继承基本语法
class 类型名称(要继承的类型):
pass
(2)继承的特性
代码中出现了继承,类型就出现了新的名称
子类中可以继承和直接使用父类中的属性和方法
class Person:
"""人的类型"""
def __init__(self, name):
self.name = name
class Man:
"""男人"""
pass
tianqi = Man("jerry")
# isinstance类型判断运算符
print(isinstance(tianqi, Man))
print(isinstance(tianqi,Person))
打印结果:
True
True
(3)子类对象使用父类数据
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def say(self):
print(self.name, "滚去学习")
def play(self):
print(self.name, "滚去玩")
def sleep(self):
print(self.name, "滚去睡觉")
class Child(Person):
pass
c = Child("jerry", 18)
print(c.name) #对象访问父类中的属性
print(c.age)
c.say() #对象访问父类中的方法
c.play()
c.sleep()
运行结果:
jerry
18
滚去学习
滚去玩
滚去睡觉
(4)子类类型使用父类数据
1、子类中访问父类的方法
super().方法名称()
2、子类的__init__()方法
如果子类中不写__init__()方法,直接使用父类的__init__()方法初始化数据。
如果子类中写了自己的__init__()方法,一定要调用执行父类的__init__()方法。
当子类中出现独立属性时,子类定义自己的__init__()方法。
3、方法重写
子类中可以重新定义从父类中继承的方法【方法名称和方法参数一致】。
在执行过程中,如果子类中重写了方法,执行子类的方法;如果没有重写,则执行父类的方法。
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def say(self):
print("hello world")
class Child(Person):
def __init__(self, name, age, gender, phone):
super().__init__(name, age)
self.gender = gender
self.phone = phone
def speak(self):
"""子类的方法"""
super().say()
print("子类的speak方法执行中...")
c = Child("tom", 18, "男", "123")
c.speak()
运行结果:
hello world
子类的speak方法执行中…
(5)所有对象都继承于object
1、我们都继承了什么?
构造方法——
new 创建对象的方法 一般不使用~直接通过父类创建对象即可。
init 初始化数据的方法 一般会重写该方法,用来初始化对象数据
__slots__ 封装时,限制属性的
__str__ 对象字符打印方式;默认情况打印内存中16进制表示的位置
__repr__ 交互模式中,字符打印方式
__hash__ 获取兑现的hash数据,用于判断的依据
__ne__ 不等于:not equals;两个对象使用 判断 !=
__ge__ 大于等于:grant or equals 判断 >=
__gt__ 大于: grant than判断 >
__le__ 小于等于:less or equals 判断 <=
__lt__ 小于: less than 判断 <
__eq__ 等于: equals 判断 ==
__dict__ 将对象转换成字典
__doc__ 说明文档
__class__ 类型 ,类似于type
__setattr__ 给属性设置数据,一般不重写
2、继承这些有什么作用?
class Person:
"""人的类型"""
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f"人:[name:{self.name}, age:{self.age}]"
# ——>人:[name:tom, age:18]
def __hash__(self):
return self.name.__hash__()
def __gt__(self, other):
# 判断两人的大小:业务判断,按照年龄判断
if self.age > other.age:
return True
else:
return False
def __ge__(self, other):
if self.age >= other.age:
return True
else:
return False
def __eq__(self, other):
# 判断两个对象是否相等,按照业务逻辑:姓名和年龄一样,表示是同一个对象。
if self.name == other.name and self.age == other.age:
return True
else:
return False
def sleep(self, area):
"""
:param area 这是一个方法的参数说明
:return:
"""
# 创建对象
p1 = Person("tom", 18)
# 打印对象
print(p1)
# ——><__main__.Person object at 0x000001F8856C8320>
p2 = Person("tom", 18)
print(p1 == p2)
# ——>True
print(p1 > p2)
# ——>False
print(p1 >= p2)
# ——>True
print(p1.__dict__)
# ——>{'name': 'tom', 'age': 18}
print(p1.__doc__)
# ——>人的类型
print(p1.sleep.__doc__)
# ——>:param area 这是一个方法的参数说明
# :return:
面向对象特征——多态
(1)python中的多继承
一个对象在不同的场景中,可能扮演不同的角色【设计时多态】。
class Son:
def xiao_shun(self):
print("百善孝为先")
class Student:
def study(self):
print("好好学习,天天向上")
class Friend:
def play(self):
print("吃喝玩乐")
class Person(Son, Student, Friend):
"""人的类型"""
pass
p = Person()
# 家庭环境
if isinstance(p, Son):
p.xiao_shun()
# 学习环境
if isinstance(p, Student):
p.study()
# 朋友
if isinstance(p, Friend):
p.play()
def xue_tang(person):
if isinstance(person, Student):
person.study()
xue_tang(p)
(2)多继承的问题
如果不同的父类出现了相同的属性和方法,子类会继承谁的属性或者方法呢?
Python3中都是新式类:广度优先,从父类中查询对应的方法,查询到第一个满足的方法后就直接返回。
Test(A_1,A_2) ——> A_1(A) ——>A_2(A) ——>A(object) ——>object
Python2中的经典类:深度优先
Test(A_1,A_2) ——>A_1(A) ——>A ——>A_2(A) ——>A
代码如下——
class A:
def test(self):
print("aaaa")
class A_1:
def test(self):
print("1111")
class A_2:
def test(self):
print("2222")
class Test(A_1, A_2):
pass
# 创建一个对象
t = Test()
t.test()
# ——>1111
print(Test.mro())
# ——>[<class '__main__.Test'>, <class '__main__.A_1'>, <class '__main__.A_2'>, <class 'object'>]