【编程语言】python面向对象知识整理

该博客围绕Python展开,介绍了类和对象,包括定义类、创建对象、魔法方法等;阐述面向对象的三大特性,如封装、继承、多态;讲解异常处理,包含了解异常、捕获异常语法和自定义异常;还提及模块和包,如模块的导入、制作,包的制作和导入等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、类和对象

类和对象的关系:⽤类去创建⼀个对象,类是对⼀系列具有相同特征和⾏为的事物的统称,是⼀个抽象的概念,不是真实存在的事物,对象是类创建出来的真实存在的事物

1. 定义类

  • 类名要满⾜标识符命名规则,同时遵循⼤驼峰命名习惯
  • 语法
class 类名():
	代码
# 例:定义类
class A():
	def test(self):
		print('hello world')

1、理解self

  • self指的是调⽤该函数的对象,打印对象和self得到的结果是⼀致的,都是当前对象的内存中存储地址
class TestClass():
	def test1(self):
		print('hello world')
		print(self)

testclass= TestClass()
print(testclass)
testclass.test1()
# <__main__.Washer object at 0x000001C1820D1850>
# hello world
# <__main__.Washer object at 0x000001C1820D1850>

2. 创建对象

  • 语法:对象名 = 类名()
# 例:创建对象
class A():
	def test(self):
		print('hello world')
		
a = A()

2、添加和获取对象属性

  • 类外⾯添加和获取对象属性,语法:对象名.属性名 = 值

  • 类外面获取对象属性,语法:对象名.属性名

  • 类⾥⾯获取对象属性,语法:self.属性名

class TestClass():
	def test1(self):
		print(f'hello world {self.attribute1}')

testclass= TestClass()
testclass.attribute1 = 100
testclass.test1()
# hello world 100

3. 魔法方法

1、__init__()

  • 不带参数的__init__(),作⽤:初始化对象
  • 在创建⼀个对象时默认被调⽤,不需要⼿动调⽤
  • self参数不需要手动传递,python解释器会⾃动把当前的对象引⽤传递过去
class TestClass():
	def __init__(self):
		self.attribute1 = 100
	def test1(self):
		print(f'hello world {self.attribute1}')

testclass= TestClass()
testclass.test1()
# hello world 100
  • 带参数的__init__(),作⽤:对不同的对象设置不同的初始化属性
class TestClass():
	def __init__(self,num):
		self.attribute1 = num
	def test1(self):
		print(f'hello world {self.attribute1}')

testclass= TestClass(100)
testclass.test1()
# hello world 100

2、__str__()

  • 当使⽤print输出对象的时候,默认打印对象的内存地址;如果类定义了 __str__ ()方法,那么就会打印出在这个方法中 return的数据
class TestClass():
	def __init__(self,num):
		self.attribute1 = num
	def __str__(self):
		return 'hello world'

testclass= TestClass(100)
print(testclass)
# hello world 100

3、__del__()

  • 当删除对象时,python解释器也会默认调⽤ __del__() 方法
class TestClass():
	def __init__(self,num):
		self.attribute1 = num
	def __del__(self):
		print(f'{self}对象已被删除')

testclass= TestClass(100)
del testclass
# <__main__.TestClass object at 0x000001C1820D1CA0>对象已被删除

4. 类属性和实例属性

(1)类属性

1、设置和访问类属性

  • 类属性:类对象所拥有的属性,它被该类的所有实例对象所共有,可以使⽤类对象或实例对象访问
  • 优点:类属性为全类所共有,仅占⽤⼀份内存,更加节省内存空间
  • 使用场景:记录的某项数据始终保持⼀致时,则定义类属性
class A(object):
	num= 10
	
a1= A()
a2= A()
print(A.num) # 10
print(a1.num) # 10
print(a2.num) # 10

2、修改类属性

  • 类属性只能通过类对象修改,不能通过实例对象修改
class A(object):
	num = 100
	
a1 = A()
a2 = A()

# 修改类属性
A.num= 200
print(a1.num ) # 200
print(a2.num ) # 200

# 如果通过实例对象修改类属性,表示的是创建了⼀个实例属性
a1.num= 300
print(a1.num) # 300
print(a2.num) # 200

(2)实例属性

class A(object):
	def __init__(self):
		self.num = 100
	def info(self):
		print(self.num)

a = A()
print(a.num) # 5
# print(A.num) # 报错:实例属性不能通过类访问
a.info() # 5

5. 类方法和静态方法

(1)类方法

  • 特点:第⼀个参数必须是类对象,⼀般以cls作为第⼀个参数,能够通过类对象和实例对象访问
  • 使⽤场景:当方法中需要使用类对象(如访问私有类属性等)时,⼀般和类属性配合使用
  • 修饰方法:装饰器@classmethod
class A(object):
	__num = 100
	
	@classmethod
	def get_num(cls):
		return cls.__num

a= A()
re = a.get_num()
print(re) # 100

(2)静态方法

  • 特点:既不需要传递类对象也不需要传递实例对象(形参没有self/cls),能够通过类对象和实例对象访问
  • 使⽤场景:当方法中既不需要使用实例对象,也不需要使用类对象时,取消不需要的参数传递,有利于减少不必要的内存占用和性能消耗
  • 修饰方法:装饰器@staticmethod
class A(object):
	@staticmethod
	def info():
		print('100')

a = A()
a.info() # 100
A.info() # 100

二、面向对象的三大特性

1. 封装

  • 封装:将属性和方法书写到类⾥⾯的操作,可以为属性和方法添加私有权限

2. 继承

  • 继承指的是多个类之间的所属关系,即子类默认继承⽗类的所有属性和方法,且可以重写⽗类属性和方法
  • 在Python中,所有类默认继承object类,object类是顶级类或基类,其他子类叫做派⽣类
# ⽗类 A
class A(object):
	def __init__(self):
		self.num = 100
	def info(self):
		print(self.num)
# 子类 B
class B(A):
	pass

b = B()
b.info() # 100

(1)单继承

  • ⼀个类只继承一个⽗类
# 1. 父类 A
class A(object):
	def __init__(self):
		self.name= 'Jack'
		
	def info(self):
		print(f'姓名:{self.name}')
 
# 2. 子类 B
class B(A):
	pass
	
# 3. 创建对象
people = B()

# 4. 对象访问实例属性
print(people.name) # Jack

# 5. 对象调⽤实例方法
people.info() # 姓名:Jack

(2)多继承

  • ⼀个类同时继承多个⽗类,默认使⽤第⼀个⽗类的同名属性和方法
# 1. 父类 A
class A(object):
	def __init__(self):
		self.name= 'Jack'
		
	def info(self):
		print(f'姓名:{self.name}')

# 2. 父类 B
class B(object):
	def __init__(self):
		self.name= 'Tom'
		
	def info(self):
		print(f'姓名:{self.name}')
 
# 3. 子类 C
class C(A,B):
	pass
	
# 4. 创建对象
people = C()

# 5. 对象访问实例属性
print(people.name) # Jack

# 6. 对象调⽤实例方法
people.info() # 姓名:Jack

(3)子类重写父类同名方法和属性

  • 子类和父类具有同名属性和方法时,默认使用子类的同名属性和方法
# 1. 父类 A
class A(object):
	def __init__(self):
		self.name= 'Jack'
		
	def info(self):
		print(f'姓名:{self.name}')

# 2. 父类 B
class B(object):
	def __init__(self):
		self.name= 'Tom'
		
	def info(self):
		print(f'姓名:{self.name}')
 
# 3. 子类 C
class C(A,B):
	def __init__(self):
		self.name= 'Jerry'
		
	def info(self):
		print(f'姓名:{self.name}')
	
# 4. 创建对象
people = C()

# 5. 对象访问实例属性
print(people.name) # Jerry

# 6. 对象调⽤实例方法
people.info() # 姓名:Jerry

(4)子类调用父类的同名方法和属性

  • 为了保证调用到的是父类属性,所以必须在调⽤方法前调⽤父类的初始化
# 1. 父类 A
class A(object):
	def __init__(self):
		self.name= 'Jack'
		
	def info(self):
		print(f'姓名:{self.name}')

# 2. 父类 B
class B(object):
	def __init__(self):
		self.name= 'Tom'
		
	def info(self):
		print(f'姓名:{self.name}')
 
# 3. 子类 C
class C(A,B):
	def __init__(self):
		self.name= 'Jerry'
		
	def info(self):
		# 为了保证调⽤到的是子类属性,所以也要先调⽤子类的初始化
		self.__init__()
		print(f'姓名:{self.name}')
		
	# 调⽤⽗类方法
	def A_info(self):
		A.__init__(self)
		A.info(self)
		
	def B_info(self):
		B.__init__(self)
		B.info(self)
	
# 4. 创建对象
people = C()

# 5. 对象访问实例属性
print(people.name) # Jerry

# 6. 对象调⽤实例方法
people.info() # 姓名:Jerry
people.A_info() # 姓名:Jack
people.B_info() # 姓名:Tom
people.info() # 姓名:Jerry

(5)多层继承

# 1. 父类 A
class A(object):
	def __init__(self):
		self.name= 'Jack'
		
	def info(self):
		print(f'姓名:{self.name}')

# 2. 父类 B
class B(object):
	def __init__(self):
		self.name= 'Tom'
		
	def info(self):
		print(f'姓名:{self.name}')
 
# 3. 子类 C
class C(A,B):
	def __init__(self):
		self.name= 'Jerry'
		
	def info(self):
		# 为了保证调⽤到的是子类属性,所以必须先调⽤子类的初始化
		self.__init__()
		print(f'姓名:{self.name}')
		
	# 调⽤⽗类方法,为了保证调⽤到的是⽗类属性,所以必须在调⽤方法前调⽤⽗类的初始化	
	def A_info(self):
		A.__init__(self)
		A.info(self)
		
	def B_info(self):
		B.__init__(self)
		B.info(self)

# 4. 子孙类 D
class D(C):
	pass
	
# 5. 创建对象
people = D()

# 6. 对象访问实例属性
print(people.name) # Jerry

# 7. 对象调⽤实例方法
people.info() # 姓名:Jerry
people.A_info() # 姓名:Jack
people.B_info() # 姓名:Tom

(6)super()调⽤⽗类方法

  • 使⽤super()可以⾃动查找⽗类,⽐较适合单继承使⽤
# 1. 父类 A
class A(object):
	def __init__(self):
		self.name= 'Jack'
		
	def info(self):
		print(f'姓名:{self.name}')

# 2. 子类 B
class B(A):
	def __init__(self):
		self.name= 'Tom'
		
	def info(self):
		print(f'姓名:{self.name}')
		
		# ⼀次性调⽤⽗类的同名属性和方法
		super().__init__()
		super().info()
 
# 3. 子孙类 C
class C(B):
	def __init__(self):
		self.name= 'Jerry'
		
	def info(self):
		self.__init__()
		print(f'姓名:{self.name}')
		
	def A_info(self):
		A.__init__(self)
		A.info(self)
		
	def B_info(self):
		B.__init__(self)
		B.info(self)

	# ⼀次性调⽤⽗类的同名属性和方法
	def A_B_info(self):
		super().__init__()
		super().info()
		
# 4. 创建对象
people = C()

# 5. 对象访问实例属性
print(people.name)
# Jerry
 
# 6. 对象调⽤实例方法
people.info() 
# 姓名:Jerry

people.A_info() 
# 姓名:Jack

people.B_info() 
# 姓名:Tom
# 姓名:Jack

people.A_B_info() 
# 姓名:Tom
# 姓名:Jack

(7)私有权限

1、定义私有属性和方法

  • 可以为实例属性和方法设置私有权限,即设置某个实例属性或实例方法不继承给子类(只能在类⾥⾯访问和修改)
  • 设置私有权限的方法:定义属性名或方法名时在前面加__,也就是__属性名__方法名
# 1. 父类 A
class A(object):
	def __init__(self):
		self.name= 'Jack'
		
	def info(self):
		print(f'姓名:{self.name}')

# 2. 父类 B
class B(object):
	def __init__(self):
		self.name= 'Tom'
		
	def info(self):
		print(f'姓名:{self.name}')
 
# 3. 子类 C
class C(A,B):
	def __init__(self):
		self.name= 'Jerry'
	
	# 定义私有属性
		self.__age = 18

	# 定义私有方法
	def __info(self):
		print(self.name)
		print(self.__age)
		
	def info(self):
		self.__init__()
		print(f'姓名:{self.name}')
		
	def A_info(self):
		A.__init__(self)
		A.info(self)
		
	def B_info(self):
		B.__init__(self)
		B.info(self)

# 4. 子孙类 D
class D(C):
	pass
	
# 5. 创建子类对象
people = C()

# 6. 对象访问实例属性&方法
print(people.name) # Jerry
people.info() # 姓名:Jerry
# print(people.__age) # 报错
# people.__info() # 报错


# 7. 创建子孙类对象
people = D()

# 8. 对象访问实例属性&方法
print(people.name) # Jerry
people.info() # 姓名:Jerry
# print(people.__age) # 报错
# people.__info() # 报错

2、获取和修改私有属性值

  • ⼀般定义函数名get_xx⽤来获取私有属性,定义set_xx⽤来修改私有属性值
# 1. 父类 A
class A(object):
	def __init__(self):
		self.name= 'Jack'
		
	def info(self):
		print(f'姓名:{self.name}')

# 2. 父类 B
class B(object):
	def __init__(self):
		self.name= 'Tom'
		
	def info(self):
		print(f'姓名:{self.name}')
 
# 3. 子类 C
class C(A,B):
	def __init__(self):
		self.name= 'Jerry'
		self.__age = 18

	# 获取私有属性
	def get_age(self):
		return self.__age

	# 修改私有属性
	def set_age(self):
		self.__age = 20
		
	def __info(self):
		print(self.name)
		print(self.__age)
		
	def info(self):
		self.__init__()
		print(f'姓名:{self.name}')
		
	def A_info(self):
		A.__init__(self)
		A.info(self)
		
	def B_info(self):
		B.__init__(self)
		B.info(self)

# 4. 子孙类 D
class D(C):
	pass
	
# 5. 创建子类对象
people = C()

# 6. 对象访问实例属性&方法
print(people.get_age()) # 18
people.set_age()
print(people.get_age()) # 20

3. 多态

  • 多态是⼀种使⽤对象的⽅式,依赖于继承:⼀个抽象类有多个子类,子类重写⽗类方法,调⽤不同子类对象的相同⽗类方法,可以产⽣不同的执⾏结果

实现步骤:

  1. 定义⽗类,并提供公共方法
  2. 定义子类,并重写⽗类方法
  3. 传递子类对象给调⽤者,可以看到不同子类执⾏效果不同
# 1. 父类
class Dog(object):
	def info(self):
		print('我是一只狗')

# 2. 子类 1
class Samll_Dog(Dog): 
	def info(self):
		print('我是一只小狗')

# 3. 子类 2
class Big_Dog(Dog):
	def info(self):
		print('我是一只大狗')

# 4. 应用类
class Dog_Type(object):
	def dog_info(self, dog): 
		dog.info()

small_dog = Samll_Dog()
big_dog = Big_Dog()
dog_type = Dog_Type()

dog_type.dog_info(small_dog) # 我是一只小狗
dog_type.dog_info(big_dog) # 我是一只大狗

三、异常

1. 了解异常

异常:当检测到⼀个错误时,解释器无法继续执行,出现了⼀些错误的提示

2. 捕获异常的语法

  • 一般语法
try:
	可能发⽣错误的代码
	
except:
	如果出现异常执⾏的代码
  • 捕获指定异常,语法
try:
	可能发⽣错误的代码
	
except 异常类型:
	如果捕获到该异常类型执⾏的代码

注意:

  1. 如果尝试执⾏的代码的异常类型和要捕获的异常类型不⼀致,则⽆法捕获异常
  2. ⼀般try下⽅只放⼀⾏尝试执⾏的代码
  • 捕获多个指定异常,语法
try:
	可能发⽣错误的代码
	
except (异常类型1, 异常类型2):
	如果出现这些异常执⾏的代码
  • 捕获异常描述信息,语法
try:
	可能发⽣错误的代码
	
except (异常类型1, 异常类型2) as result:
	print(result)
  • 捕获所有异常描述信息,语法
try:
	可能发⽣错误的代码
	
 # Exception是所有程序异常类的父类
except Exception as result:
	print(result)
  • 异常的else:表示的是如果没有异常要执⾏的代码
try:
	可能发⽣错误的代码
	
except Exception as result:
	print(result)

else:
	print('未发生异常')
  • 异常的finally:表示⽆论是否异常都要执⾏的代码
try:
	可能发⽣错误的代码
	
except Exception as result:
	print(result)
	
else:
	print('未发生异常')
	
finally:
	print('发生异常')

3. 自定义异常

  • 自定义异常语法:
# 1. ⾃定义异常类
class 异常类类名(Exception):
	代码
 
	# 设置抛出异常的描述信息
	def __str__(self):
		return ...
		
# 2. 抛出异常
raise 异常类名()
# 例:设置输入密码不能小于3位,否则抛出自定义异常
class ShortInputError(Exception):
	def __init__(self, length, min_len):
		self.length = length
		self.min_len = min_len
	
	# 设置抛出异常的描述信息
	def __str__(self):
		return f'你输⼊的⻓度是{self.length}, 不能少于{self.min_len}个字符'
	
def main():
	try:
		con = input('请输⼊密码:')
		if len(con) < 3:
			raise ShortInputError(len(con), 3)
	except Exception as result:
		 print(result)
	else:
		print('密码已经输⼊完成')
main()

四、模块和包

1. 模块

模块(Module):是以 .py 结尾的Python文件,能定义函数、类和变量,也能包含可执行的代码

1、导⼊模块

  • import 模块名1, 模块名2...
  • from 模块名 import 功能1, 功能2, 功能3...
  • from 模块名 import *
  • import 模块名 as 别名
  • from 模块名 import 功能名 as 别名

2、制作模块

每个Python文件都可以作为⼀个模块,模块的名字就是⽂件的名字(必须符合标识符命名规则)

  • 定义模块:新建⼀个Python⽂件,命名为 my_module1.py ,并定义 testA 函数。

  • 测试模块:在实际开发中,为了让模块能够在项目中达到想要的效果,一般会在 .py 文件中添加⼀些测试代码

让测试代码在模块被导入的时候不被执行

if __name__ == '__main__':
 	测试代码
  • 调⽤模块:参考上面的导入模块

3、模块定位顺序

导入模块时,Python解析器对模块位置的搜索顺序是:

  1. 当前⽬录
  2. 如果不在当前⽬录,则搜索在shell变量PYTHONPATH下的每个⽬录
  3. 如果都找不到,会查看默认路径

模块搜索路径存储在system模块的sys.path变量中(变量⾥包含当前目录,PYTHONPATH和由安装过程决定的默认默认)

注意

  • ⾃⼰的⽂件名不要和已有模块名重复,否则导致模块功能⽆法使⽤
  • 使⽤from 模块名 import 功能的时候,如果功能名字重复,调⽤到的是最后定义或导⼊的功

4、__all__
如果⼀个模块⽂件中有 __all__ 变量,当使⽤from 模块 import *导⼊时,只能导入 __all__ 列表中的元素

2. 包

包(Package):将有联系的模块组织在⼀起,放到同⼀个⽂件夹下,并且创建⼀个__init__.py ⽂件

1、制作包

PyChram新建包:文件 — 新建 — Python 软件包 — 输⼊包名 — 新建功能模块(有联系的模块)

注意:新建包后,包内部会⾃动创建 __init__.py ⽂件,此文件控制着包的导入行为

在这里插入图片描述

2、导入包

方法一:

import 包名.模块名

包名.模块名.⽬标

方法⼆:

from 包名 import *

模块名.目标

注意:必须在 __init__.py ⽂件中添加 __all__ = [] ,控制允许导入的模块列表

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值