文章目录

  • 一、引言
  • 二、类
  • 三、面向对象的三大特征
    • 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>

面向对象编程——2.细致了解相关推荐

  1. 转载知乎上的一篇:“ 面向对象编程的弊端是什么?”

    2019独角兽企业重金招聘Python工程师标准>>> 弊端是,没有人还记得面向对象原本要解决的问题是什么. 1.面向对象原本要解决什么(或者说有什么优良特性) 似乎很简单,但实际又 ...

  2. 关于python面向对象编程中、下列说法中_关于Python面向对象编程的知识点总结

    前言 如果你以前没有接触过面向对象的编程语言,那你可能需要先了解一些面向对象语言的一些基本特征,在头脑里头形成一个基本的面向对象的概念,这样有助于你更容易的学习Python的面向对象编程. 接下来我们 ...

  3. python浓缩(13)面向对象编程

    为什么80%的码农都做不了架构师?>>>    本章主题 ? 引言 ? 面向对象编程 ? 类 ? 实例 ? 绑定与方法调用 ? 子类,派生和继承 ? 内建函数 ? 定制类 ? 私有性 ...

  4. 【转载】面向对象编程的弊端是什么?

    弊端是,没有人还记得面向对象原本要解决的问题是什么. 1.面向对象原本要解决什么(或者说有什么优良特性) 似乎很简单,但实际又很不简单:面向对象三要素封装.继承.多态 (警告:事实上,从业界如此总结出 ...

  5. 面向对象编程的弊端是什么?

    现时C++可以说是支持OOP范式中最为常用及高性能的语言.虽然如此,在C++使用OOP的编程方式在一些场合未能提供最高性能. [1]详细描述了这个观点,我在此尝试简单说明.注意:其他支持OOP的语言通 ...

  6. SECTION 22 面向对象编程(一)

    面向对象编程(类) 22.1 介绍 22.1.1类与实例 22.1.2 方法 22.1.2.1 方法定义 22.1.2.2 创建一个类(类定义) 22.1.2.3 创建实例(实例化) 22.1.2.4 ...

  7. 【面向对象编程】(4) 类的继承,重构父类中的方法

    各位同学好,今天和大家分享一下面向对象编程中,类的三大特征之继承.主要介绍:子类继承父类的基本方法:重写父类的类方法:重构父类的初始化方法:super() 方法.本节主要是单继承,多继承在下一节中介绍 ...

  8. 【面向对象编程】(3) 类之间的交互,依赖关系,关联关系

    各位同学好,今天和大家分享一下面向对象编程中,类之间的交互,类之间的依赖关系和关联关系.有不明白的可见前一章节:https://blog.csdn.net/dgvv4/article/details/ ...

  9. 【面向对象编程】(1) 类实例化的基本方法

    各位同学好,本章节和大家分享一下面向对象编程的一些方法,通过一些案例带大家由浅入深掌握面向对象的编程. 1. 最基本的类实例化 创建类的方法是 class 变量名: ,实例化方法是 类名() ,分配属 ...

  10. C#编程概念系列(一):面向对象编程

    系列文章索引目录:http://www.cnblogs.com/loner/archive/2013/05/09/3068211.html 引子: 面向对象编程:这个在当下已不是什么时髦的概念,但通过 ...

最新文章

  1. BZOJ.3004.[SDOI2012]吊灯(结论)
  2. AMDF换成ACF和AMDF合作算法
  3. DL之DNN:自定义2层神经网络TwoLayerNet模型(计算梯度两种方法)利用MNIST数据集进行训练、预测
  4. loj 300 [CTSC2017]吉夫特 【Lucas定理 + 子集dp】
  5. ubuntu编译并调试OpenJDK8源码实践
  6. 2021网络药理学研究的免费数据库、在线平台与软件工具汇总整理介绍
  7. php获取标准输入输出,shell--标准输入输出(readamp;echo)
  8. BZOJ4681 [jsoi2010]旅行
  9. 一个使用指针的简单程序
  10. iOS 中delegate的理解与使用(传值)
  11. 《SQL Server 2000 完全实战:数据转换服务(DTS)》
  12. DropDownList 实现分页不包含选择值
  13. 【时间序列分析】03.正态时间序列与严平稳序列
  14. 信息学奥赛一本通在线评测平台的一些bug
  15. 最全iOS12捷径库收集整理,iOS12捷径推荐
  16. 02-准备实验环境(批量克隆)-011-DiskPart 遇到错误 介质受写入保护
  17. 云控系统都支持哪些安卓手机装机步骤
  18. 跨考计算机者艰难的2019自白
  19. 废土艺术风格 2丨游戏主题概念设计
  20. 北大深院计算机录取难度保饰,她高考685分被北大录取却哭了,看到她的书桌,大家沉默了...

热门文章

  1. 192B Walking in the Rain
  2. HDU 1500(经典的恶心DP)
  3. C# 0xC0000005 捕获
  4. Launch MySQL on my PC
  5. Python的基本数据类型(1)
  6. 常见排序算法以及对应的时间复杂度和空间复杂度
  7. Eclipse JSP 页面设置 charset=UTF-8
  8. 18107 校赛排名
  9. 遍历python字典几种方法
  10. CMake中include指令介绍