【Python】编程规范01-类定义

14 篇文章 1 订阅
2 篇文章 0 订阅

背景:

最近在做大模型相关产品研发过程中,需要用到python,由于博主之前主要是Java方面的开发,以前也用过python开发过项目,但是一直没有确定的规范约束,在对python进行了一段时间的研究后,对python编程规范做一些小小的总结,文章内容为开发过程中的亲身经验,希望给有需要的同学一些帮助!

注:本文极有可能是python系列的开端,具体根据博主的时间来看,敬请期待~~

一、python编写类的规范:

在 Python 中编写类时,有一些约定俗成的规范和最佳实践,这些规范帮助代码更具可读性和一致性。以下是一些常见的规范和示例:

1. 类名命名规范

  • 命名风格: 类名通常使用驼峰式命名法(CamelCase),即每个单词的首字母都大写,并且没有下划线。
  • 示例
class MyClass:
    pass

class CustomerAccount:
    pass

2.类定义

  • 类的定义: 使用 class 关键字定义类,类名后跟括号和冒号。
  • 示例:
class Car:
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year

    def start_engine(self):
        print(f"The {self.make} {self.model}'s engine is now running.")

3.方法和属性

  • 方法命名: 方法名使用小写字母和下划线(snake_case),以提高可读性。
  • 属性: 属性(变量)的命名也使用小写字母和下划线
  • 示例
class Employee:
    def __init__(self, name, position):
        self.name = name
        self.position = position

    def get_details(self):
        return f"Name: {self.name}, Position: {self.position}"

4. 调用类和方法

  • 实例化类: 使用类名加括号创建对象(实例)。
  • 调用方法: 使用点(.)运算符调用对象的方法。
  • 示例:
# 实例化类
my_car = Car("Toyota", "Corolla", 2022)

# 调用方法
my_car.start_engine()  # 输出: The Toyota Corolla's engine is now running.

# 创建一个员工对象
emp = Employee("Alice", "Engineer")

# 获取员工详细信息
print(emp.get_details())  # 输出: Name: Alice, Position: Engineer

5. 文档字符串

  • 文档字符串: 每个类和方法通常都应该包含一个文档字符串(docstring),描述其功能。
  • 示例:
class Rectangle:
    """
    A class to represent a rectangle.
    """

    def __init__(self, width, height):
        """
        Initialize the rectangle with width and height.
        """
        self.width = width
        self.height = height

    def area(self):
        """
        Calculate the area of the rectangle.
        """
        return self.width * self.height

 6. 特殊方法

  • 特殊方法: 在类中,前后都有双下划线的方法被称为特殊方法(如 __init____str__),它们通常用于实现类的特殊行为或重载运算符。
  • 示例:
class Circle:
    def __init__(self, radius):
        self.radius = radius

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

    def area(self):
        import math
        return math.pi * (self.radius ** 2)

总结

  • 类名: 驼峰式命名(CamelCase)。
  • 方法和属性: 小写字母和下划线(snake_case)。
  • 实例化和方法调用: 使用类名创建实例,并通过点(.)调用方法。
  • 文档字符串: 为类和方法提供简洁的说明。

遵循这些规范和最佳实践可以使你的 Python 代码更加规范和易于维护。

二、文件名命名规范

文件名的命名规范在 Python 编程中也很重要,因为它可以提高代码的组织性和可读性。以下是一些常见的文件名命名规范和最佳实践:

1. 文件名使用小写字母和下划线

  • 命名风格: 文件名通常使用小写字母,并用下划线分隔单词,以提高可读性。
  • 示例:
    • my_script.py
    • data_processing.py
    • utils_helpers.py

2. 避免使用特殊字符和空格

  • 规范: 文件名中应避免使用特殊字符(如 @!#* 等)和空格。使用下划线代替空格是推荐的做法。
  • 示例:
    • 不推荐: my script.pydata-processing@2024.py
    • 推荐: my_script.pydata_processing_2024.py

3. 文件名应简洁且描述性强

  • 规范: 文件名应简洁明了,能够清楚地描述文件的内容或功能。
  • 示例:
    • database_connection.py 适用于处理数据库连接的脚本。
    • config_reader.py 适用于读取配置文件的脚本。

4. 避免使用与 Python 内置模块相同的名称

  • 规范: 避免使用与 Python 标准库模块或常用第三方库模块相同的名称,以防止命名冲突。
  • 示例:
    • 避免: json.py (因为 Python 标准库有一个 json 模块)
    • 推荐: custom_json_parser.py

5. 使用一致的命名风格

  • 规范: 在一个项目中,保持一致的命名风格对于文件名非常重要。这样可以使项目结构更加统一和易于理解。
  • 示例:
    • 如果项目中使用 snake_case 风格,那么所有文件名都应遵循这个风格。
    • 如果项目中使用 kebab-case(虽然不常见),那么所有文件名都应遵循这个风格(如 data-processing-script.py)。

6. 包和模块文件名

  • 模块: 模块文件名通常是单个 Python 文件,用于实现特定的功能。
  • : 包是包含 __init__.py 文件的目录,目录名也应使用小写字母和下划线。例如:my_package/

示例

  • 脚本文件:

    • main.py:主要执行脚本。
    • helpers.py:包含辅助函数的脚本。
    • data_analysis.py:进行数据分析的脚本。
  • :

    • my_project/
      • __init__.py:标识 my_project 目录为一个包。
      • module_one.py:包中的第一个模块。
      • module_two.py:包中的第二个模块。

遵循这些文件命名规范可以提高代码的可维护性和可读性,帮助团队成员快速理解文件的内容和目的。

三、文件名和类型规约扩展:

文件名和类型(类名)之间并没有强制的规定必须保持一致,但有一些最佳实践可以帮助提高代码的组织性和可读性:

1.文件名和类型(类名)的关系

  1. 一致性:

    • 实践: 虽然文件名和类名不需要严格一致,但在很多代码风格指南中,推荐让文件名和包含的主要类名保持一致,以便更容易识别文件的内容。
    • 示例: 如果文件 my_class.py 中定义了一个主要的 MyClass 类,这种一致性可以使代码更具可读性。
  2. 单一职责原则:

    • 实践: 每个文件(模块)应尽量只定义一个主要的类或功能。这样有助于文件更专注于一个功能,便于维护和理解。
    • 示例user.py 文件中定义了 User 类,而 utils.py 中包含了多个工具函数。

2.文件中可以定义多个类吗?

  1. 可以,但需要注意:

    • 实践: 一个文件中可以定义多个类,尤其是当这些类紧密相关时。例如,一个文件中可能包含多个内部类或辅助类。
    • 示例: 在 shapes.py 文件中,可以定义 CircleSquare 等多个类,因为它们都与“形状”相关。
  2. 最佳实践:

    • 相关性: 如果多个类在功能上紧密相关,可以放在同一个文件中。例如,定义不同形状的几何图形类可以放在 shapes.py 中。
    • 文件大小: 文件中类的数量不应过多,以免导致文件过大和难以管理。如果文件变得很大,可以考虑将类拆分到不同的文件中。
    • 可读性: 为了保持代码的可读性,文件中的类定义应具有清晰的注释和组织。每个类的功能和职责应明确,以避免混淆。
示例
  • 单个类文件:

# user.py
class User:
    def __init__(self, name):
        self.name = name

    def greet(self):
        print(f"Hello, {self.name}!")
  • 多个类文件:
# shapes.py
class Circle:
    def __init__(self, radius):
        self.radius = radius

    def area(self):
        return 3.14 * (self.radius ** 2)

class Square:
    def __init__(self, side):
        self.side = side

    def area(self):
        return self.side ** 2
  • 文件内的多个类:
# shapes.py
class Circle:
    def __init__(self, radius):
        self.radius = radius

    def area(self):
        return 3.14 * (self.radius ** 2)

class Square:
    def __init__(self, side):
        self.side = side

    def area(self):
        return self.side ** 2

class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height

    def area(self):
        return self.width * self.height

总结来说,文件名和类名的一致性有助于代码的可读性,但并不是强制要求。文件中可以包含多个类,只要它们在功能上相关并且文件不变得过于庞大和难以管理

四、继承与基类

class Position_Model(BaseModel)

在 Python 中,类定义的括号中可以包含一个或多个基类。当你看到像 class Position_Model(BaseModel): 这样的定义时,这意味着 Position_Model 类继承自 BaseModel 类。括号中的 BaseModel 被称为“基类”或“父类”,它是 Position_Model 类的超类。

1.继承:

  • 继承允许一个类(子类)获得另一个类(基类)的属性和方法。在这个例子中,Position_Model 继承了 BaseModel 的所有功能,并且可以添加自己的属性和方法,或者覆盖基类中的方法。
  • 示例
class BaseModel:
    def __init__(self):
        self.id = None

    def save(self):
        print("Saving...")

class Position_Model(BaseModel):
    def __init__(self, position_name):
        super().__init__()  # 调用 BaseModel 的构造函数
        self.position_name = position_name

    def display(self):
        print(f"Position: {self.position_name}")

2.属性定义

在类中定义属性可以在 __init__ 构造函数中进行。__init__ 是一个特殊的方法,用于初始化类的实例。当你创建类的对象时,__init__ 方法会被调用来设置对象的初始状态。

示例:如何在 Position_Model 类中定义属性

使用 __init__ 方法定义属性:

class Position_Model(BaseModel):
    def __init__(self, position_name, salary):
        super().__init__()  # 调用 BaseModel 的构造函数
        self.position_name = position_name
        self.salary = salary

在这个示例中,Position_Model 类的 __init__ 方法定义了两个属性:position_namesalary。这些属性可以通过对象的实例访问和修改。

属性定义示例:

# 创建 Position_Model 实例
position = Position_Model(position_name="Software Engineer", salary=90000)

# 访问属性
print(position.position_name)  # 输出: Software Engineer
print(position.salary)  # 输出: 90000

3.类中定义元组类型的属性:

要在类中定义一个元组类型的属性,可以在 __init__ 方法中初始化这个属性,确保其值是一个元组。你可以使用类型注解来标明属性的类型

from typing import Tuple

class MyClass:
    def __init__(self, coordinates: Tuple[float, float]):
        self.coordinates = coordinates

# 示例
obj = MyClass((12.34, 56.78))
print(obj.coordinates)  # 输出: (12.34, 56.78)

说明:

  • 类型注解coordinates: Tuple[float, float] 表明 coordinates 属性应当是一个包含两个浮点数的元组。
  • 初始化:在 __init__ 方法中,将传入的参数赋值给 self.coordinates,确保属性是一个元组。

总结

  • 括号中的基类:括号中包含的是类的基类或父类。基类为子类提供了继承的属性和方法。
  • 定义属性:属性通常在 __init__ 方法中定义。通过 self 关键字访问实例属性。
  • 使用 super():在子类的 __init__ 方法中调用 super().__init__() 是一种常见的做法,用于初始化基类的属性。

这种继承机制是面向对象编程的一个核心概念,有助于代码的复用和组织。

4.BaseModel

from pydantic import BaseModel的这个BaseModel的作用:

BaseModel 是 Pydantic 库中的一个核心组件。Pydantic 是一个用于数据验证和设置的数据模型库,特别适用于 Python 的数据解析和验证任务。BaseModel 提供了很多有用的功能,使得数据模型的创建和管理更加方便和安全。

BaseModel 的作用
  1. 数据验证:

    BaseModel 可以自动验证模型中的数据类型和数据值。你可以定义模型属性的类型,Pydantic 会确保实例化时提供的数据符合这些类型。例如,如果你定义一个字段是 int 类型,Pydantic 会确保传递的值是整数,否则会抛出验证错误。
  2. 数据解析:

    BaseModel 可以从不同的数据格式(如字典、JSON 等)创建模型实例。它会自动将输入数据解析成适当的类型。例如,你可以从一个 JSON 字符串创建一个模型实例,Pydantic 会解析 JSON 并验证数据。
  3. 数据转换:

    在验证数据的同时,Pydantic 还支持类型转换。例如,将字符串 '123' 自动转换为整数 123
  4. 自动生成文档:

    使用 Pydantic 可以轻松生成 API 文档,因为它可以与 FastAPI 等库集成,这些库能够自动生成 OpenAPI 文档。
  5. 易于使用的错误处理:

    当数据验证失败时,Pydantic 提供清晰且详细的错误信息,帮助开发者迅速定位和解决问题。
示例

以下是使用 BaseModel 的一个简单示例:

from pydantic import BaseModel, ValidationError
from typing import List

class Person(BaseModel):
    name: str
    age: int
    friends: List[str] = []

# 正确的使用
try:
    person = Person(name="Alice", age=30, friends=["Bob", "Charlie"])
    print(person)
except ValidationError as e:
    print(e)

# 错误的使用
try:
    person = Person(name="Alice", age="thirty", friends=["Bob", "Charlie"])
except ValidationError as e:
    print(e)
解释
  1. 定义模型:

    • Person 类继承自 BaseModel,定义了 name(字符串类型)、age(整数类型)和 friends(字符串列表类型)三个属性。
  2. 创建实例:

    • 如果提供的数据类型正确,Person 实例将被成功创建,并可以访问属性。
    • 如果数据类型错误(如将 age 设置为字符串),Pydantic 将抛出 ValidationError,提供详细的错误信息。
结论

继承 BaseModel 使得类在数据验证、解析和转换方面具有强大的功能和便利性。这对于构建健壮和可靠的数据驱动应用程序尤其重要,特别是在处理外部输入数据时。

BaseModel VS  __init__

从规范和开发角度来看,建议使用继承 BaseModelBaseModel 提供了自动数据验证、解析和类型转换的功能,显著减少了样板代码和潜在的错误。它还集成了友好的错误处理和数据转换机制,这可以帮助保持代码的简洁性和可靠性。自己编写 __init__ 方法虽然可以提供更多的灵活性,但通常需要额外的代码来实现数据验证和解析,增加了出错的风险和维护的复杂性。

使用示例:

pip install pydantic==2.3.0

from pydantic import BaseModel
class PositionModel(BaseModel):
    content: str = ""
    position: list[tuple[float, float]]
    page_num: int
# 调用示例	
position_paragraph = PositionModel(
	content=content,
	position=position,
	page_num=page_num
)  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Alex_81D

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值