欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程语言 > python >内容正文

python

python面向对象生动讲解_Python面向对象语法精讲

发布时间:2025/3/20 python 41 豆豆
生活随笔 收集整理的这篇文章主要介绍了 python面向对象生动讲解_Python面向对象语法精讲 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

本专题的内容结构:

第一部分主要是:面向对象基础

第二部分主要是:面向对象进阶

第一部分的结构:

unit1:面向对象编程模式:

(1),面向对象编程思想

(2),面向对象的三个特征

(3),Python面向对象术语

unit2:Python类的构建:

(1),类的基本构建

(2),类的属性和方法

(3),类的构造函数和析构函数

unit3:实例1:银行ATM等待时间分析

(1),对象的设计和构建

(2),生活现象的程序分析

unit4:Python类的封装

(1),私有属性和公开属性

(2),私有方法和公开方法

(3),保留属性和保留方法

unit5:Python类的继承:

(1),子类,父类与超类

(2),类的方法重载和属性重载

(3),类的多继承

第二部分的结构:

unit1:Python类的运算:

(1),运算符的理解

(2),各类运算符的重载

unit2:Python类的多态:

(1),多态的理解

(2),参数类型的多态

(3),参数形式的多态

unit3:实例2:图像的四则运算

(1),PIL库和Numpy 库实践

(2),图像的加减乘除操作

unit4:Python对象的引用

(1),引用的理解

(2),浅拷贝和深拷贝

unit5:Python类的高级话题:

(1),类的特殊装饰器

(2),命名空间的理解

(3),类的名称修饰

第一部分的内容:

unit1:面向对象编程模式:

(1),万物皆对象:

自然意义上的对象:独立的存在 或 作为目标的事物

>独立性:对象都存在清晰的边界,重点在于划分边界

>功能性:对象都能表现出一些功能,操作或行为

>交互性:对象之间存在交互,如:运算和继承

Python语言的“万物皆对象”:

>Python语言中所有数据类型都是对象,函数是对象,模块是对象

>Python所有类都是继承于最基础类object

>Python语言中数据类型的操作功能都是类方法的体现

(2),面向对象编程思想:

OOP :Object-Oriented Programming

>OOP :面向对象编程,一种编程思想,重点在于高抽象的 复用代码

>OOP 把对象当做程序的基本单元,对象包含数据和操作数据的函数

>OOP 本质是把问题解决抽象为以对象为中心的计算机程序

注:

>OOP在较大规模或复杂项目中十分有用,OOP可以提高协作产量

>OOP最主要的价值在于代码复用

>OOP只是一种编程方式,并非解决问题的高级方法

面向过程 vs 面向对象

>面向过程:以解决问题的过程步骤为核心编写程序的方式

>面向对象:以问题对象构建和应用为核心编写程序的方式

>所有OOP能解决的问题,面向过程都能解决

小例子:

(3),面向对象的三个特征:

OOP的三个特征:

>封装:属性和方法的抽象,用数据和操作数据的方法来形成对象逻辑

>继承:代码复用的高级抽象,用对象之间的继承关系来形成代码复用

>多态:方法灵活性的抽象,让对象的操作更加灵活,更多复用代码

它能让更少的对象名称来支持更多的对象操作

它们都是表达了代码抽象和代码复用,

封装的理解:

封装Encapsulation:属性和方法的抽象

>属性的抽象:对类的属性(变量)进行定义,隔离及保护

>方法的抽象:对类的方法(函数)进行定义,隔离及保护

>目标是形成一个类/对象 对外可操作属性和方法的接口

继承的理解:

继承 Inheritance:代码复用的高级抽象

>继承是面向对象程序设计精髓之一

>实现了以类为单位的高抽象级别代码复用

>继承是新定义的类 能够几乎完全使用原有类属性和方法的过程

多态的理解:

多态 Polymorphism :仅针对方法,方法灵活性的抽象

>参数类型的多态:一个方法能够处理多个类型的能力

>参数形式的多态:一个方法能够接受多个参数的能力

>多态是 OOP的一个传统概念,Python天然支持多态,不需要特殊语法

其他语言中要用特定的语法用多态,但是Python中设计的弱类型天然支持多态

对多态的理解重点是概念和思路上的理解,更能理解Python对类的方法灵活性的抽象是如何表达的,

(4),Python面向对象术语:

先简要过一遍,后会介绍:

类 Class 和 对象 Object :

>类:逻辑抽象和产生对象的模板,一组变量和函数的特定编排

>对象:具体表达数据及操作的实体,相当于程序中的"变量"

>实例化:从类到对象的过程,所有"对象"都源于某个"类"

对象: 对象具体分为: 类对象和实例对象

类对象 vs 实例对象 :

>类对象:Class Object,当一个类建立之后,系统会维护个Python类基本信息的数据结构

>实例对象:Instance Object,Python类实例后产生的对象,简称:对象

>这是一组概念,类对象全局只有一个(保存类的基本信息),实例对象可以生成多个

属性: 存储数据的“变量”,分为 :类属性 和实例属性

方法: 操作数据的"函数",

包括:类方法,实例方法,自由方法,静态方法,保留方法

三个特性:封装继承多态

继承:基类,派生类,子类,父类,超类,重载

命名空间:程序元素作用域的表达

构造和析构:生成对象和删除对象的过程

(5),Python面向对象实例入门:

是上面的那个例子,计算价格的和,

出现新的保留字class

它可以定义抽象的Product 类,

1 classProduct():2 def __init__(self,name):3 self.name =name4 self.label_price =05 self.real_price =06

7 c = Product("电脑")8 d = Product("打印机")9 e = Product("投影仪")10 c.label_price,c.real_price = 10000,8000

11 d.label_price,d.real_price = 2000,1000

12 e.label_price,e.real_price = 1500,900

13 s1 ,s2 =0,014 for i in[c,d,e]:15 s1+=i.label_price16 s2+=i.real_price17 print(s1,s2)

View Code

unit2:Python类的构建:

python类的构建需要关注的地方:

就是上面的那个图:它包含了构建一个类所要关注的方方面面:

(1),类的基本构建:

使用class保留字定义类:

class <类名>:

[可以写个类描述字符串"documentation string"]

<语句块>

注:类定义不限位置,可以包含在分支或其他从属语句块中,执行时存在即可

可以放在全局部分,也可以放在分支,函数,等从属语句块中,由于Python语言是脚本语言,

所以在某个对象引用之前,只要是类被定义就可以。

类构造之类的名字:可以是任意有效标识符,建议采用大写单词的组合

如:ClassName ,BasicAuto ,BasicCreature

类构造之类描述:在类的定义后首行,以独立字符串形式定义

定义可以通过<类名>.__doc__属性来访问

注:像这种前后都有两个下划线的属性是Python给类保留的属性,

class DemoClass:

"This is a demo for Python class"

pass

print(DemoClass.__doc__)

>>>This is a demo for Python class

介绍一个概念:类对象

大家不要把类和对象拆开,类对象是一个名词,(Class Object)

>类定义完成后,默认生成一个类对象

与其他语言不同,python的类只要定义完就会生成一个对象,但这个对象呢?只是与这个类唯一对应的,

每一个类只唯一对应一个类对象,这个类对象是存储这个类的基本信息的

>每个类唯一对应一个类对象,用于存储这个类的基本信息

>类对象是type类的实例,表达为type类型

什么是type类型呢?

它是编译器提供了一种类型,

class DemoClass:

"This is a demo for Python class"

print("hello DemoClass")

print(type(DemoClass))

输出:

hello DemoClass

我们发现,我们只是定义了这个类,但是它也执行print("hello DemoClass)

这时因为在python中只要这个类被定义了, 就会生成一个表达它信息的 类对象

这个类对象是内置包含在类的定义中的,

那么这个类对象的生成使得类定义中的一些语句被执行,

因此,我们一般不在类的定义中直接包含语句,而是通过属性和方法来增加操作功能

类对象并不是使用类的常用方式,

使用类的方式最常用的是:通过创建实例对象来使用类的功能

<对象名> = <类名>([<参数>])

进一步采用<对象名>.<属性名>和<对象名>.<方法名>()体现类的功能

实例对象的类型:

它所生成时的那个类的类型

class DemoClass:

"This is a demo for Python class"

pass

print(type(DemoClass))

cn = DemoClass()

print(type(cn))

输出:

所以,实例对象和类对象是不一样的 ,

实例对象是最常用的方式,

了解Python类的构造函数

>类的构造函数用于从类创建实例对象的过程

>类的构造函数为实例对象创建提供了参数输入方式

>类的构造函数为实例属性的定义和赋值提供了支持

了解Python类的属性和方法:

>类的属性:类中定义的变量,采用描述类的一些特性参数

>类的方法:类中定义且与类相关的函数,用来给出类的操作功能

>属性和方法是类对外交互所提供的两种接口方式

(2),类的构造函数:

类的构造函数是从类生成实例对象所使用的函数,

Python中使用预定义的__init__()作为构造函数,

clsaa <类名>:

def __init__(self,<参数列表>)

<语句块>

类实例化时所使用的函数,可以接收参数并完成初始化操作

class DemoClass:

def __init__(self,name):

print(name)

dc1 = DemoClass("老王")

dc2 = DemoClass("老李")

输出:

老王

老李

注:通过构造函数__init__()可以为Python对象提供参数

还有,构造函数默认有个参数self ,它内部使用的,默认保留的,

__init__()的使用说明:

>参数:第一个参数约定是self,表示类实例自身,其他参数都是实例参数

>函数名:Python解释器内部定义的,由双下划线开始和结束

>返回值:构造函数没有返回值,或返回None ,否则产生TypeError异常

self在类定义内部代表类的实例

>self是Python面向对象中约定的一个类参数

>self代表类的实例,在类内部,self用于组合访问实例相关的属性和方法

>相比较而言,类名代表类对象本身

(3),类的属性:

属性是类内部定义的变量

>类属性:类对象的属性,由所有实例对象共享

>实例属性:实例对象的属性,由各实例所独享

类的属性和实例属性是如何定义的?

我们知道属性是变量,类中有两个地方可以放变量,

第一个是在class的全局命名空间:

<类属性名> =<类属性初值>

第二个是在函数/方法中定义的它就是实例属性:

class <类名>:

<类属性名>=<类属性初值>

def __init__(self,<参数列表>):

self.<实例属性名> = <实例属性初值>

...

class DemoClass:

count = 0 #直接在类中定义或赋值 无论在类内类外,访问类属性都要用<类名>.<属性名>来访问

def __init__(self,name,age):

self.name = name

self.age = age

DemoClass.count +=1

dc1 = DemoClass("老王",45)

dc2 = DemoClass("老李",51)

print("总数:",DemoClass.count)

print(dc1.name,dc2.name)

我们已经知道,类属性在类内,类外都是<类名>.<类属性>

而对于实例属性:

在类内部,用self.<属性名>访问

在类外部,用<对象名>.<属性名>访问

注:在类外,类属性也是可以用<对象名>.<属性名>来访问的

class DemoClass:

def __init__(self,name):

self.name = name

#注:构造函数没有返回值

def luckey(self):

s = 0

for c in self.name:

s+=ord(c)%100

return s

dc1 = DemoClass("Wang")

dc2 = DemoClass("Li")

print(DemoClass.__dict__) #类对象的属性字典

print(dc1.__dict__) #实例对象的属性字典

print(dc2.__dict__) #实例对象的属性字典

print(DemoClass.__dir__(DemoClass)) #类对象的属性列表

print(dc1.__dir__()) #实例对象的属性列表

(4),类的方法:

方法是类内部定义的函数:

>实例方法:实例对象的方法,由各实例对象独享,最常用的形式

>类方法:类对象的方法,由所有实例对象共享

>自由方法:类中的一个普通函数,由类所在命名空间管理,类对象独享

>静态方法:类中的一个普通函数,由类对象和实例对象共享

>保留方法:由双下划线开始和结束的方法,保留使用,如__len__()

方法1:实例方法:

实例方法是类内部定义的函数,与实例对象相关

class <类名>:

def <方法名>(self,<参数列表>):

...

实例方法采用<对象名>.<方法名>(<参数列表>)方式使用

class DemoClass:

def __init__(self,name):

self.name = name

#注:构造函数没有返回值

def luckey(self):

s = 0

for c in self.name:

s+=ord(c)%100

return s

dc1 = DemoClass("Wang")

dc2 = DemoClass("Li")

print(dc1.name,"'s lucky number is :",dc1.luckey())

print(dc2.name,"'s lucky number is :",dc2.luckey())

输出:

Wang 's lucky number is : 197

Li 's lucky number is : 81

方法2:类方法:

类方法是与类对象相关的函数,由所有实例对象共享

class <类名>:

@classmethod装饰器

def <方法名>(cls,<参数列表>):

...

类方法采用<类名>.<方法名>(<参数列表>)或<对象名>.<方法名>(<参数列表>)方式使用

>类方法至少包含一个参数,表示类对象,建议使用cls

>@classmethod是装饰器,类方法定义必须要有

>类方法只能操作类属性和其他类方法,不能操作实例属性和实例方法

class DemoClass:

count =0

def __init__(self,name):

self.name = name

DemoClass.count +=1

#注:构造函数没有返回值

@classmethod

def getChrCount(cls):

s = "0123456789"

return s[DemoClass.count]

dc1 = DemoClass("Wang")

dc2 = DemoClass("Li")

print(DemoClass.getChrCount())

print(dc1.getChrCount()) #类方法是可以被实例对象调用的,因为它归类对象和实例对象共同所有

输出:

2

2

方法3,自由方法:

是定义在类命名空间中的普通函数

class <类名>:

def <方法名>(<参数列表>):

...

#注:这里既没有self,也没有cls

自由方法采用<类名>.<方法名>(<参数列表>)方式使用,这时的<类名>代表的是命名空间

换句话说,自有方法是什么,它是在<类名>这个命名空间中定义的一个函数,访问它只能用

<函数名>.方法名来访问,

注:类对象自己独有

>自由方法不需要self,cls这类参数,可以没有参数

>自由方法只能操作类属性和类方法,不能操作实例属性和实例方法

>自由方法的使用只能用<类名>

严格来说,自由方法就不应该算是方法,它就是个函数,只不过是定义在类的命名空间中

为了统一说法,所以我们叫它自由方法,

class DemoClass:

count =0

def __init__(self,name):

self.name = name

DemoClass.count +=1

#注:构造函数没有返回值

def func():

DemoClass.count *=100

return DemoClass.count

dc1 = DemoClass("Wang")

print(DemoClass.func())

输出:100

方法4:静态方法:

我们知道,自由方法只能由类对象来使用,有没有办法让实例对象使用普通的函数(没有self,cls)呢?

可以,就是在自由方法的基础上加上一个装饰器@classmethod就可以了,

它是定义在类中的普通函数,能够被所有实例对象共享

class <类名>:

@staticmethod

def <方法名>(<参数列表>):

...

静态方法采用<类名>.<方法名>(<参数列表>)或<对象名>.<方法名>(<参数列表>)方式使用

>静态方法可以没有参数,可以理解为定义在类中的普通函数

>@staticmethod是装饰器,静态方法必须用它

>静态方法只能操作 类属性和其他类 方法,不能操作实例属性和实例方法

>相比于自由方法,静态方法能够使用<类名>和<对象名>两种方式调用

class DemoClass:

count =0

def __init__(self,name):

self.name = name

DemoClass.count +=1

#注:构造函数没有返回值

@staticmethod

def func():

DemoClass.count *=100

return DemoClass.count

dc1 = DemoClass("Wang")

print(dc1.func())

print(DemoClass.func())

记时,方法3和方法4一起记

方法5:保留方法:

保留方法由双下划线开始和结束的方法,保留使用

class <类名>:

def <保留方法名>(self,<参数列表>):

...

保留方法一般都对应类的某种操作,使用操作符调用它

其实构造函数本身也是保留方法,

class DemoClass:

count =0

def __init__(self,name):

self.name = name

DemoClass.count +=1

#注:构造函数没有返回值

def __len__(self):

return len(self.name)

dc1 = DemoClass("Wang")

print(len(dc1))

输出:4

__len__ ()方法对应内置函数len()函数操作

理解:

这时Python解释器保留方法,已经对应,只需要编写代码即可

重写保留方法:

class DemoClass:

count =0

def __init__(self,name):

self.name = name

DemoClass.count +=1

#注:构造函数没有返回值

def __len__(self):

return 5

dc1 = DemoClass("Wang")

print(len(dc1))

输出:5

终结总结:

我们可以理解为len()只能计算基本数据类型的长度,对于类的长度它不能计算

我们就让他去调用类的保留方法__len__()

len(dc1)其实它还是调用的是dc1.__len__()方法

然后:这个保留方法内部计算了一个基础类型的长度len(name)

(5),类的析构函数:

当一个对象不用的时候,我们要对它释放空间,

Python使用预定义的__del__()作为析构函数

class <类名>:

def __del__(self):

<语句块>

...

析构函数在“真实” 删除实例对象时被调用

“真实”后面会介绍

例子:

class DemoClass:

def __init__(self,name):

self.name = name

def __del__(self):

print("再见",self.name)

dc1 = DemoClass("Wang")

del dc1

输出:

再见Wang

删除对象就是使用保留字del

使用del删除对象且对象被真实删除 时调用析构函数__del__()

>函数名和参数:Python解释器内部约定,保留方法

>调用条件:当实例对象被“真实删除”时,才调用该函数语句

>“真实删除”:当前对象的引用数为0或当前程序退出(垃圾回收)

例子:

import time

class DemoClass:

def __init__(self,name):

self.name = name

def __del__(self):

print("再见",self.name)

dc1 = DemoClass("Wang")

dc2 = dc1 #引用

del dc1

print(dc2.name)

while(True):

time.sleep(1) #使程序不退出

输出:

Wang

这就是只有当真实删除时才会调用析构函数

当然,一般构建对象的时候,我们不用写析构函数,python的垃圾回收机制已经很灵活了。

Python类的内存管理:

>在删除对象前,Python解释器会检查引用次数

>检查删除之后是否引用次数为0,不为0则仅删除当前引用;为0,则删除对象

>如果程序退出,则由垃圾回收机制删除对象

那么如何对一个对象的引用数量进行获取呢?

python提供了一个sys.getrefcount(<对象名>)获得对象的引用次数

>返回对象引用次数的方法,辅助删除对象时的分析

>sys.getrefcount()函数返回值为 被 引用值+1

>非特定目的,不建议自己写析构函数,利用Python垃圾回收机制就行

import sys

class DemoClass:

def __init__(self,name):

self.name = name

def __del__(self):

print("再见",self.name)

dc1 = DemoClass("Wang")

dc2 = dc1 #引用

print(sys.getrefcount(dc1))

输出:3 (比真实多1)

unit3:实例1:银行ATM等待时间分析:

需求分析:

可扩展为泊松分布:

1 importrandom as rd2 '''

3 整体思路:4 1,需要一个全局时间5 2,以ATM每次处理结束的时间为时间驱动事件6 3,需要一个等待队列,维护客户到达时间7 4,时间变化时,驱动等待队列变化8 '''

9 classATM():10 def __init__(self,maxtime = 5):11 self.t_max =maxtime12 def getServCompleteTime(self,start= 0):#完成一次业务的时间 start 可赋值给真实的时间,

13 #这样就是绝对的时间了

14 return start + rd.randint(1,self.t_max)15

16 classCustomers():17 def __init__(self,n):18 self.count =n19 self.left =n20 def getNextArrvTime(self,start = 0,arrvtime = 10): #下一个人到达的时间

21 if self.left !=0:22 self.left -=1

23 return start +rd.randint(1,arrvtime)24 else:25 return026 def isOver(self): #判断n 个客户是否都到达了

27 return True if self.left == 0 elseFalse28

29 c = Customers(100) #100个客户

30 a =ATM()31 wait_list =[] #存放用户到达时间

32 wait_time =0 #总共等待时间

33 cur_time= 0 #当前时间

34 cur_time +=c.getNextArrvTime()35 wait_list.append(cur_time)36 while len(wait_list) !=0 or notc.isOver():37 if wait_list[0] <= cur_time: #用户提前到了

38 next_time = a.getServCompleteTime(cur_time) #下次时间

39 delwait_list[0]40 else:41 next_time = cur_time +1

42

43 if not c.isOver() and len(wait_list) ==0:44 next_arrv =c.getNextArrvTime(cur_time)45 wait_list.append(next_arrv)46

47 if not c.isOver() and wait_list[-1]

<

<<

<

<

<<

<

<<<<

<

<<

<

<<

<

<<

<

<<

<<<<

<

<<

<

<

<

<

<<

<

<

<<

<<

<<

<<<

<

<

<

<<&

<

&other

<<

<

<<

<<<<<

<<

<

<

<

<<

<

<

<

总结

以上是生活随笔为你收集整理的python面向对象生动讲解_Python面向对象语法精讲的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。