클래스 대 함수
함수는 프로그래밍 경험이 없지만 수학에 대한 배경 지식이없는 사람도 쉽게 이해할 수 있습니다. 반면에 수업은 이해하기가 더 어려워 보입니다.
생일 연도와 현재 연도를 고려하여 사람의 나이를 계산하는 클래스 / 함수를 만들고 싶다고 가정 해 보겠습니다. 이것에 대한 클래스를 만들어야합니까, 아니면 함수를 만들어야합니까? 아니면 시나리오에 따라 선택이 달라지는가?
추신 : 저는 Python에서 작업하고 있지만 질문은 일반적인 것 같습니다.
함수를 만듭니다. 함수 는 특정한 일을하고, 클래스 는 특정한 일을합니다.
클래스에는 종종 특정 클래스와 관련된 함수 인 메서드가 있으며 클래스가하는 일과 관련된 작업을 수행합니다.하지만 원하는 작업이 무엇이든하는 것이라면 함수 만 있으면됩니다.
기본적으로 클래스는 함수 (메서드)와 데이터 (속성)를 특정 종류의 사물을 중심으로 회전하는 논리 단위로 그룹화하는 방법입니다. 그룹화가 필요하지 않으면 수업을 만들 필요가 없습니다.
Amber가 대답에서 말하는 것처럼 : 함수를 만듭니다. 실제로 다음과 같은 것이 있으면 수업을 만들 필요가 없습니다 .
class Person(object):
def __init__(self, arg1, arg2):
self.arg1 = arg1
self.arg2 = arg2
def compute(other):
""" Example of bad class design, don't care about the result """
return self.arg1 + self.arg2 % other
여기에는 클래스에 캡슐화 된 함수가 있습니다. 이것은 코드의 가독성과 효율성을 떨어 뜨립니다. 사실 함수 compute
는 다음과 같이 작성할 수 있습니다.
def compute(arg1, arg2, other):
return arg1 + arg2 % other
하나 이상의 함수가 있고 내부 상태 (속성 포함)를 유지할 수있는 경우에만 클래스를 사용해야합니다. 그렇지 않고 함수를 다시 그룹화하려면 새 .py
파일에 모듈을 만듭니다 .
이 영상 (Youtube, 약 30 분)을 보시면 제 요점이 설명됩니다. Jack Diederich는이 경우 클래스가 왜 나쁜지, 특히 API와 같은 경우 왜 그렇게 나쁜 디자인인지 보여줍니다.
꽤 길지만 꼭 봐야 할 곳
클래스 (또는 인스턴스)는 사물을 표현하기위한 것입니다. 클래스는 특정 객체 클래스 (해당 인스턴스)에서 지원하는 작업을 정의하는 데 사용됩니다. 응용 프로그램이 사람을 추적해야한다면 Person
아마도 클래스 일 것입니다. 이 클래스의 인스턴스는 추적중인 특정 사람을 나타냅니다.
함수는 사물을 계산하기위한 것입니다. 입력을 받고 출력을 생성하거나 효과가 있습니다.
클래스와 함수는 같은 것을위한 것이 아니기 때문에 실제로 대안이 아닙니다. "생일 연도와 현재 연도를 고려하여 사람의 나이를 계산"하는 수업을 만드는 것은 실제로 의미가 없습니다. 당신은 또는 개념의 표현하는 수업을하지 않을 수도 있습니다 Person
, Age
, Year
, 및 / 또는 Birthday
. 하지만 Age
클래스 라고하더라도 사람의 나이를 계산하는 것으로 생각해서는 안됩니다. 오히려 사람의 나이의 계산 결과 의 인스턴스의 Age
클래스입니다.
응용 프로그램에서 사람들을 모델링하고 Person
클래스 가있는 경우 연령 계산을 클래스 의 방법 으로 만드는 것이 합리적 일 수 있습니다 Person
. 메서드는 기본적으로 클래스의 일부로 정의되는 함수입니다. 이것은 앞서 언급했듯이 "특정 객체 클래스가 지원하는 작업을 정의"하는 방법입니다.
따라서 사람의 나이를 계산하기 위해 사람 클래스에 메서드를 만들 수 있습니다 (아마 사람 개체에서 생일 연도를 검색하고 현재 연도를 매개 변수로받습니다). 그러나 계산은 여전히 함수 (클래스의 메서드 인 함수)에 의해 수행됩니다.
또는 인수 (생년월일을 검색 할 사람 객체 또는 단순히 출생 연도 자체)를받는 독립형 함수를 만들 수 있습니다. 아시다시피이 메서드가 자연스럽게 속한 클래스가 아직 없다면 훨씬 간단합니다! 단순히 작업을 유지하기 위해 클래스를 만들면 안됩니다. 그게 전부 라면 그 작업은 독립형 함수 여야합니다.
시나리오에 따라 다릅니다. 사람의 나이 만 계산할 수 있다면 하나의 특정 행동 을 구현하고 싶기 때문에 함수를 사용하십시오 .
그러나 사람의 생년월일 (및 기타 데이터)이 포함 된 개체를 만들고 싶다면 개체를 수정할 수 있습니다. 나이를 계산하는 것은 사람과 관련된 많은 작업 중 하나가 될 수 있습니다. 대신 클래스를 사용하십시오.
클래스는 일부 데이터 및 관련 작업을 병합하는 방법을 제공합니다. 데이터에 대한 작업이 하나만있는 경우 함수를 사용하고 데이터를 인수로 전달하면 덜 복잡한 코드로 동등한 동작을 얻을 수 있습니다.
종류의 클래스는 다음과 같습니다.
class A(object):
def __init__(self, ...):
#initialize
def a_single_method(self, ...):
#do stuff
실제로 클래스가 아니라 (복잡한) 함수일뿐입니다. 합법적 인 클래스는 항상 최소한 두 개의 메서드를 가져야합니다 (세지 않음 __init__
).
논란의 여지가있는 주제라는 것을 알고 있으며 지금 화상을 입을 가능성이 높습니다. 하지만 여기 내 생각이 있습니다.
나는 가능한 한 오랫동안 수업을 피하는 것이 가장 좋다고 생각했습니다. 복잡한 데이터 유형이 필요한 경우 간단한 구조체 (C / C ++), dict (python), JSON (js) 또는 이와 유사한 것을 사용합니다. 즉, 생성자 없음, 클래스 메서드 없음, 연산자 오버로딩 없음, 상속 없음 등을 사용합니다. 클래스를 사용할 때 OOP 자체 (What Design pattern, what should be private, bla bla)에 매료되어 처음부터 코딩하고 싶은 필수 항목에 집중할 수 없습니다.
프로젝트가 크고 복잡해지면 일종의 헬리콥터-뷰 시스템 아키텍처가 필요하기 때문에 OOP가 이해되기 시작합니다. "함수 대 클래스"는 또한 앞서있는 작업에 따라 달라집니다.
함수
- 목적 : 데이터 처리, 데이터 조작, 결과 집합 생성.
- 사용시기 : 이렇게하려면 항상 함수를 코딩하십시오.“y = f (x)”
struct / dict / json / etc (클래스 대신)
- 목적 : attr./param. 저장, attr./param. 유지, attr./param. 재사용, attr./param 사용. 나중.
- 사용시기 : 속성 / 매개 변수 세트를 다루는 경우 (가급적 변경 불가능)
- 다른 언어 : struct (C / C ++), JSON (js), dict (python) 등
- 복잡한 클래스보다 항상 간단한 struct / dict / json / etc를 선호합니다 (간단하게 유지하십시오!).
클래스 (새 데이터 유형 인 경우)
- 간단한 관점 : struct (C), dict (python), json (js) 등 메서드가 첨부되어 있습니다.
- 이 메서드는 클래스에 저장된 데이터 / 매개 변수와 결합해서 만 의미가 있어야합니다.
- 내 충고 : 클래스 메서드 내부에서 복잡한 것을 코딩하지 마십시오 (대신 외부 함수 호출).
- 경고 : 클래스를 함수의 가짜 네임 스페이스로 오용하지 마십시오! (이것은 매우 자주 발생합니다!)
- other use cases: if you want to do a lot of operator overloading then use classes (e.g. your own matrix/vector multiplication class)
- ask yourself: is it really a new “data type”? (Yes => class | No => can you avoid using a class)
array/vector/list (to store a lot of data)
- purpose: store a lot of homogeneous data of the same data type, e.g. time series
- advice#1: just use what your programming language already have. do not reinvent it
- advice#2: if you really want your “class mysupercooldatacontainer”, then overload an existing array/vector/list/etc class (e.g. “class mycontainer : public std::vector…”)
enum (enum class)
- i just mention it
- advice#1: use enum plus switch-case instead of overcomplicated OOP design patterns
- advice#2: use finite state machines
Before answering your question:
If you do not have a Person
class, first you must consider whether you want to create a Person
class. Do you plan to reuse the concept of a Person
very often? If so, you should create a Person
class. (You have access to this data in the form of a passed-in variable and you don't care about being messy and sloppy.)
To answer your question:
You have access to their birthyear, so in that case you likely have a Person
class with a someperson.birthdate
field. In that case, you have to ask yourself, is someperson.age
a value that is reusable?
The answer is yes. We often care about age more than the birthdate, so if the birthdate is a field, age should definitely be a derived field. (A case where we would not do this: if we were calculating values like someperson.chanceIsFemale
or someperson.positionToDisplayInGrid
or other irrelevant values, we would not extend the Person
class; you just ask yourself, "Would another program care about the fields I am thinking of extending the class with?" The answer to that question will determine if you extend the original class, or make a function (or your own class like PersonAnalysisData
or something).)
Never create classes. At least the OOP kind of classes in Python being discussed.
Consider this simplistic class:
class Person(object):
def __init__(self, id, name, city, account_balance):
self.id = id
self.name = name
self.city = city
self.account_balance = account_balance
def adjust_balance(self, offset):
self.account_balance += offset
if __name__ == "__main__":
p = Person(123, "bob", "boston", 100.0)
p.adjust_balance(50.0)
print("done!: {}".format(p.__dict__))
vs this namedtuple version:
from collections import namedtuple
Person = namedtuple("Person", ["id", "name", "city", "account_balance"])
def adjust_balance(person, offset):
return person._replace(account_balance=person.account_balance + offset)
if __name__ == "__main__":
p = Person(123, "bob", "boston", 100.0)
p = adjust_balance(p, 50.0)
print("done!: {}".format(p))
The namedtuple approach is better because:
- namedtuples have more concise syntax and standard usage.
- In terms of understanding existing code, namedtuples are basically effortless to understand. Classes are more complex. And classes can get very complex for humans to read.
- namedtuples are immutable. Managing mutable state adds unnecessary complexity.
- class
inheritance
adds complexity, and hides complexity.
I can't see a single advantage to using OOP classes. Obviously, if you are used to OOP, or you have to interface with code that requires classes like Django.
BTW, most other languages have some record type feature like namedtuples. Scala, for example, has case classes. This logic applies equally there.
I'm going to break from the herd on this one and provide an alternate point of view:
Never create classes.
Reliance on classes has a significant tendency to cause coders to create bloated and slow code. Classes getting passed around (since they're objects) take a lot more computational power than calling a function and passing a string or two. Proper naming conventions on functions can do pretty much everything creating a class can do, and with only a fraction of the overhead and better code readability.
That doesn't mean you shouldn't learn to understand classes though. If you're coding with others, people will use them all the time and you'll need to know how to juggle those classes. Writing your code to rely on functions means the code will be smaller, faster, and more readable. I've seen huge sites written using only functions that were snappy and quick, and I've seen tiny sites that had minimal functionality that relied heavily on classes and broke constantly. (When you have classes extending classes that contain classes as part of their classes, you know you've lost all semblance of easy maintainability.)
When it comes down to it, all data you're going to want to pass can easily be handled by the existing datatypes.
Classes were created as a mental crutch and provide no actual extra functionality, and the overly-complicated code they have a tendency to create defeats the point of that crutch in the long run.
ReferenceURL : https://stackoverflow.com/questions/18202818/classes-vs-functions
'Programing' 카테고리의 다른 글
부트 스트랩을 사용하여 중첩 된 목록에 대한 일관된 스타일링 (0) | 2021.01.10 |
---|---|
mscorlib.dll 및 System.dll (0) | 2021.01.10 |
ASP.NET 멤버십이 사용하는 기본 해시 알고리즘은 무엇입니까? (0) | 2021.01.10 |
Ruby에서 파일 이름을 바꾸는 방법은 무엇입니까? (0) | 2021.01.10 |
파이썬 세트에서 목록 가져 오기 (0) | 2021.01.10 |