객체 지향 프로그래밍(Object Oriented Programming) 또는 OOP는 속성 및 동작이 개별 객체에 고정적으로 포함되도록 프로그램을 구성하는 수단을 제공하는 프로그래밍 패러다임입니다.
예를 들어, 사람이라는 객체는 이름, 나이, 주소 등을의 속성을 가지고 있으며 걷고, 말하고, 호흡하고, 달리기와 같은 행동으로 표현 할 수 있습니다. 또 전자메일은 받는 사람 목록, 제목, 본문 등과 같은 속성 과 첨부 파일 추가 및 보내기와 같은 동작을 포함한 객체입니다.
다른 말로 하자면, 객체 지향 프로그래밍은 회사와 직원, 학생과 교사 등의 관계뿐만 아니라 자동차와 같은 실제의 물건을 모델링하는 접근법입니다. OOP는 객체를 소프트웨어 객체로 모델링합니다. 어떤 데이터는 그들과 연관되어 특정 기능을 수행 할 수 있습니다.
핵심은 개체가 절차 형 프로그래밍 에서처럼 데이터를 표현할뿐만 아니라 프로그램의 전체 구조에서도 객체 지향 프로그래밍 패러다임의 중심에 있다는 것입니다.
클래스란 객체의 설계도(blueprint)를 코드로 나타낸 것을 의미합니다. 다시 말해, 객체를 프로그램적으로 만들기 위한 설계 코드란 의미입니다. 객체를 클래스로 나타낼 때, 추상화라는 과정을 거칩니다. 추상화란 말 그대로 추상적이게, 단순하게 나타내는 것을 의미합니다. 그렇게 객체를 단순화시켜 필요한 정보와 행위를 모은 것을 클래스라고 합니다.
객체는 데이터에 대한 파이썬의 추상화입니다. 파이썬 프로그램의 모든 데이터는 객체 또는 객체 간의 관계로 표현됩니다. 모든 객체에는 ID(Identity), 유형(Type) 및 값(Value)이 있습니다.
클래스에 의해서 만들어진 객체를 인스턴스라고도 합니다. 클래스를 만들었다고 해서, 우리가 실제로 사용할 수 있는 것은 아닙니다. 클래스라는 것은 단지 객체가 가질 수 있는 상태 정보와 행동들에 대한 정의이기 때문입니다. 클래스를 실제로 나타나게 하는 것을, 다시 말해서 클래스에 대한 변수를 선언하는 것을 “인스턴스를 생성한다”라 하고, 이렇게 생성된 변수를 인스턴스라 하며, 이 인스턴스는 메모리 공간을 차지하게 됩니다. 그리고, 인스턴스의 메소드를 이용하여 클래스의 속성을 설정 및 변경할 수 있습니다.
Define a Class
파이썬에서 클래스의 정의는 간단 합니다.
classDog:pass
클래스를 정의하려면 class 키워드와 클래스의 이름을 사용하면 됩니다. 또한 여기에서는 Python 키워드 pass를 사용했습니다. 이것은 코드가 결국 진행할 place holder로 자주 사용됩니다. 이 코드를 사용하면 오류가 발생하지 않고 실행할 수 있습니다.
Instance Attributes
모든 클래스는 객체를 만들고 모든 객체는 속성(attribute)이라는 특징을 포함합니다. 객체의 초기 속성을 기본값으로 지정하는 init () 메서드를 사용하여 초기화 합니다. 이 메소드에는 객체 자체 (예 : Dog)를 참조하는 self 변수뿐만 아니라 하나 이상의 인수가 있어야합니다.
classDog:# Initializer / Instance Attributesdef__init__(self,name,age): self.name = name self.age = age
Dog() 클래스의 경우 각 개(dog)마다 특정 이름과 나이가 있습니다. 실제로 개를 만들 때 알아 두어야 할 중요한 사항입니다. 이 클래스는 실제로 개를 정의하기위한 것으로, 특정 이름과 나이를 가진 개별 개 인스턴스를 생성하지 않습니다.
마찬가지로, self 변수는 클래스의 인스턴스이기도합니다. 클래스의 인스턴스는 값이 다양하기 때문에 self.name = name 대신 Dog.name = name으로 지정할 수도 있습니다. 그러나 모든 개가 동일한 이름을 사용하지 않기 때문에 우리는 다른 인스턴스에 다른 값을 할당 할 수 있어야합니다. 따라서 각 클래스의 개별 인스턴스를 추적하는 데 도움이되는 유일한 특별한 self 변수가 필요합니다.
Class Attributes
인스턴스 속성은 각 객체에 고유하게 지정되지만 클래스 속성은 모든 인스턴스에 대해 동일합니다. 다음 코드를 보면 개마다 고유한 이름과 나이가 있지만 모든 개는 포유류입니다.
classDog:# Class Attribute species ='포유류'# Initializer / Instance Attributesdef__init__(self,name,age): self.name = name self.age = age
Instantiating Objects
인스턴스 생성이란 새로운 고유한 클래스 인스턴스를 만드는 용어입니다.
python>>>classDog:... pass...>>>Dog()<__main__.Dog object at 0x1004ccc50>>>>Dog()<__main__.Dog object at 0x1004ccc90>>>> a =Dog()>>> b =Dog()>>> a == bFalse
위의 코드를 보면 새로운 Dog() 클래스를 정의한 다음 두 개의 새로운 개를 만들고 각각 다른 객체에 할당했습니다. 따라서 클래스의 인스턴스를 만들려면 클래스 이름을 사용하고 그 뒤에 괄호를 사용합니다. 그런 다음 각 인스턴스가 실제로 다르다는 것을 입증하기 위해 두 개의 개를 인스턴스화하고 각 인스턴스에 변수를 할당 한 다음 해당 변수가 동일한 지 테스트했습니다.
클래스 인스턴스의 유형(type)이 무엇으로 나오는지 확인해 보겠습니다.
>>>classDog:... pass...>>> a =Dog()>>>type(a)<class'__main__.Dog'>
조금 복잡한 예를 들어 보겠습니다.
classDog:# Class Attribute species ='포유류'# Initializer / Instance Attributesdef__init__(self,name,age): self.name = name self.age = age# Instantiate the Dog objectphilo =Dog("두부", 5)mikey =Dog("뭉치", 6)# Access the instance attributesprint("{} is {} and {} is {}.".format( philo.name, philo.age, mikey.name, mikey.age))# Is Philo a mammal?if philo.species =="mammal":print("{0} is a {1}!".format(philo.name, philo.species))
위의 코드를 실행하면 다음과 같은 결과가 출력 됩니다.
두부 is 5 and 뭉치 is 6.
Dog() 클래스의 새 인스턴스를 만들어 변수 "philo"에 할당했습니다. 우리는 그 다음에 개명과 나이를 나타내는 "두부"와 5 살이라는 인자를 각각 전달했습니다.
이러한 속성은 init 메쏘드로 전달됩니다. init 메쏘드는 새로운 인스턴스를 생성 할 때마다 호출되며, 객체에 이름과 나이를 붙입니다. 클래스의 새 인스턴스를 만들면 Python은 자동으로 자체 정의 (이 경우 Dog)를 결정하고이를 init 메소드에 전달합니다.
Instance Methods
인스턴스 메소드는 클래스 내부에서 정의되며 인스턴스의 내용을 가져 오는 데 사용됩니다. 또한 객체의 속성을 사용하여 작업을 수행하는 데에도 사용할 수 있습니다. init 메쏘드와 마찬가지로, 첫번째 인자는 항상 self입니다.
classDog:# Class Attribute species ='mammal'# Initializer / Instance Attributesdef__init__(self,name,age): self.name = name self.age = age# instance methoddefdescription(self):return"{} is {} years old".format(self.name, self.age)# instance methoddefspeak(self,sound):return"{} says {}".format(self.name, sound)# Instantiate the Dog objectmikey =Dog("뭉치", 6)# call our instance methodsprint(mikey.description())print(mikey.speak("멍 멍"))
뭉치 is 6 years old
뭉치 says 멍 멍
메서드 speak ()에서는 행동을 정의합니다.
Object Inheritance
상속(inheritance)이란 한 클래스가 다른 클래스의 속성 및 메소드를 사용하는 프로세스입니다. 새로 형성된 클래스를 하위 클래스라고하며 하위 클래스가 파생 된 클래스를 상위 클래스라고합니다.
하위 클래스는 상위 클래스의 기능 (예 : 속성 및 동작)을 재정의하거나 확장한다는 점에 유의해야합니다. 즉, 하위 클래스는 부모의 모든 특성과 동작을 상속하지만 다른 동작을 지정하여 수행 할 수도 있습니다. 가장 기본적인 유형의 클래스는 객체입니다. 일반적으로 다른 모든 클래스는 부모로부터 상속됩니다.
새로운 클래스 인 Python 3을 정의하면이 클래스는 암묵적으로 객체를 부모 클래스로 사용합니다. 따라서 다음의 두 정의는 동일합니다.
classDog(object):pass# In Python 3, this is the same as:classDog:pass
Dog 객체가 여러 개 있다고 가정합니다. 각 Dog 객체는 이름과 나이가 다르고 하는 행동들도 다르다고 가정 합니다. 한 개와 다른 개를 구별하는 방법이 어던것이 있을 까요?
# Parent classclassDog:# Class attribute species ='포유류'# Initializer / Instance attributesdef__init__(self,name,age): self.name = name self.age = age# instance methoddefdescription(self):return"{} is {} years old".format(self.name, self.age)# instance methoddefspeak(self,sound):return"{} says {}".format(self.name, sound)# Child class (inherits from Dog class)classMaltise(Dog):defrun(self,speed):return"{} runs {}".format(self.name, speed)# Child class (inherits from Dog class)classBulldog(Dog):defrun(self,speed):return"{} runs {}".format(self.name, speed)# Child classes inherit attributes and behaviors from the parent classjim =Bulldog("뭉치", 12)print(jim.description())# Child classes have specific attributes and behaviors as wellprint(jim.run("천천히"))
뭉치 is 12 years old
뭉치 runs 천천히
말티즈와 불독을 구별 할 수있는 특별한 속성이나 메소드는 추가하지 않았지만 이제는 서로 다른 클래스이므로 각각의 속도를 정의하는 클래스 속성을 서로 다르게 지정할 수 있습니다.
# Parent classclassDog:# Class attribute species ='mammal'# Initializer / Instance attributesdef__init__(self,name,age): self.name = name self.age = age# instance methoddefdescription(self):return"{} is {} years old".format(self.name, self.age)# instance methoddefspeak(self,sound):return"{} says {}".format(self.name, sound)# Child class (inherits from Dog() class)classMaltise(Dog):defrun(self,speed):return"{} runs {}".format(self.name, speed)# Child class (inherits from Dog() class)classBulldog(Dog):defrun(self,speed):return"{} runs {}".format(self.name, speed)# Child classes inherit attributes and behaviors from the parent classjim =Bulldog("Jim", 12)print(jim.description())# Child classes have specific attributes and behaviors as wellprint(jim.run("slowly"))# Is jim an instance of Dog()?print(isinstance(jim, Dog))# Is julie an instance of Dog()?julie =Dog("Julie", 100)print(isinstance(julie, Dog))# Is johnny walker an instance of Bulldog()johnnywalker =Maltise("Johnny Walker", 4)print(isinstance(johnnywalker, Bulldog))# Is julie and instance of jim?print(isinstance(julie, jim))
C:\Users\Nainsys\Anaconda3\envs\onebook\python.exe C:/Users/Nainsys/PycharmProjects/OneBook/JustTest.py
Jim is 12 years old
Traceback (most recent call last):
Jim runs slowly
File "C:/Users/Nainsys/PycharmProjects/OneBook/JustTest.py", line 52, in <module>
True
print(isinstance(julie, jim))
True
False
TypeError: isinstance() arg 2 must be a type or tuple of types
이해가 되십니까? johnnywalker는 Bulldog () 클래스의 인스턴스가 아니지만 jim과 julie는 모두 Dog () 클래스의 인스턴스입니다. 그런 다음 julie가 jim의 인스턴스인지 테스트합니다. Jim은 클래스 자체가 아닌 클래스의 인스턴스이므로 불가능합니다. 따라서 TypeError가 발생합니다.
Overriding
하위 클래스는 상위 클래스의 특성 및 동작을 재정의 할 수 있습니다. 오버라이딩(Overriding)이란 : 상위 클래스가 가지고 있는 메소드를 하위 클래스가 재정의 해서 사용하는 것을 말합니다.
# 부모 클래스classPets: dogs = []def__init__(self,dogs): self.dogs = dogs# 부모 클래스classDog:# 클래스 속성 species ='mammal'# Initializer / Instance attributesdef__init__(self,name,age): self.name = name self.age = age self.is_hungry =True# Instance methoddefdescription(self):return self.name, self.age# Instance methoddefspeak(self,sound):return"%s says %s"% (self.name, sound)# Instance methoddefeat(self): self.is_hungry =False# Dog class로 부터 상속 받은 자식 클래스classRussellTerrier(Dog):defrun(self,speed):return"%s runs %s"% (self.name, speed)# Dog class로 부터 상속 받은 자식 클래스classBulldog(Dog):defrun(self,speed):return"%s runs %s"% (self.name, speed)# Create instances of dogsmy_dogs = [Bulldog("Tom", 6),RussellTerrier("Fletcher", 7),Dog("Larry", 9)]# Instantiate the Pets classmy_pets =Pets(my_dogs)# Outputprint("I have {} dogs.".format(len(my_pets.dogs)))for dog in my_pets.dogs: dog.eat()print("{} is {}.".format(dog.name, dog.age))print("And they're all {}s, of course.".format(dog.species))are_my_dogs_hungry =Falsefor dog in my_pets.dogs:if dog.is_hungry: are_my_dogs_hungry =Trueif are_my_dogs_hungry:print("My dogs are hungry.")else:print("My dogs are not hungry.")
I have 3 dogs.
Tom is 6.
Fletcher is 7.
Larry is 9.
And they're all mammals, of course.
My dogs are not hungry.