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

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

问题描述

我已经用python编程了大约两年了;主要是数据(pandas,mpl,numpy),还有自动化脚本和小型Web应用程序.我试图成为一个更好的程序员,并增加我的python知识,而令我困扰的一件事是我从未使用过一个类(除了为小型Web应用程序复制随机烧瓶代码外).我通常理解它们是什么,但是我似乎无法为为什么在一个简单的函数中需要它们的问题而wrap之以鼻.

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,api)中提取数据,执行大量或少量的数据整理和格式化,然后将数据写入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,它将帮助您以后的自己和他人理解,编辑和使用您的代码.此外,您可以使用数据结构的名称并方便地引用它们,而不是使用复杂的任意数据存储机制(命令或列表的命令,集合的命令或列表的命令或其他命令).

  • 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天全站免登陆