我是基于 deepseek v3 的 AI 助手
本文深入探讨了Python中的面向对象编程(OOP)和异常处理机制。首先,文章介绍了类方法和静态方法的使用,展示了如何通过`@classmethod`和`@staticmethod`装饰器来定义这些方法,并通过实例代码演示了它们的应用场景。接着,文章详细解释了魔法方法(如`__init__`和`__str__`)的作用,帮助读者理解如何在类中自定义对象的行为。 在继承部分,文章通过一个简单的例子展示了如何创建子类并重写父类的方法,同时介绍了`super()`函数的使用,帮助读者理解如何在子类中调用父类的构造函数。 异常处理部分则重点讲解了如何抛出和捕获异常。文章通过代码示例展示了`raise`和`assert`关键字的使用,以及如何通过`try...except...else...finally`结构来处理不同类型的异常。此外,文章还介绍了如何自定义异常类,并提供了练习题,帮助读者巩固所学知识。 最后,文章通过一个练习题,引导读者使用`while`循环和异常处理机制来模拟`for`循环的功能,进一步加深对迭代器和生成器的理解。 这篇文章不仅适合Python初学者,也适合有一定经验的开发者,帮助他们更好地掌握面向对象编程和异常处理的技巧。
# 面向对象
# 类方法和静态方法
# 类方法
class Dog: | |
variety = "柴犬" | |
def __init__(self, name): | |
self.name = name | |
@classmethod | |
def show_variety(cls): | |
print(f"这个类下所有对象都是{cls.variety}") | |
def __str__(self): | |
return f"{self.name}是一只狗" | |
dog = Dog("dog") | |
dog.show_variety() | |
print(dog) |
variety 是类变量,通过这个类实例化的所有对象都有这个变量
在方法前加上 @classmethod 来声明这是一个类方法
类方法的首位参数应为 cls , 代表调用的对象的类 / 类
首位参数可以是任何合法的形参名,但一般使用 self 和 cls
# 静态方法
class Dog: | |
def __init__(self, name): | |
self.name = name | |
@staticmethod | |
def demo(): | |
print("这是一个静态方法") | |
def __str__(self): | |
return f"{self.name}是一只狗" | |
dog = Dog("dog") | |
dog.demo() | |
print(dog) |
静态方法没有特殊参数,所以和类外函数基本一致
静态方法可以传入参数
# 魔法方法
魔法方法指 class 内的部分特殊方法,通常以双下划线开头结尾
例如 __init__ 就是初始化类时执行的方法
__str__ 就是输出时执行的方法
可以看官方文档
# 继承
class Dog: | |
def __init__(self, name): | |
self.name = name | |
def __str__(self): | |
return f"{self.name}是一只狗" | |
class Huskies(Dog): | |
def __init__(self, name): | |
super().__init__(name) | |
self.variety = "哈士奇" | |
def eat(self): | |
print(f"{self.name}正在吃") | |
def sleep(self): | |
print(f"{self.name}正在睡") | |
def __str__(self): | |
print(f"{self.name}是一只哈士奇") |
在这个例子中, Huskies 是 Dog 的派生类 (子类), Dog 是 Huskies 的父类 (基类)
Huskies 类重写了实例化和输出方法,Huskies 类拥有所有 Dog 类的方法和变量
子类语法:
class name(父类): | |
语句 |
有时候会有这样的语法:
class Demo(object): | |
pass |
object 是所有 python 类的基类,在 python2 时必须要写入,但 python3 不需要这样写
# 超类
def __init__(self, name): | |
super().__init__(name) | |
self.variety = "哈士奇" |
这是 Huskies 类的实例化方法,里面的 super() 就是超类
super() 在 Huskies 类内代表 Dog 类,也可以使用 Dog.__init__() 来代替超类
# 异常处理
# 抛出异常
u = input("输入1或0:") | |
if u: | |
raise ValueError("一个错误") |
输入 1 就会抛出 ValueError 错误,因为使用了 raise 关键字
语法: raise 错误
但这个代码还可以简化:
u = input("输入1或0:") | |
assert not u |
assert 关键字在后面的变量为非时会返回 AssertionError
assert 不可以选择返回错误
# 异常捕获
# 捕获语法
try: | |
u1 = int(input()) | |
u2 = int(input()) | |
a = u1/u2 | |
except ZeroDivisionError: | |
print("触发了除零错误") | |
except ValueError: | |
print("触发了数值错误") | |
except Exception as e: | |
print(f"触发了{e}") | |
else: | |
print("没有错误") | |
print(a) | |
finally: | |
print("有没有错我都输出") |
try 关键字后的代码块会被尝试执行,如果触发错误便会寻找 except 子句
execpt 语法: except 异常:
如果没有触发错误,就会寻找 else 子句,没有 else 子句就会继续执行
如果有 finally 子句,就会执行,无论是否触发错误
execpt Exception as e 就是在处理未知错误,这里的 e 就是错误的临时变量
如果在 try 代码块内触发异常,将会直接跳出代码块,处理后下面需要使用 try 内定义的变量
可能导致未定义错误
# 捕获的特殊情况
try: | |
5/0 | |
except ZeroDivisionError: | |
raise Exception | |
else: | |
raise Exception | |
finally: | |
raise Exception |
这是一段离谱的代码,如果执行,就会出现这样一串字:
During handling of the above exception, another exception occurred:
这行字代表在处理 try 内错误时,except 或 finally 内有 raise 子句或抛出了其他错误
except 子句内有 raise 且被触发会导致错误无法正常处理,上面的代码也会抛出 ZeroDivisionError: division by zero
# 定义异常
class MyException(Exception): | |
pass |
这是一个最简单的异常类,但我们可以给它加上一个实例化函数:
class MyException(Exception): | |
def __init__(self, value): | |
self.value = value | |
def __str__(self): | |
return self.value |
现在就可以自定义异常输出了
# 练习题
用 whlie 和 try...except... 子句来实现 for 循环遍历迭代和生成器的功能
输出 next 返回值即可
超出迭代器序列是 StopIteration 错误
这是数据:
list1 = [1,2,3,4,5] | |
l = iter(list1) |
答案:
while True: | |
try: | |
temp = l.__next__() | |
except StopIteration: | |
break | |
else: | |
print(temp) |
下一篇是 9plus, 关于第三方库
