一、概念比较
-
面向过程&面向对象
- 面向过程:按解决问题的步骤,逐步进行;
- 面向对象:抽象出事物的属性和行为作为对象,通过对象及对象间关系解决问题
-
类&对象
- 类:对某类事物的抽象,是一个模板,包括属性和方法
- 对象:根据类创建的实例
-
函数&方法
- 函数:实现了单个或多个功能模块的代码块
- 方法:声明在类中,带有表示类或者当前对象的位置参数(如,cls,self),通过类名或者实例对象调用。
二、如何创建类
-
语法格式:def 类名[(父类)]: 类模块
''' # 定义类 def 类名(父类名): # 定义类对象 类对象 # 定义实例属性 #init初始化方法,创建实例时执行,用于挂载实例属性,self表示当前对象 def __init__(self,args...): self.实例属性名 = 属性值 ... # 定义类方法 @classmethod def 类方法名(cls): #cls表示类对象 ... # 定义实例方法 def 方法名(self,args...): ... '''
-
属性&方法
- 实例属性&类属性
对比项 实例属性 类属性 如何定义 定义在类的初始化方法中__init__ 直接定义在类中 如何访问 创建实例对象访问 约定用类名调用 备注 __init__为初始化方法,在创建实例时被执行。用于挂载实例属性 实际上用实例对象也可访问,但是约定用类名访问 例如 # 定义类A
class A:
def __init__(self,a,b):
self.a = a
self.b = b
# 创建实例对象,并访问实例属性
x = A(a1,b1)
print(x.a,x.b)
# 定义类B
class B:
c
# 约定用类名访问类属性
B.c
- 实例方法&类方法
对比项 实例方法 类方法 如何定义 定义在类中,带有表示当前对象的位置参数self 定义在类中,带有表示类对象的位置参数cls,且用装饰器@classmethod修饰 如何访问 创建实例对象访问 约定用类名访问 可访问属性 类属性(类名.类属性名)
类方法(类名.类方法)
实例属性(self.实例属性)
实例方法(self.实例方法)
类属性(类名/cls.类属性名)
类方法(类名/cls.类方法)
备注 self为约定命名 cls为约定命名 例如 # 定义类A
class A:
desc
def __init__(self,a,b):
self.a = a
self.b = b
@classmethod
def cmethod(cls):
print('class method')
def run(self):
print('self run')
# 实例方法中访问其他内容
def dosth(self):
print(self.a,A.desc)
self.run()
A.cmethod()
# 调用实例方法
x = A()
x.dosth()
# 定义类A
class A:
desc
def __init__(self,a,b):
self.a = a
self.b = b
@classmethod
def cmethod(cls):
print('class method')
def run(self):
print('self run')
# 类方法中访问其他内容
@classmethod
def clsdosth(cls):
print(A.desc,cls.desc)
A.cmethod()
cls.cmethod()
# 调用类方法
A.clsdosth()
- 动态添加类的属性、方法,实例对象的属性、方法
动态添加 添加方式 备注 例如 类属性 类名.类属性名 = 属性值 class A:
pass #占位符
A.desc = 'hello python'
类方法 类名.方法名 = 方法名1 定义方法1时:
如果没有形参,只能用类名调用;
如果有形参,可以是类对象、实例对象、普通实参;
如果用实例对象调用时,该方法至少有一个位置参数接收实例对象
class A:
pass
# 1.方法没有形参
def g1():
pass
A.cmethod1 = g1
# 调用
A.cmethod1()
# 2.方法有一个形参
def g2(self):
pass
A.cmethod2 = g2
# 调用
A.cmethod2(任意实参)
a.cmethod2() #其实已传入self
实例属性 实例对象.属性名 = 属性值 仅作用于当前实例对象 class A:
pass
x = A()
x.a = 'hello python'
实例方法 实例对象.方法名 = 方法名1 定义方法1无要求
仅作用于当前实例对象
class A:
pass
def run():
pass
x = A()
x.run = run
x.run()
- 实例属性&类属性
-
公有&私有
- 内部访问&外部访问:类内部访问称为内部访问;类外部访问称为外部访问。
- 私有&公有:
- 私有:仅内部访问。在名称前加两个下划线'__'。本质上,只是做了伪装,通过dir()可以找到对应属性或方法,一般为'_类名__属性名/方法名'。约定外部不访问。
- 公有:不仅内部访问,也可以外部访问
-
其他知识点
-
字符串的格式化方法
- '{}*****{}******'.format(arg1,arg2):表示占位{}分别用位置参数替换;如果{}中标记了数字(下标从0开始),则用对应位置的参数替换;
- f'{***}******{***}***':字符串前加f时,占位{}里直接添加参数
-
命名中下划线的用法
下划线位置 作用 例如 _(单下划线) 1. 在Python REPL(Read-Eval-Print Loop,读取-求值-打印 循环)交互式命令行界面中,表示查看上个指令执行结果;
2. 临时变量
3. 无关紧要变量,用于过滤数据中不需要的部分
# 1. 在命令行中输入_,回车,查看上个指令执行结果
# 2. 临时变量
for _ in range(2):
print(_)# 3. 无关紧要变量
li = [1,2,3]
a,_,_ = li #只想要a
_名(单下划线+名) 受保护的变量/函数 # demo1.py文件中
def _run():
pass
# demo2.py文件中
import demo1
demo1._run()#可访问
from demo1 import *
_run()#访问不到
名_(名+单下划线) 如果名是关键字,可在尾部加下划线加以区分 class_
def_
__名(双下划线+名) 私有,外部无法访问 __arg
__run()
__名__(双下划线+名+双下划线) 魔法方法,自定义不用此方式 __main__#主方法
__var__#执行模块名
-
三、面向对象的三个特征
-
封装:将属性和方法抽象到一个类中,作为整体对外提供访问
-
继承:实现代码重用,体现父类、子类关系
- 语法格式:class 类名(父类名):
- 继承
- 无法继承父类私有属性和方法
- 继承初始化方法:
- super(子类名,self).__init__(父类初始化参数序列)
- 父类名.__init__(self,父类初始化参数序列)
-
多态:在继承关系前提下,重写父类方法,使得不同类型的实例调用相同方法,返回不同的执行结果。