我什么时候应该在Python中使用类?
我已经用python编程大约两年了;主要是数据内容(熊猫、mpl、numpy),但也有自动化脚本和小型web应用程序。我正在努力成为一名更好的程序员,增加我的python知识,而困扰我的一件事是我从未使用过类(除了为小型web应用复制随机烧瓶代码)。我通常理解它们是什么,但我似乎无法理解为什么我需要它们而不是一个简单的函数我什么时候应该在Python中使用类?,python,oop,Python,Oop,我已经用python编程大约两年了;主要是数据内容(熊猫、mpl、numpy),但也有自动化脚本和小型web应用程序。我正在努力成为一名更好的程序员,增加我的python知识,而困扰我的一件事是我从未使用过类(除了为小型web应用复制随机烧瓶代码)。我通常理解它们是什么,但我似乎无法理解为什么我需要它们而不是一个简单的函数 让我的问题更具体一点:我编写了大量的自动化报告,这些报告总是涉及从多个数据源(mongo、sql、postgres、API)提取数据,执行大量或少量的数据搜索和格式化,将数据
让我的问题更具体一点:我编写了大量的自动化报告,这些报告总是涉及从多个数据源(mongo、sql、postgres、API)提取数据,执行大量或少量的数据搜索和格式化,将数据写入csv/excel/html,并通过电子邮件发送出去。脚本的行数从250行到600行不等。我有什么理由使用类来做这件事吗?为什么 我认为你做得对。当您需要模拟某些业务逻辑或具有困难关系的困难的实际流程时,类是合理的。 例如:
- 具有共享状态的几个函数
- 相同状态变量的多个副本
- 扩展现有功能的行为的步骤
- 组织: OOP定义了在代码中描述和定义数据和过程的众所周知的标准方法。数据和过程都可以存储在不同的定义级别(在不同的类中),讨论这些定义有标准的方法。也就是说,如果您以标准方式使用OOP,它将帮助您以后的自己和其他人理解、编辑和使用您的代码。此外,您可以命名数据结构并方便地引用它们,而不是使用复杂、任意的数据存储机制(dicts of dicts或list或dicts or list of dicts of set,等等)
- 状态:OOP帮助您定义和跟踪状态。例如,在一个经典的例子中,如果你正在创建一个处理学生的程序(例如,年级程序),你可以将你需要的关于学生的所有信息保存在一个位置(姓名、年龄、性别、年级、课程、年级、教师、同龄人、饮食、特殊需求等),只要对象还活着,这些数据就会被保存,而且容易接近
- : 通过封装,过程和数据存储在一起。方法(函数的OOP术语)与它们操作和生成的数据一起定义。在Java这样的语言中,或者在Python中,根据您描述公共API的方式,这意味着可以对用户隐藏方法和数据。这意味着,如果您需要或想要更改代码,您可以对代码的实现做任何您想做的事情,但保持公共API不变
- :
继承允许您在一个位置(在一个类中)定义数据和过程,然后稍后重写或扩展该功能。例如,在Python中,我经常看到人们创建
类的子类来添加额外的功能。一个常见的更改是重写当从不存在的字典请求键时引发异常的方法,以基于未知键提供默认值。这允许您现在或以后扩展自己的代码,允许其他人扩展您的代码,并允许您扩展其他人的代码dict
- 可重用性:所有这些原因和其他原因都允许代码具有更高的可重用性。面向对象的代码允许您一次性编写可靠的(经过测试的)代码,然后反复重用。如果您需要为您的特定用例调整某些内容,您可以从现有类继承并覆盖现有行为。如果您需要更改某些内容,您可以在维护现有公共方法签名的同时对其进行全部更改,没有人比您更明智(希望如此)
class Student(object):
def __init__(self, name, age, gender, level, grades=None):
self.name = name
self.age = age
self.gender = gender
self.level = level
self.grades = grades or {}
def setGrade(self, course, grade):
self.grades[course] = grade
def getGrade(self, course):
return self.grades[course]
def getGPA(self):
return sum(self.grades.values())/len(self.grades)
# Define some students
john = Student("John", 12, "male", 6, {"math":3.3})
jane = Student("Jane", 12, "female", 6, {"math":3.5})
# Now we can get to the grades easily
print(john.getGPA())
print(jane.getGPA())
标准口述
def calculateGPA(gradeDict):
return sum(gradeDict.values())/len(gradeDict)
students = {}
# We can set the keys to variables so we might minimize typos
name, age, gender, level, grades = "name", "age", "gender", "level", "grades"
john, jane = "john", "jane"
math = "math"
students[john] = {}
students[john][age] = 12
students[john][gender] = "male"
students[john][level] = 6
students[john][grades] = {math:3.3}
students[jane] = {}
students[jane][age] = 12
students[jane][gender] = "female"
students[jane][level] = 6
students[jane][grades] = {math:3.5}
# At this point, we need to remember who the students are and where the grades are stored. Not a huge deal, but avoided by OOP.
print(calculateGPA(students[john][grades]))
print(calculateGPA(students[jane][grades]))
类定义了真实世界的实体。如果您正在处理一些单独存在并且有自己的逻辑与其他逻辑相分离的东西,那么您应该为它创建一个类。例如,封装数据库连接的类
如果不是这种情况,则无需在需要维护函数的状态时创建类,并且它无法通过生成器(生成而不是返回的函数)完成。发电机保持自己的状态 如果要重写任何标准运算符,则需要一个类 无论何时使用访问者模式,都需要类。使用生成器、上下文管理器(作为生成器比作为类更好地实现)和POD类型(字典、列表和元组等),可以更有效、更干净地完成其他所有设计模式 如果您想编写“pythonic”代码,您应该更喜欢上下文管理器和生成器而不是类。它会更干净 如果您想扩展功能,您几乎总是能够通过包含而不是