二十 成员和异常
20.1 成员
成员:类中 属性和方法
20.1 类属性和实例属性
class Dog:
# 类属性是直接写的,不用特定写到某个方法中
count = 0 # 记录当前类,已经被创建多少次
type_set = set() # 记录所有狗的种类
def __init__(self, name, age, master,type):
# 实例属性
self.name = name
self.age = age
self.master = master
self.type = type
Dog.count += 1 # 每增加一狗,加一
Dog.type_set.add(type)
dog1 = Dog("小红",5,'翠果','哈士奇')
print(Dog.count)
dog2 = Dog('小黑',1,'清越','金毛')
print(Dog.count)
print(dog1.count)
print(dog2.count)
dog3 = Dog('小白',1,'晶晶','金毛')
print(dog3.count)
print(dog1.count)
print(dog2.count)
print(dog3.type_set)
dog3 = Dog('小白',1,'晶晶','萨摩耶')
print(dog1.type_set)
区别总结
- 定义位置
- 实例属性:在 __init__ 方法中使用self.xxx 定义
- 类:直接在类体内定义,不需要self关键字
- 作用范围
- 实例属性:每个实例自己独立的区间,实例之间不共享
- 类属性:所有的实例都可以访问,都共享这个变量,它是存储在类中。修改一个类属性,其他的实例都会受到影响
- 使用场景
- 实例属性:适用于需要在每个实例中存储不同数据的情况
- 类属性:适用于需要在所有实例中共享数据的情况
20.2 实例方法
- 这种方法是带self为参数的方法,主要也是区分每个对象的功能
class A:
# 类属性
count = 0
# init方法中定义实例属性
def __init__(self,name):
self.name = name
# 实例方法: 第一个参数是self
def speak(self):
print(f"my name is {self.name}")
a = A('彬彬')
# a.speak() 本质上是 A.speak(a)
20.3 类方法
类方法特点和 类属性是意义。
定义类方法需要在方法头部上使用一个 内置装饰器
- @classmethod
类方法和普通方法的区别
-
类方法中只能访问类属性,不能访问实例属性
class A: # 类属性 count = 0 # init方法中定义实例属性 def __init__(self, name): self.name = name # 实例方法: 第一个参数是self def speak(self): print(f"my name is {self.name}") @classmethod def add_count(cls): cls.count +=1 @classmethod def clear(cls): cls.count = 0 # 修改类属性 print(A.count) A.add_count() A.add_count() A.add_count() A.add_count() print(A.count) A.clear() print(A.count)
-
注意语法区别
- 第一个参数不同
- 实例方法:self 表示对象区间
- 类方法:cls 表示类
- 第一个参数不同
-
类方法,对象和类都可以直接访问
class A:
# 类属性
count = 0
# init方法中定义实例属性
def __init__(self, name):
self.name = name
# 实例方法: 第一个参数是self
def speak(self):
print(f"my name is {self.name}")
@classmethod
def add_count(cls):
cls.count +=1
@classmethod
def clear(cls):
cls.count = 0 # 修改类属性
print(A.count)
A.add_count()
A.add_count()
A.add_count()
A.add_count()
print(A.count)
A.clear()
print(A.count)
bb = A(name="Bob")
bb.clear()
bb.add_count()
print(bb.count)
20.4 静态方法
# 工具类, 就是存储和数学相关的功能而已
class Math:
@staticmethod
def sin():
print("求正玄")
@staticmethod
def cos():
print('求余玄')
@staticmethod
def pow(a,b):
# 求a的b次方
print(a**b)
静态方法总结
-
静态方法本质上和类没多大关系,只是一个管理模式。严格意义上可以不算方法,就是一个函数也行
-
既不能访问类中的属性,也不能访问对象的属性
-
更多只是作为一个工具来使用
20.5 魔法方法(特殊方法)
长相(外貌): 双下划线开头和结尾的方法。 比如 __init__
魔法方法主要从object来,这种方法一般情况是不需要自己去用的,都是在特殊情况被调用
20.5.1 基本的
__str__(self)
默认情况下直接打印对象,打印的是一串地址
- 作用:返回对象的字符串表示, 在print()和str()函数中起作用
- 调用时机:print和str
class Dog:
def __init__(self,name,age,master):
self.name = name
self.age = age
self.master =master
def __str__(self):
return f"名字和年龄 : {self.name} {self.age} 主人是 {self.master}"
dog1 = Dog("大王",1,'不凡')
print(dog1)
__len__(self)
- 作用:返回对象长度
- 调用时机:len()
class Dog:
count = 0
def __init__(self,name,age,master):
self.name = name
self.age = age
self.master =master
Dog.count += 1
def __str__(self):
return f"名字和年龄 : {self.name} {self.age} 主人是 {self.master}"
def __len__(self):
return Dog.count
dog1 = Dog("大王",1,'不凡')
dog1 = Dog("大王",1,'不凡')
dog1 = Dog("大王",1,'不凡')
# 求狗的数量
print(len(dog1))
20.5.2 比较的
这些魔法方法,都是在运算符中生效
方法名 | 说明 |
---|---|
__add__ | 加法 |
__sub__ | 减法 |
__mul__ | 乘法 |
__truediv__ | 除法 |
__floodiv__ | 地板除 |
__mod__ | 求余 |
__pow__ | 幂 |
__iadd__ | += |
__isub__ | -= |
__imul__ | *= |
__itruediv__ | /= |
__ifloodiv__ | //= |
__imod__ | %= |
__ipow__ | **= |
__lt__ | 小于 |
__le__ | 小于等于 |
__gt__ | 大于 |
__ge__ | 大于等于 |
__eq__ | 等于 |
__ne__ | 不等于 |
比较方法特点
# 等于操作
def __eq__(self,ohter): #other表示被比较的对象
return 布尔值
# class Dog:
# count = 0
#
# def __init__(self,name,age,master):
# self.name = name
# self.age = age
# self.master =master
# Dog.count += 1
#
# def __str__(self):
# return f"名字和年龄 : {self.name} {self.age} 主人是 {self.master}"
#
# def __len__(self):
# return Dog.count
# 日期类
class Date:
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
# 等于
def __eq__(self,other):
# self 表示比较对象,other 表示被比较对象
return self.year == other.year and self.month == other.month and self.day == other.day
# 大于号操作
def __gt__(self,other):
# self>other
return self.year > other.year
x = Date(2025,12,30)
y = Date(2024,12,31)
# 默认比的是否是同一个对象
print(x==y)
print(x>y)
print(x== y)
20.2 异常
异常:程序运行中一些不可避免的错误
- 使用未定义的变量
- 超出序列下标使用
- 除以0
20.2.1 捕获异常结构
语法
try:
代码块(可能出错的语句)
except:
代码块(出错后的处理方式)
else:
代码块(没出错的时候才执行的语句)
结构类似于分支结构
print("异常发生之前的代码")
try:
# 可能出错的代码块
print(a)
b = 10
except:
# 只有出错了,才会执行
print('出错了,哈哈')
else:
# 必须要try走完,才有用的代码
print(b)
print("异常发生之后的代码")
20.2.2 异常对象
-
我们在python中遇到的所有error,都是异常
-
实际上这些异常也是对象,都统一来源于Exception
-
NameError 名称错误异常
-
ZeroDivisionError 除0错误
-
IndexError 索引错误, 超出下标了
在Python中一切皆对象,包括异常也是对象
只要类继承了Excetion,就是一个异常类
对专门的异常进行捕获
try:
print(a)
# 指定异常类型进行捕获
except ZeroDivisionError:
print('处理nameerror')
except NameError:
print('nameError')
... 可以去多个指定 抓门的异常对象来做专门的处理
捕获一切异常
try:
print(a)
# 啥异常都能捕获
except Exception:
print('处理nameerror')
Exception能不能看错误
a = [1,2]
try:
print(a[5])
# 啥异常都能捕获
except Exception as e:
print(e)
- 捕获所有
- 捕获指定
- 一个一个写,更好排查
- 最终结点
try:
代码块(可能出错的语句)
except:
代码块(出错后的处理方式)
else:
代码块(没出错的时候才执行的语句)
finally:
代码块(无论是否出现异常,都会执行)
20.2.3 raise
语法
raise 异常对象
-
为什么要用raise设置异常提示
1.维护性强
20.2.4 自定义异常
可以去继承Exception,做一些异常扩展
class my_erroy(Exception):
pass
20.2.5 assert断言
assert 一种调试工具,基于某种 布尔值 来进行报错
用于在程序中检查某个条件是否为真,如果条件为假,assert会引发一个AssertionError
raise 简洁版
assert 条件表达式,错误提示语句
用处
-
调试用途
- 接口输入验证
-
提前报错,避免副作用
开发产品只要2个阶段 1.开发调式阶段 敲代码,实现需求。 特点:代码频繁变动,需求不断修改和完善 2.生产阶段 重点:提供稳定服务,确保可靠性和性能 真实的场景,面对的高并发,处理实际用户的操作 assert更适合的 开发调试阶段,简洁捕捉,但是提供的错误信息简单 raise更适合 生产阶段 目的都是为了 让程序崩溃,避免因为错误而导致一些副作用