我什么时候应该在 Python 中使用类?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/33072570/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When should I be using classes in Python?
提问by metersk
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.
我已经用 python 编程大约两年了;主要是数据内容(pandas、mpl、numpy),但也有自动化脚本和小型网络应用程序。我正在努力成为一名更好的程序员并增加我的 Python 知识,困扰我的一件事是我从未使用过类(除了为小型 Web 应用程序复制随机烧瓶代码之外)。我通常理解它们是什么,但我似乎无法理解为什么我需要它们而不是一个简单的函数。
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?
为我的问题添加特殊性:我编写了大量自动报告,这些报告总是涉及从多个数据源(mongo、sql、postgres、apis)中提取数据,执行大量或少量数据修改和格式化,将数据写入 csv/excel /html,通过电子邮件发送。脚本范围从 ~250 行到 ~600 行。我有什么理由使用类来做到这一点,为什么?
采纳答案by dantiston
Classes are the pillar of Object Oriented Programming. OOP is highly concerned with code organization, reusability, and encapsulation.
类是面向对象编程的支柱。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 部分地与Functional Programming形成对比,后者是 Python 中经常使用的一种不同范式。并非所有使用 Python(或大多数语言)编程的人都使用 OOP。您可以在 Java 8 中做很多不是非常面向对象的工作。如果您不想使用 OOP,那就不要使用。如果您只是编写一次性脚本来处理您永远不会再使用的数据,那么请继续按您的方式编写。
However, there are a lot of reasons to use OOP.
但是,使用 OOP 的原因有很多。
Some reasons:
一些原因:
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.
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.
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.
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 定义了众所周知的标准方式来描述和定义代码中的数据和过程。数据和过程都可以存储在不同的定义级别(在不同的类中),并且有谈论这些定义的标准方法。也就是说,如果您以标准方式使用 OOP,它将帮助您以后的自己和其他人理解、编辑和使用您的代码。此外,您可以命名数据结构片段并方便地引用它们,而不是使用复杂的、任意的数据存储机制(字典的字典或列表或字典或集合的字典列表,或其他)。
状态:OOP 帮助您定义和跟踪状态。例如,在一个经典示例中,如果您正在创建一个处理学生的程序(例如,成绩程序),您可以将所有需要的关于他们的信息(姓名、年龄、性别、年级、课程、成绩、教师、同龄人、饮食、特殊需求等),只要对象还活着,这些数据就会持久存在,并且很容易访问。
封装:通过封装,过程和数据存储在一起。方法(函数的 OOP 术语)与它们操作和产生的数据一起定义。在 Java 等允许访问控制的语言中,或者在 Python 中,这取决于您如何描述公共 API,这意味着可以对用户隐藏方法和数据。这意味着如果您需要或想要更改代码,您可以对代码的实现做任何您想做的事情,但保持公共 API 不变。
继承:继承允许您在一个地方(在一个类中)定义数据和过程,然后在以后覆盖或扩展该功能。例如,在 Python 中,我经常看到人们创建类的子
dict
类以添加附加功能。一个常见的更改是覆盖当从不存在的字典中请求键以基于未知键给出默认值时抛出异常的方法。这允许您现在或以后扩展您自己的代码,允许其他人扩展您的代码,并允许您扩展其他人的代码。可重用性:所有这些和其他原因都可以提高代码的可重用性。面向对象的代码允许您编写一次可靠的(经过测试的)代码,然后一遍又一遍地重用。如果您需要针对特定用例调整某些内容,您可以从现有类继承并覆盖现有行为。如果您需要更改某些内容,您可以在保留现有公共方法签名的同时更改所有内容,并且没有人是更明智的(希望如此)。
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.
同样,不使用 OOP 的原因有很多,您也不需要。但幸运的是,使用像 Python 这样的语言,你可以使用一点点或很多,这取决于你。
An example of the student use case (no guarantee on code quality, just an example):
学生用例的一个例子(不保证代码质量,只是一个例子):
Object Oriented
面向对象
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())
Standard Dict
标准字典
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]))
回答by valignatev
I think you do it right. Classes are reasonable when you need to simulate some business logic or difficult real-life processes with difficult relations. As example:
我认为你做对了。当您需要模拟一些业务逻辑或具有困难关系的困难现实生活过程时,类是合理的。例如:
- Several functions with share state
- More than one copy of the same state variables
- To extend the behavior of an existing functionality
- 具有共享状态的几个函数
- 多个相同状态变量的副本
- 扩展现有功能的行为
I also suggest you to watch this classic video
我也建议你看这个经典视频
回答by Ashutosh
A class defines a real world entity. If you are working on something that exists individually and has its own logic that is separate from others, you should create a class for it. For example, a class that encapsulates database connectivity.
一个类定义了一个现实世界的实体。如果您正在处理独立存在且具有与其他逻辑分开的逻辑的东西,您应该为它创建一个类。例如,封装数据库连接的类。
If this not the case, no need to create class
如果不是这种情况,则无需创建类
回答by Dmitry Rubanovich
Whenever you need to maintain a state of your functions and it cannot be accomplished with generators (functions which yield rather than return). Generators maintain their own state.
每当您需要维护函数的状态并且无法使用生成器(产生而不是返回的函数)来完成时。生成器维护自己的状态。
If you want to override any of the standardoperators, you need a class.
如果要覆盖任何标准运算符,则需要一个类。
Whenever you have a use for a Visitor pattern, you'll need classes. Every other design pattern can be accomplished more effectively and cleanly with generators, context managers (which are also better implemented as generators than as classes) and POD types (dictionaries, lists and tuples, etc.).
每当您使用访问者模式时,您都需要类。使用生成器、上下文管理器(作为生成器比作为类实现更好)和 POD 类型(字典、列表和元组等),所有其他设计模式都可以更有效、更干净地完成。
If you want to write "pythonic" code, you should prefer context managers and generators over classes. It will be cleaner.
如果你想编写“pythonic”代码,你应该更喜欢上下文管理器和生成器而不是类。会更干净。
If you want to extend functionality, you will almost always be able to accomplish it with containment rather than inheritance.
如果您想扩展功能,您几乎总是能够通过包含而不是继承来完成它。
As every rule, this has an exception. If you want to encapsulate functionality quickly (ie, write test code rather than library-level reusable code), you can encapsulate the state in a class. It will be simple and won't need to be reusable.
正如每条规则一样,这有一个例外。如果您想快速封装功能(即编写测试代码而不是库级可重用代码),您可以将状态封装在一个类中。它将很简单,不需要可重复使用。
If you need a C++ style destructor (RIIA), you definitely do NOT want to use classes. You want context managers.
如果您需要 C++ 风格的析构函数 (RIIA),您绝对不想使用类。你想要上下文管理器。
回答by Mohit Thakur
Its depends on your idea and design. if you are good designer than OOPs will come out naturally in the form of various design patterns. For a simple script level processing OOPs can be overhead. Simple consider the basic benefits of OOPs like reusable and extendable and make sure if they are needed or not. OOPs make complex things simpler and simpler things complex. Simply keeps the things simple in either way using OOPs or not Using OOPs. which ever is simpler use that.
这取决于您的想法和设计。如果你是一名优秀的设计师,那么 OOP 会自然而然地以各种设计模式的形式出现。对于简单的脚本级处理 OOP 可能是开销。简单地考虑 OOP 的基本好处,例如可重用和可扩展,并确定是否需要它们。OOP 让复杂的事情变得更简单,让更简单的事情变得复杂。简单地以使用 OOP 或不使用 OOP 的任何一种方式使事情变得简单。使用哪个更简单。