我什么时候应该在 Python 中使用类? [英] When should I be using classes in Python?

查看:42
本文介绍了我什么时候应该在 Python 中使用类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用python编程大约两年了;主要是数据内容(pandas、mpl、numpy),但也有自动化脚本和小型网络应用程序.我正在努力成为一名更好的程序员并增加我的 Python 知识,困扰我的一件事是我从未使用过类(除了为小型 Web 应用程序复制随机烧瓶代码之外).我通常理解它们是什么,但我似乎无法理解为什么我需要它们而不是一个简单的函数.

I have been programming in python for about two years; mostly data stuff (pandas, mpl, numpy), but also automation scripts and small web apps. I'm trying to become a better programmer and increase my python knowledge and one of the things that bothers me is that I have never used a class (outside of copying random flask code for small web apps). I generally understand what they are, but I can't seem to wrap my head around why I would need them over a simple function.

为我的问题添加特殊性:我编写了大量自动报告,这些报告总是涉及从多个数据源(mongo、sql、postgres、apis)中提取数据,执行大量或少量数据调整和格式化,将数据写入csv/excel/html,通过电子邮件发送.脚本范围从 ~250 行到 ~600 行.我有什么理由使用类来做到这一点,为什么?

To add specificity to my question: I write tons of automated reports which always involve pulling data from multiple data sources (mongo, sql, postgres, apis), performing a lot or a little data munging and formatting, writing the data to csv/excel/html, send it out in an email. The scripts range from ~250 lines to ~600 lines. Would there be any reason for me to use classes to do this and why?

推荐答案

类是对象的支柱面向编程.OOP 高度关注代码组织、可重用性和封装性.

Classes are the pillar of Object Oriented Programming. OOP is highly concerned with code organization, reusability, and encapsulation.

首先,免责声明:OOP 部分地与 函数式编程形成对比,后者是不同的范式在 Python 中使用了很多.并非所有使用 Python(或大多数语言)编程的人都使用 OOP.您可以在 Java 8 中做很多不是非常面向对象的工作.如果您不想使用 OOP,那就不要使用.如果您只是编写一次性脚本来处理您永远不会再使用的数据,那么请继续按您现在的方式编写.

First, a disclaimer: OOP is partially in contrast to Functional Programming, which is a different paradigm used a lot in Python. Not everyone who programs in Python (or surely most languages) uses OOP. You can do a lot in Java 8 that isn't very Object Oriented. If you don't want to use OOP, then don't. If you're just writing one-off scripts to process data that you'll never use again, then keep writing the way you are.

然而,使用 OOP 的原因有很多.

However, there are a lot of reasons to use OOP.

一些原因:

  • 组织:OOP 定义了在代码中描述和定义数据和过程的众所周知的标准方法.数据和过程都可以存储在不同的定义级别(在不同的类中),并且有谈论这些定义的标准方法.也就是说,如果您以标准方式使用 OOP,它将帮助您以后的自己和其他人理解、编辑和使用您的代码.此外,您可以命名数据结构片段并方便地引用它们,而不是使用复杂的、任意的数据存储机制(dicts 的 dicts 或 list 或 dicts 或 dicts of set 的列表等等).

  • Organization: OOP defines well known and standard ways of describing and defining both data and procedure in code. Both data and procedure can be stored at varying levels of definition (in different classes), and there are standard ways about talking about these definitions. That is, if you use OOP in a standard way, it will help your later self and others understand, edit, and use your code. Also, instead of using a complex, arbitrary data storage mechanism (dicts of dicts or lists or dicts or lists of dicts of sets, or whatever), you can name pieces of data structures and conveniently refer to them.

状态:OOP 帮助您定义和跟踪状态.例如,在一个经典示例中,如果您正在创建一个处理学生的程序(例如,一个成绩程序),您可以将所有需要的关于他们的信息(姓名、年龄、性别、年级、课程、成绩、教师、同龄人、饮食、特殊需求等),只要对象还活着,并且易于访问,这些数据就会一直存在.

State: OOP helps you define and keep track of state. For instance, in a classic example, if you're creating a program that processes students (for instance, a grade program), you can keep all the info you need about them in one spot (name, age, gender, grade level, courses, grades, teachers, peers, diet, special needs, etc.), and this data is persisted as long as the object is alive, and is easily accessible.

封装:通过封装,过程和数据存储在一起.方法(函数的 OOP 术语)与它们操作和产生的数据一起定义.使用 Java 等允许访问控制的语言,或在Python,取决于您如何描述公共 API,这意味着可以对用户隐藏方法和数据.这意味着如果您需要或想要更改代码,您可以对代码的实现做任何您想做的事情,但保持公共 API 不变.

Encapsulation: With encapsulation, procedure and data are stored together. Methods (an OOP term for functions) are defined right alongside the data that they operate on and produce. In a language like Java that allows for access control, or in Python, depending upon how you describe your public API, this means that methods and data can be hidden from the user. What this means is that if you need or want to change code, you can do whatever you want to the implementation of the code, but keep the public APIs the same.

继承:继承允许您在一个地方(在一个类中)定义数据和过程,然后在以后覆盖或扩展该功能.例如,在 Python 中,我经常看到人们创建 dict 类的子类以添加附加功能.一个常见的更改是覆盖当从不存在的字典中请求键以基于未知键给出默认值时抛出异常的方法.这允许您现在或以后扩展自己的代码,允许其他人扩展您的代码,并允许您扩展其他人的代码.

Inheritance: Inheritance allows you to define data and procedure in one place (in one class), and then override or extend that functionality later. For instance, in Python, I often see people creating subclasses of the dict class in order to add additional functionality. A common change is overriding the method that throws an exception when a key is requested from a dictionary that doesn't exist to give a default value based on an unknown key. This allows you to extend your own code now or later, allow others to extend your code, and allows you to extend other people's code.

可重用性:所有这些和其他原因都可以提高代码的可重用性.面向对象的代码允许您编写一次可靠的(经过测试的)代码,然后一遍又一遍地重用.如果您需要针对特定​​用例调整某些内容,您可以从现有类继承并覆盖现有行为.如果您需要更改某些内容,您可以在保留现有公共方法签名的情况下进行更改,没有人是明智的(希望如此).

Reusability: All of these reasons and others allow for greater reusability of code. Object oriented code allows you to write solid (tested) code once, and then reuse over and over. If you need to tweak something for your specific use case, you can inherit from an existing class and overwrite the existing behavior. If you need to change something, you can change it all while maintaining the existing public method signatures, and no one is the wiser (hopefully).

同样,不使用 OOP 的原因有很多,您也不需要.但幸运的是,像 Python 这样的语言,你可以使用一点点或很多,这取决于你.

Again, there are several reasons not to use OOP, and you don't need to. But luckily with a language like Python, you can use just a little bit or a lot, it's up to you.

学生用例的一个例子(不保证代码质量,只是一个例子):

An example of the student use case (no guarantee on code quality, just an example):

面向对象

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]))

这篇关于我什么时候应该在 Python 中使用类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆