面向对象编程——2.细致了解

news/2024/11/8 17:00:01/

文章目录

      • 一、引言
      • 二、类
      • 三、面向对象的三大特征
        • 1.继承
        • 2.多态
        • 3.其他

一、引言

在上一篇文章中,我们以就面向对象编程进行了简单的介绍,这一章主要是进行一些细致补充与拓展,这部分内容在初学python时就已经学到了,现在回顾,没有做到学与用的结合,切记!!!

二、类

  • 1.类的定义

python中“一切皆对象”。类称为类对象,类的实例称为实例对象。
在这里插入图片描述

  • 2.构造函数__init__
    一个python对象含以下部分:
    在这里插入图片描述
    在这里插入图片描述
  • 3.实例属性
    实例属性是从属于实例对象的属性
    要点:
    在这里插入图片描述
  • 4.实例方法
    实例方法是从属于实例对象的方法。
    定义格式:
    在这里插入图片描述
    在这里插入图片描述
    函数和方法的区别:
    在这里插入图片描述
    在这里插入图片描述
    例子:
class Bettery():"""模拟电动汽车的电池"""def __init__(self, bettery_size=70):self.bettery_size = bettery_size  # 电池容量self.electric_quantity = bettery_size  # 电池剩余容量self.electric_distance_ratio = 5  # 电量距离换算系数self.remainder_range = self.electric_quantity *self.electric_distance_ratio  # 剩余可行驶距离def get_electric_quantity(self):"""查看当前容量"""print("当前电池剩余电量:{}kw.h".format(self.electric_quantity))def set_electric_quantity(self, electric_quantity):"""设置电池剩余电量,重新计算电量可支撑行驶里程"""if electric_quantity > 0 and electric_quantity < self.bettery_size:self.electric_quantity = electric_quantityself.remainder_range = self.electric_quantity * self.electric_distance_ratioelse:print("电量未设置在合理范围内!")def get_remainder_range(self):"""查看剩余可行驶里程"""print("当前电量还可以继续行驶{}公里".format(self.remainder_range))class Car():"""模拟汽车"""def __init__(self, brand, model, year):"""初始化汽车属性"""self.brand = brand  # 品牌self.model = model  # 型号self.year = year  # 出厂年份self.mileage = 0  # 里程碑数def get_main_information(self):  # self不能省"""获取汽车主要信息"""print("品牌:{},型号:{},出厂年份:{}".format(self.brand, self.model,self.year))def get_all_mileage(self):"""获取总里程数"""return "行车总里程:{}公里".format(self.mileage)class ElectricCar(Car):"""模拟电动汽车"""def __init__(self, brand, model, year, bettery_size):"""初始化电动汽车属性"""super().__init__(brand, model, year)self.bettery = Bettery(bettery_size)  # 电池def get_main_information(self):  # 重写父类方法"""获取电动车的主要信息"""print("品牌:{}  型号:{}  出厂年份:{}  续航里程数:{}公里".format(self.brand, self.model, self.year,self.bettery.bettery_size * self.bettery.electric_distance_ratio))my_electric_car = ElectricCar("NextWeek", "FF91", 2046, 70)
# 获取车辆主要信息
my_electric_car.get_main_information()
# 获取当前电池量
my_electric_car.bettery.get_electric_quantity()
# 重设电量
my_electric_car.bettery.set_electric_quantity(50)
# 获取当前电量
my_electric_car.bettery.get_electric_quantity()
# 获取当前剩余可行驶里程数
my_electric_car.bettery.get_remainder_range()# 获得对象的所有属性与方法
print(dir(my_electric_car))
# 获得对象的属性字典
print(dir(my_electric_car.__dict__))
# 判断对象是不是指定类型
print(isinstance(my_electric_car,ElectricCar))# 品牌:NextWeek  型号:FF91  出厂年份:2046  续航里程数:350公里
# 当前电池剩余电量:70kw.h
# 当前电池剩余电量:50kw.h
# 当前电量还可以继续行驶250公里
# ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'bettery', 'brand', 'get_all_mileage', 'get_main_information', 'mileage', 'model', 'year']
# ['__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']
# True

创建过程
实例化对象时,先通过__new__创建对象,然后将对象地址传给__init__中的self参数,__init__用于初始化创建好的对象,最后再将创建好的对象地址返回给相应变量。

5.类对象
当解释器执行class语句时,就会创建一个类的类型对象(type)

class Student:        #创建Student类的类型对象(type)def __init__(self,name,score):self.name = nameself.score = scoredef say_score(self):print("{0}的分数是{1}".format(self.name,self.score))stu = Student       #指向同一个类对象
s1 = stu("柳杰","100")
s2 = stu("谈昊田","99")
print(s1)
print(s2)
s1.say_score()
s2.say_score()
>>>
<__main__.Student object at 0x000001FE3C28F160>
<__main__.Student object at 0x000001FE3C28F128>
柳杰的分数是100
谈昊田的分数是99

6.类属性
类属性从属于类对象,可以被所有实例对象共享
在这里插入图片描述
类中或者类的外面,可以通过类名.类变量名来读写
类属性常用于计数(实例对象创建的数量),如下:
在这里插入图片描述
内存分析:
在这里插入图片描述
7.类方法
在这里插入图片描述

#类方法只存在于Student类的类型对象里,而不存在于实例对象里
class Student:company = "SXT"@classmethoddef printCompany(cls):print(cls.company)Student.printCompany()
>>>
SXT

8.静态方法
在这里插入图片描述

class Student:commpany = "SXT"@staticmethoddef add(a,b):print("{0}+{1}={2}".format(a,b,(a+b)))Student.add(5,6)
>>>
5+6=11

9.__del__析构方法
在这里插入图片描述

#析构方法测试
class Person:def __del__(self):print("销毁对象:{0}".format(self))p1 = Person()
p2 = Person()
>>>
销毁对象:<__main__.Person object at 0x000001C3C9266940>
销毁对象:<__main__.Person object at 0x000001C3C955A048>

内存分析
在这里插入图片描述

#析构方法测试
class Person:def __del__(self):print("销毁对象:{0}".format(self))p1 = Person()
p2 = Person()
del p1
del p2
>>>
销毁对象:<__main__.Person object at 0x000001C3C9266940>
销毁对象:<__main__.Person object at 0x000001C3C955A048>

10.__call__方法
定义了__call__方法的对象,称为可调用对象。即该对象可以像函数一样被调用


# 测试可调用方法__call__
class SalaryAccount:def __call__(self,salary):print("算工资啦!")monthsalary = salaryyearsalary = salary * 12daysalary = salary/22.5hoursalary = daysalary/8return dict(yearsalary = yearsalary,monthsalary = monthsalary,daysalary = daysalary,hoursalary = hoursalary)s = SalaryAccount()
print(s(15000))
>>>
算工资啦!
{'yearsalary': 180000, 'monthsalary': 15000, 'daysalary': 666.6666666666666, 'hoursalary': 83.33333333333333}

11.方法没有重载
在这里插入图片描述
在这里插入图片描述
12.方法的动态性
在这里插入图片描述

# 测试方法的动态性-方法是对象,函数是对象,一切皆对象
class Person:def work(self):print("好好上班!!!")def playGame(s):print("{}在玩游戏!".format(s))
def work2(s):print("好好工作,努力上班,赚大钱,娶媳妇!!!")p = Person()
p.work()
Person.play = playGame          #为类添加新的方法
p.play()                        #Person.play(p)Person.work = work2             #动态地修改类已有的方法
p.work()
>>>
好好上班!!!
<__main__.Person object at 0x000001C34848F160>在玩游戏!
好好工作,努力上班,赚大钱,娶媳妇!!!

13.私有属性和私有方法(实现封装)
要点:
在这里插入图片描述
注:方法本质上也是属性,只不过是可以通过()来执行。

# 测试私有属性
class Employee:def __init__(self, name, age):self.name = nameself.__age = age     #私有属性e = Employee("柳杰", "23")
# print(e.__age)             #__age属性私有化,'Employee' object has no attribute 'age'
print(e._Employee__age)   #访问私有属性
print(dir(e))
>>>
23
['_Employee__age', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name']
# 测试私有方法
class Employee:def __init__(self, name, age):self.name = nameself.__age = agedef __work(self):               #私有方法print("好好工作,努力上班,赚大钱,娶媳妇!!!")print("年龄:{}".format(self.__age))      # 类内部可以访问私有属性(或方法)e = Employee("柳杰", "23")
# e.__work()                  #AttributeError: 'Employee' object has no attribute '__work'
e._Employee__work()
>>>
好好工作,努力上班,赚大钱,娶媳妇!!!
年龄:23

14.@property装饰器_get和set方法
@property可以将一个方法的调用方式变成了“属性调用”。

# 方法的调用
class Employee:def __init__(self,name,salary):self.__name = nameself.__salary = salarydef getSalary(self):return self.__salarydef setSalary(self,salary):if 1000 < salary <= 50000:self.__salary = salaryelse:print("工资录入错误!!!薪水应该在1000-50000之间")e = Employee("柳杰","25000")
print(e.getSalary())
e.setSalary(30000)
print(e.getSalary())
>>>
25000
30000
# 测试@property装饰器的用法-属性的调用
class Employee:def __init__(self,name,salary):self.__name = nameself.__salary = salary@propertydef salary(self):return self.__salary@salary.setterdef salary(self,salary):if 1000 < salary <= 50000:self.__salary = salaryelse:print("工资录入错误!!!薪水应该在1000-50000之间")
e = Employee("柳杰","25000")
print(e.salary)
e.salary = 30000
print(e.salary)
>>>
25000
30000

三、面向对象的三大特征

三大特征:继承、封装、多态

  • 继承:继承可以让子类具有父类的特性,提高代码的重用性。 在原有父类设计不变的情况下,可以增加新功能或改进已有算法
  • 封装:隐藏对象的属性和实现细节,只对外提供必要的方法。 通过私有属性、私有方法进行封装,更多依靠程序员自觉完成
  • 多态:是指同一种方法调用由于对象不同会产生不同的行为

1.继承

在这里插入图片描述

class Person:def __init__(self,name,age):self.name = nameself.__age = age        #私有属性def sayAge(self):print("年龄,年龄,我也不知道!!!")
class Student(Person):def __init__(self,name,age,score):Person.__init__(self,name,age)      # 必须显式的调用父类的方法,不然解释器不会去调用self.score = scores = Student("柳杰","23","100")
s.sayAge()
print(s.name)
print(dir(s))
print(s._Person__age)         # 必须用访问私有属性的方法,访问父类里的私有属性
>>>
年龄,年龄,我也不知道!!!
柳杰
['_Person__age', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name', 'sayAge', 'score']
23

1)类成员的继承和重写
在这里插入图片描述

# 测试继承的基本使用
class Person:def __init__(self,name,age):self.name = nameself.__age = age        #私有属性def sayAge(self):print("我的年龄是",self.__age)def sayIntroduce(self):print("我的名字是",self.name)
class Student(Person):def __init__(self,name,age,score):Person.__init__(self,name,age)      #必须显式的调用父类的方法,不然解释器不会去调用self.score = scoredef sayIntroduce(self):'''重写了父类的方法'''print("报告老师!我的名字是{}".format(self.name))s = Student("柳杰","23","100")
s.sayAge()
s.sayIntroduce()
print(Student.mro())   #print(Student.__mro__)输出这个类的继承层次结构
>>>
我的年龄是 23
报告老师!我的名字是柳杰
[<class '__main__.Student'>, <class '__main__.Person'>, <class 'object'>]

2)查看类的层次结构
通过类的方法mro()或者类的属性__mro__输出这个类的继承层次结构
3)object根类
object类是所有类的父类,因此所有类都有object类的属性和方法
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
4)重写__str__方法
在这里插入图片描述

# 测试重写object对象的__str__()
class Person:def __init__(self,name):self.name = namedef __str__(self):return "名字是{}".format(self.name)
p = Person("柳杰")
print(p)
>>>
名字是柳杰

5)多重继承
在这里插入图片描述
在这里插入图片描述
**MRO方法解析顺序:**广度优先算法
在这里插入图片描述
6)super()获得父类定义
在这里插入图片描述

# 测试super()代表父类的定义,而不代表父类的对象
class A:def say(self):print("A:",self)
class B(A):def say(self):super(B, self).say()            #A.say()print("B:",self)
B().say()
>>>
A: <__main__.B object at 0x00000131F855BFD0>
B: <__main__.B object at 0x00000131F855BFD0>

2.多态

在这里插入图片描述

# 多态
class Man:def eat(self):print("饿啦,吃饭了!!!")
class Chinese(Man):def eat(self):print("中国人用筷子吃饭!!!")
class English(Man):def eat(self):print("英国人用叉子吃饭!!!")
class India(Man):def eat(self):print("印度人用右手吃饭!!!")def manEat(m):if isinstance(m,Man):m.eat()else:print("传入错误!!!")manEat(Chinese())       #同一方法调用,由于对象不同可能产生不同的行为
manEat(English())
manEat(India())
>>>
中国人用筷子吃饭!!!
英国人用叉子吃饭!!!
印度人用右手吃饭!!!

3.其他

1)特殊方法和运算符重载
在这里插入图片描述
在这里插入图片描述

# 测试运算符的重载
class Person:def __init__(self,name):self.name = namedef __add__(self,other):if isinstance(other,Person):return "{0}--{1}".format(self.name,other.name)else:return "不是同类对象,不能相加!!!"def __mul__(self, other):if isinstance(other,int):return self.name * otherelse:return "不是同类对象,不能相乘!!!"p1 = Person("柳杰")
p2 = Person("谈昊田")
x = p1 + p2
print(x)
print(p1*5)
print(x*5)
>>>
柳杰--谈昊田
柳杰柳杰柳杰柳杰柳杰
柳杰--谈昊田柳杰--谈昊田柳杰--谈昊田柳杰--谈昊田柳杰--谈昊田

2)特殊属性
在这里插入图片描述
3)对象的浅拷贝和深拷贝
在这里插入图片描述

# 测试浅拷贝和深拷贝
# 组合关系
import copy
class MobilePhone:def __init__(self,cpu,screen):self.cpu = cpuself.screen =screenclass CPU:def calculate(self):print("算你个12345")print("cpu对象:",self)
class Screen:def show(self):print("显示一个好看的图片")print("screen对象:",self)
print("测试浅复制")
#测试浅拷贝
c1 = CPU()
s1 = Screen()
m1 = MobilePhone(c1,s1)
m2 = copy.copy(m1)
print(m1,m1.cpu,m1.screen)
print(m2,m2.cpu,m2.screen)print("测试深拷贝")
#测试深拷贝
m3 = copy.deepcopy(m1)
print(m1,m1.cpu,m1.screen)
print(m3,m3.cpu,m3.screen)
>>>
测试浅复制
<__main__.MobilePhone object at 0x00000106A796C4E0> <__main__.CPU object at 0x00000106A796C4A8> <__main__.Screen object at 0x00000106A796C128>
<__main__.MobilePhone object at 0x00000106A79730F0> <__main__.CPU object at 0x00000106A796C4A8> <__main__.Screen object at 0x00000106A796C128>
测试深拷贝
<__main__.MobilePhone object at 0x00000106A796C4E0> <__main__.CPU object at 0x00000106A796C4A8> <__main__.Screen object at 0x00000106A796C128>
<__main__.MobilePhone object at 0x00000106A796F048> <__main__.CPU object at 0x00000106A89E79B0> <__main__.Screen object at 0x00000106A89E7DA0>

4)组合
在这里插入图片描述

# 测试组合
class A:def say_a(self):print("我是a,a,a")
class B:def __init__(self,a):       # 把a的对象作为属性self.a = a
a = A()
b = B(a)
b.a.say_a()
>>>
我是a,a,a
# 测试has-a关系,使用组合
class MobilePhone:def __init__(self,cpu,screen):self.cpu = cpuself.screen =screenclass CPU:def calculate(self):print("算你个12345")print("cpu对象:",self)
class Screen:def show(self):print("显示一个好看的图片")print("screen对象:",self)c1 =CPU()
s1 = Screen()
m1 = MobilePhone(c1,s1)         # 组合的关系
m1.cpu.calculate()
m1.screen.show()
>>>
算你个12345
cpu对象: <__main__.CPU object at 0x00000233DA93C128>
显示一个好看的图片
screen对象: <__main__.Screen object at 0x00000233DA93C4A8>

5)工厂模式
工厂模式实现创建者和调用者的分离,使用专门的工厂类将选择实现类、创建对象进行统一管理

# 测试工厂模式
class CarFactory:def creat_car(self,brand):			#对创建对象进行管理if brand == "奔驰":return Benz()if brand == "宝马":return BMW()if brand == "比亚迪":return BYD()else:return "未知品牌,无法创建"class Benz:pass
class BMW:pass
class BYD:passfactory = CarFactory()
c1 = factory.creat_car("奔驰")
c2 = factory.creat_car("比亚迪")
print(c1)
print(c2)
>>>
<__main__.Benz object at 0x000001CED3F7C470>
<__main__.BYD object at 0x000001CED3F7C4A8>

6)单例模式
在这里插入图片描述

# 测试单例模式
class MySingleton:__obj = None            #类属性__init_flag = True      #标志,控制只进行一次初始化的属性def __new__(cls, *args, **kwargs):if cls.__obj == None:cls.__obj = object.__new__(cls)return cls.__objdef __init__(self,name):if MySingleton.__init_flag:print("init....")self.name = nameMySingleton.__init_flag = Falsea = MySingleton("aa")
b = MySingleton("bb")
print(a)
print(b)
>>>
init....
<__main__.MySingleton object at 0x000001EFE206BFD0>
<__main__.MySingleton object at 0x000001EFE206BFD0>
# 工厂模式和单例模式整合使用
class CarFactory:__obj = None  # 类属性__init_flag = True  # 标志def __new__(cls, *args, **kwargs):if cls.__obj == None:cls.__obj = object.__new__(cls)return cls.__objdef __init__(self):if CarFactory.__init_flag:print("init....")CarFactory.__init_flag = Falsedef creat_car(self,brand):if brand == "奔驰":return Benz()if brand == "宝马":return BMW()if brand == "比亚迪":return BYD()else:return "未知品牌,无法创建"
class Benz:pass
class BMW:pass
class BYD:pass
ggmian
c1 = CarFactory()
c2 = CarFactory()
print(c1)
print(c2)
>>>
init....
<__main__.CarFactory object at 0x0000022CCF59C128>
<__main__.CarFactory object at 0x0000022CCF59C128>

http://www.ppmy.cn/news/172080.html

相关文章

浮点型在内存中的存储,与整型存储方式竟然不同

对于整形的存储方式&#xff0c;大家可以看我的上一篇文章&#xff0c;这篇文章来介绍浮点型在内存中存储方式。 目录 1. 问题 2. 浮点型家族&#xff1a; 3. 存储方式: 4. 读取方式&#xff1a; 5. 解题 1. 问题 我们先来看一段代码&#xff1a; #include <stdio.h&…

[数据集][目标检测]目标检测数据集黄瓜数据集VOC格式1309张

数据集格式&#xff1a;Pascal VOC格式(不包含分割路径的txt文件和yolo格式的txt文件&#xff0c;仅仅包含jpg图片和对应的xml) 图片数量(jpg文件个数)&#xff1a;1308 标注数量(xml文件个数)&#xff1a;1308 标注类别数&#xff1a;1 标注类别名称:["cucumber"] 每…

WIFI抗干扰分析介绍及来源

目录 1.WLAN抗干扰分析 2.无线干扰的分类和来源 2.1.WLAN干扰 2.1.1. 同频干扰 2.1.2.邻频干扰 2.2.WLAN外部的干扰 3.无线干扰的检测 4.无线干扰的避免和消减 4.1.RRM 4.2.频谱分析 4.3.信道复用 5. 其他无线干扰避免和消减措施 6.结束语 1.WLAN抗干扰分析 今天&…

深入理解设计原则之里氏替换原则(LSP)

系列文章目录 C高性能优化编程系列 深入理解设计原则系列 深入理解设计模式系列 高级C并发线程编程 LSP&#xff1a;里氏替换原则 系列文章目录1、里氏替换原则的定义和解读2、里氏替换原则可以用于哪些设计模式中&#xff1f;3、如何使用里氏替换原则来降低代码耦合度&#…

Goby 漏洞更新 |海康威视部分iVMS系统存在文件上传漏洞

漏洞名称&#xff1a;海康威视部分iVMS系统存在文件上传漏洞 English Name&#xff1a;Some Hikvision iVMS file upload vulnerabilitie CVSS core: 9.8 影响资产数&#xff1a;15294 漏洞描述&#xff1a; 海康威视-iVMS综合安防管理平台是一套“集成化”、“数字化”、…

三菱FX3U——SFC单流程的使用

梯形图块中&#xff0c;LD M8002 SET S0&#xff1b;上电第一个上升沿置位S0&#xff1b; SFC中编写SFC流程和动作&#xff1b; PLC运行后&#xff0c;S0得电&#xff0c;等待转移0的条件满足&#xff1b; M0导通后转移&#xff1b; 步20得电&#xff0c;执行其中的动作&…

工控之台达HMI和三菱FX PLC连接

1.硬件准备 1.台达人机:DOP-B03E211;三菱PLC FX-3GE HMI设置: 一小段PLC程序: 注:PLC用的是编程口,三菱FX的编程口通讯是 RS422,通讯线链接: 威纶触摸屏MT6070接三菱FX系列PLC通讯线MT6000-FXTK6100-FX-淘宝网 (taobao.com)

三菱FX3U——SFC跳转的使用

PLC上电后S0得电&#xff1b; 转移0&#xff1a;M0导通后转移&#xff0c;步10得电&#xff1b; 步10得电&#xff0c;y10得电&#xff0c;定时器T0计时&#xff1b;计时到达后&#xff0c;D0加1&#xff1b; 转移5&#xff1a;T0计时到达&#xff0c;并且D0中的数值小于等于3&…