【全栈之路】10 天掌握 Python 开发(7)面向对象和异常处理

类和对象

类和对象用于创建和使用可重用的代码。类是创建对象的蓝图,对象是类的特定实例。

任务

创建一个 Circle 的类,该类可以计算圆的面积和周长。

JavaScript 实现

typescript 复制代码
class Circle {
  static pi = Math.PI
  constructor(radius) {
    this.radius = radius;
  }

  static createCircle(radius){
    return new Circle(radius)
  }

  getArea() {
    return Circle.pi * this.radius ** 2;
  }

  getCircumference() {
    return 2 * Circle.pi * this.radius;
  }

  toString() {
    return `[Circle]: radius:${this.radius}`
  }
}

const circle = new Circle(5); // 或 Circle.createCircle(5)
console.log(circle.toString()); // [Circle]: radius:5
console.log(circle.getArea()); // 78.53981633974483
console.log(circle.getCircumference()); // 31.41592653589793

:::tip class 中的 static 关键字并非 JavaScript 原生支持的,而是由 TypeScript 提供的特性,除此之外还提供了 publicprivateprotected 访问修饰符。 :::

Python 实现

python 复制代码
import math

class Circle:
  pi = math.pi
  def __init__(self, radius):
    self.radius = radius

  @classmethod
  def create_circle(cls,radius):
    return Circle(radius)
  
  def get_area(self):
    return Circle.pi * self.radius ** 2

  def get_circumference(self):
    return 2 * Circle.pi * self.radius

  def __str__(self):
    return f"[Circle] radius:{self.radius}"

circle = Circle(5) # 或 Circle.create_circle(5)
print(circle) # [Circle] radius:5
print(circle.get_area()) # 78.53981633974483
print(circle.get_circumference()) # 31.41592653589793

代码解读

  • Python 像调用函数一样创建类实例,JavaScript 必须使用 new 关键字。
  • Python 中使用 __init__ 方法作为构造函数,JavaScript 使用 constructor 方法。
  • Python 类的实例方法的第一个参数必须为 self ,它表示类的实例。类方法需要使用 classmethod 装饰器进行标记,第一个参数必须为 cls ,表示当前类,也可以使用 staticmethod 装饰器,它跟普通函数一样,不需要第一个参数为 cls
  • Python 使用缩进来定义类中的代码块,JavaScript 使用大括号 {} 表示代码块。
  • Python 类中以 _ 开头的成员约定为私有成员,外部不应该直接使用,在 TypeScript 中可以使用 privateprotected 访问修饰符对可访问性进行限制。
  • Python 中以 __ 开头的为一般为系统级的特殊成员,在外部不可访问。

:::tip Python 类中的特殊方法 Python 中有许多常用的特殊方法,开发者可以在类中对它进行重写。

以下为部分常见的特殊方法

  • init: 类构造函数,用于对象的初始化。当创建类的实例时,方法会被自动调用。
  • str: 用于返回对象的字符串表示。当使用 print 函数打印对象时,会调用该方法。
  • repr: 用于返回对象的可打印字符串表示。当在交互式环境中直接输入对象名时,会调用该方法。
  • len: 用于返回对象的长度。当使用 len 函数获取对象的长度时,会调用该方法。
  • getitem: 用于通过索引访问对象的元素。当使用索引运算符([])访问对象时,会调用该方法。
  • setitem: 用于通过索引设置对象的元素。当使用索引运算符([])设置对象时,会调用该方法。
  • delitem: 用于通过索引删除对象的元素。当使用 del 关键字删除对象的元素时,会调用该方法。
  • getattr: 用于在访问不存在的属性时触发。当访问对象不存在的属性时,会调用该方法。
  • setattr: 用于在设置属性时触发。当设置对象的属性时,会调用该方法。
  • delattr: 用于在删除属性时触发。当使用 del 关键字删除对象的属性时,会调用该方法。 :::

差异速览

特性 JavaScript Python
定义类 class ClassName {} class ClassName:
创建对象 let myObj = new ClassName(); my_obj = ClassName()
构造函数 constructor() {} def __init__(self):
类属性赋值 this.propertyName = value; self.propertyName = value
类方法 methodName() {} def methodName(self):
继承 class ChildClass extends ParentClass {} class ChildClass(ParentClass):
对象销毁 无内置支持 def __del__(self):

相关资源


try-except 语句

try-except 语句用于处理 Python 中的异常。它允许你定义可能引发异常的代码块,并指定如何处理异常,类似于 JavaScript 中的 try-catch 语法。

任务

设计一个程序,读取一个不存在的文件,并显示一个友好的异常信息。

JavaScript 实现

javascript 复制代码
const fs = require('fs');

try {
  const content = fs.readFileSync('file-not-exist.txt', 'utf-8');
  const lines = content.split('\n');
  
  for (let line of lines) {
    if (line.trim() !== '') {
      console.log(line);
    }
  }
  
  const firstLine = lines[0].trim();
  console.log(`First line: ${firstLine}`);
  
  const numbers = lines.map(Number);
  console.log(`Sum of numbers: ${numbers.reduce((a, b) => a + b, 0)}`);
  
} catch (error) {
  console.error(`An error occurred: ${error.message}`);
}

Python 实现

python 复制代码
try:
    with open('file-not-exist.txt', 'r') as file:
        content = file.read()
        lines = content.split('\n')
        
        for line in lines:
            if line.strip() != '':
                print(line)
        
        first_line = lines[0].strip()
        print(f'First line: {first_line}')
        
        numbers = [int(line) for line in lines]
        print(f'Sum of numbers: {sum(numbers)}')
        
except Exception as error:
    print(f'An error occurred: {str(error)}')

代码解读

  • Python 使用 try-except 处理异常,JavaScript 使用 try-catch 处理异常。
  • Python 可以使用多个 except 块根据异常的实例类型来处理不同的异常,JavaScript 只允许一个 catch 块,只能在 catch 块中对异常对象的类型进行判断以实现相同的功能。
  • Python 通过将异常对象转换为字符串以获取异常信息,JavaScript 通常通过异常对象的 message 属性获取错误信息。
  • Python 和 JavaScript 都可以使用 finally 块编写无论是否发生异常都将执行的逻辑。

:::tip Python 处理特定类型异常 Python 允许在 try-except 语句中编写多个 except 块以捕获不同类型的异常,如:

python 复制代码
try:
    # 可能会引发异常的代码
    a = 10 / 0  # 除以 0 会引发 ZeroDivisionError
    b = int('abc')  # 'abc' 无法转换为整数会引发 ValueError
    raise Exception('This is a exception')
except ZeroDivisionError:
    # 处理 ZeroDivisionError 异常的代码
    print("除数不能为零!")
except ValueError:
    # 处理 ValueError 异常的代码
    print("无法将字符串转换为整数!")
except Exception as e:
    # 处理其他类型的异常的代码
    print("发生了其他异常:", str(e))

需要注意,虽然上面的代码编写了多个 except 块,但一次最多只会有一个 except 块会被命中,当编写了多个 except 块时,捕获异常的范围应从小到大。

上面的代码中,最后一个 Exception 类型的异常是所有异常的基类,只有当前面所有的异常类型都不匹配时,它才会执行,这让程序不论发生什么错误都始终能被捕获。

在 Python 代码中,使用 raise 可以将捕获到的异常或自定义的异常进行抛出,与 JavaScript 中的 throw 功能一样。 :::

相关资源


自定义异常

在 Python 中,可以自定义异常来处理特定的错误场景,这样可以为程序创建更有意义和描述性的错误消息。

任务

构建一个计算各种形状的面积的程序。使用自定义异常来处理不同类型的形状计算错误。

JavaScript 实现

javascript 复制代码
class InvalidShapeException extends Error {
  constructor(message) {
    super(message);
    this.name = "InvalidShapeException";
  }
}

class NegativeDimensionException extends Error {
  constructor(message) {
    super(message);
    this.name = "NegativeDimensionException";
  }
}

function calculateRectangleArea(length, width) {
  if (typeof length !== "number" || typeof width !== "number") {
    throw new InvalidShapeException("无效的尺寸。长度和宽度必须是数字。");
  }
  if (length <= 0 || width <= 0) {
    throw new NegativeDimensionException("无效的尺寸。长度和宽度必须是正数。");
  }
  return length * width;
}

console.log(calculateRectangleArea(5, 4)); // 输出: 20
console.log(calculateRectangleArea("5", 4)); // 抛出InvalidShapeException
console.log(calculateRectangleArea(-5, 4)); // 抛出NegativeDimensionException

Python 实现

python 复制代码
# 定义自定义异常
class InvalidShapeException(Exception):
    def __init__(self, message):
        super().__init__(message)

class NegativeDimensionException(Exception):
    def __init__(self, message):
        super().__init__(message)

def calculate_rectangle_area(length, width):
    if not isinstance(length, (int, float)) or not isinstance(width, (int, float)):
        raise InvalidShapeException("无效的尺寸。长度和宽度必须是数字。")
    if length <= 0 or width <= 0:
        raise NegativeDimensionException("无效的尺寸。长度和宽度必须是正数。")
    return length * width

print(calculate_rectangle_area(5, 4)) # 输出: 20
print(calculate_rectangle_area("5", 4)) # 引发InvalidShapeException
print(calculate_rectangle_area(-5, 4)) # 引发NegativeDimensionException

代码解读

  • Python 异常基类是 Exception,而 JavaScript 异常基类是 Error,它们都使用 class 继承基类实现自定义异常。
  • Python 使用 isinstance() 函数来检查变量的类型,而 JavaScript 使用 typeofinstance of

通用 API

特性 JavaScript Python
创建自定义异常 class CustomException extends Error {} class CustomException(Exception):
引发自定义异常 throw new CustomException(message) raise CustomException(message)

相关资源


本书的内容完全免费,开源地址:github.com/luckrnx09/p...

相关推荐
Dread_lxy8 分钟前
vue 依赖注入(Provide、Inject )和混入(mixins)
前端·javascript·vue.js
奔跑草-1 小时前
【前端】深入浅出 - TypeScript 的详细讲解
前端·javascript·react.js·typescript
羡与1 小时前
echarts-gl 3D柱状图配置
前端·javascript·echarts
前端郭德纲1 小时前
浏览器是加载ES6模块的?
javascript·算法
JerryXZR2 小时前
JavaScript核心编程 - 原型链 作用域 与 执行上下文
开发语言·javascript·原型模式
帅帅哥的兜兜2 小时前
CSS:导航栏三角箭头
javascript·css3
渗透测试老鸟-九青2 小时前
通过投毒Bingbot索引挖掘必应中的存储型XSS
服务器·前端·javascript·安全·web安全·缓存·xss
龙猫蓝图2 小时前
vue el-date-picker 日期选择器禁用失效问题
前端·javascript·vue.js
夜色呦2 小时前
掌握ECMAScript模块化:构建高效JavaScript应用
前端·javascript·ecmascript
peachSoda72 小时前
随手记:简单实现纯前端文件导出(XLSX)
前端·javascript·vue.js