OOP(Object-Oriented Programming - 실행 순서가 아닌 단위 객체를 중심으로 프로그램을 작성.)

- 객체: 실생활에서의 모든 자료 (물건)

- 모든 객체는 속성행동을 가진다.

 

> 객체 지향 프로그래밍은 이러한 객체 개념을 프로그램으로 표현함.

예) 속성 > 변수, 행동 > 함수로 표현

 

클래스

> 하나의 새로운 데이터 타입을 만드는 것 

> 클래스를 사용하는 목적이 변수와 함수를 묶어서 하나의 새로운 객체(타입)로 만드는 것

> 실제 세계에 존재하는 실체(instance)를 객체(object)라고 하고, 객체들의 공통점을 간추려서 개념적으로 나타낸 것 

> 어떤 클래스를 만들기 위해서는 그 객체가 갖는 성질(상태, 속성, 변수)과 그 객체가 하는 행동(메소드, 함수)을 정의해주면 된다고 이해하기

 

잉어빵, 황금 붕어빵과 같은 차별화된 붕어빵을 만들기 위해 틀을 잘 정의하는 것이지요. 그러나 아무리 틀을 예쁘고 정교하게 만들었다고 해서 붕어빵이 나오는 것은 아닙니다. 실제로 먹을 수 있는 붕어빵을 만들려면 붕어빵 틀에 반죽을 넣고 붕어빵을 구워야 합니다. 이처럼 붕어빵 틀에 반죽을 넣어서 만들어진 붕어빵이 인스턴스에 해당합니다.

 

클래스(class)와 인스턴스(instance)의 관계

> 학교와 모범생 관계라고 생각하면 됨.

> 학교는 커리큘럼을 가지고 있는데 아무리 좋은 커리큘럼을 가지고 있다고 해도 모범생이 무조건 나오는 것은 아니다. 모범생이 나올려면 공부도 열심히 시키고 질 높은 수업, 환경을 만들어줘야 한다. 이처럼 학교라는 어떠한 틀에서 좋은 수업 환경을 받은 모범생이 인스턴스에 해당함. 

 

예시

class Concept:
    def __init__ (self,parameter):
        self.parameter = parameter
        pass

    def method(self):
        return self. parameter
        
instance = Concept("argument")
instance.method()

 

 

 

> 코드 해석 

 >> Concept이라는 하나의 타입을 만듦.

 >> type(instance) 타입 확인 

 >> 타입이 객체임. 

 >> 이전에 썼던 리스트, 문자열과 같은 것들도 다 타입에 해당.

list, 문자열 모두 class였다는 걸 알 수 있다.

 

 >> __init__ : 이건 어떤 객체가 실행되면 무조건적으로 실행해주는 파이썬에서 특별하게 정의한 함수 메서드

 

b라는 변수를 Book() 타입이라고 할당하자마자 바로 __init__의 함수가 실행됨.

 

 

 

자동차 클래스 생성 

class Car:
    color = ""
    speed = 0

    def up_speed(self, value):
        self.speed += value

    def down_speed(self, value):
        self.speed -= value

 

> self는 클래스 자기 자신을 가리킴.

> 즉, 6,9행 self.speed는 인스턴스 변수, 3행의 speed는 클래스 변수

> 클래스 내 모든 method의 첫 번째 매개변수는 반드시 self 포함되어야함.

> 클래스에서 정의된 변수, 함수 사용 시 클래스.변수, 클래스.함수로 접근.

car = Car()
car.color = "Yellow"
car.up_speed(100)
car.down_speed(51)
print(car.color, car.speed)

 

 + 자신의 클래스 안에서 함수 호출: self.함수명() 

 

# class 

class 자동차:
	# 자동차의 속성(attribute)
    	자동차 색상
        자동차 속도
	# 자동차의 기능
    	속도 올리기()
        속도 내리기()
# 자동차(인스턴스)
자동차1 = 자동차()
자동차2 = 자동차()
자동차3 = 자동차()

 

> 각각의 인스턴스에는 별도의 공간(메모리)이 존재하며, 각각에 별도의 값 할당이 가능함. 

> 정리

class Car:
    color = ""
    speed = 0

    def up_speed(self, value):
        self.speed += value

    def down_speed(self, value):
        self.speed -= value

my_car = Car()
her_car = Car()
his_car = Car()

my_car.color = "Red" ; her_car.color = "Black" ; his_car.color = "Blue"
my_car.up_speed(100) ; her_car.up_speed(50) ; his_car.up_speed(80)
my_car.down_speed(10) ; her_car.down_speed(5) ; his_car.down_speed(20)

print(f"my_car is {my_car.color} and current speed is {my_car.speed}km/h")
print(f"my_car is {her_car.color} and current speed is {her_car.speed}km/h")
print(f"my_car is {his_car.color} and current speed is {his_car.speed}km/h")

생성된 객체는 각각의 속성을 유지하고 있음.

 

 

 

클래스 생성 단계 및 사용

 

1단계 클래스 정의

class 클래스_이름:
	// 멤버변수 선언
    // 메소드 선언
    
    
# 예시
class Car:
	def __init__ (self, c):
    	self.color = c
	
    def up_speed(self,value):
     ....

 

 

2단계 인스턴스 생성 

인스턴스 = 클래스_이름()

# 예시
my_car1 = Car("red")

 

3단계 변수 및 메소드 사용

인스턴스.멤버변수 = 값
인스턴스.메소드()

# 예시
my_car1.color = "yellow"
my_car1.up_speed(30)

 

 

 

 

 

 

 

동일한 이름의 클래스 변수가 존재할 경우 

 

1.

class Car:
    speed = 100
    
    def __init__(self, speed):
        print(f"{Car.speed = }")
        print(f"{self.speed = }")
        self.speed += speed
        
    def up(self, speed):
        self.speed += speed
        return self.speed
    
    def down(self, speed):
        self.speed -= speed
        return self.speed
    
car = Car(1)

print(f"{car.up(1) = }")
print(f"{car.down(1) = }")
print(f"{Car.speed = }")

 

 

VS

 

2.

class Car:
    speed = 100
    
    def __init__(self, speed):
        print(f"{speed = }")
        print(f"{Car.speed = }")
        print(f"{self.speed = }")
        self.speed = speed
        self.speed += speed
        
    def up(self, speed):
        self.speed += speed
        return self.speed
    
    def down(self, speed):
        self.speed -= speed
        return self.speed
    
car = Car(1)

print(f"{car.up(1) = }")
print(f"{car.down(1) = }")
print(f"{Car.speed = }")

 

 

> 이를 이해하기 위해서는 네임스페이스에 대한 이해가 필요하다. 

> 네임스페이스:  변수가 객체를 바인딩할 때 그 둘 사이의 관계를 저장하고 있는 공간 

 >> 바인딩: 자료형, 변수명, 변수값에 각각 int, num, 10 이라는 구체적인 값을 할당하는 각각의 과정

# 출처: 파이썬으로 배우는 알고리즘 트레이딩  

파이썬에서는 클래스가 정의되면 그림 6.11과 같이 하나의 독립적인 네임스페이스가 생성됩니다. 
그리고 클래스 내에 정의된 변수나 메서드는 해당 네임스페이스 안에 파이썬 딕셔너리 타입으로 저장됩니다.
Stock 클래스는 그림 6.11과 같이 Stock이라는 네임스페이스 안에 
'market':'kospi'라는 값을 가진 딕셔너리를 포함합니다.

![](https://wikidocs.net/images/page/1743/6.11.png)

**그림 6.11 파이썬 클래스 네임스페이스**

Stock 클래스의 네임스페이스를 파이썬 코드로 확인하려면 클래스의 `__dict__` 속성을 확인하면 됩니다.
딕셔너리 타입에 'market':'kospi'라는 키와 값 쌍이 존재하는 것을 확인할 수 있습니다.

```{.py}
Stock.__dict__
mappingproxy({
'market': 'kospi',
'__module__': '__main__', 
'__dict__': <attribute '__dict__' of 'Stock' objects>, 
'__doc__': None, 
'__weakref__': <attribute '__weakref__' of 'Stock' objects>})

 

> 클래스가 독립적인 네임스페이스를 가지고 클래스 내의 변수나 메서드를 네임스페이스에 저장하고 있으므로 다음과 같이 클래스 내의 변수에 접근이 가능한 것. 

 

 

> 정리

1번 코드는 speed라는 클래스 변수가 정의되고

반면에 인스턴스 변수 speed가 정의가 없다면 인스턴스 변수 sepeed는 클래스 변수 speed의 초기값을 공유

그런데 그 이후 클래스 변수 speed는 인스턴스 변수 speed가 변경되어도 클래스 변수의 값은 변경되지 않고

그냥 자기 갈 길 간다고 생각하면 된다. 

 

2번 코드는 1번 코드와 동일한 형식이지만 클래스 변수와 인스턴스 변수가 동일한 이름이라도 

별도로 코딩해줌으로써 헷갈리는 걸 방지했다고 볼 수 있다.

따라서 2번 코드로 코딩해주는 것이 더 정상적이다.  

+ Recent posts