1. 객체(object)

python에서 모든 것은 객체입니다.
모든 객체는 type, attribute, method를 가집니다.

  • type: 어떤 operator와 method가 가능한가?
  • attribute: 어떤 데이터(상태)를 가지는가?
  • method: 어떤 행위를 할 수 있는가?

1.1. 객체 지향 프로그래밍(OOP)

객체지향프로그래밍은 여러 개의 독립된 단위, 객체들의 모임과 상호작용(method)로 파악하고자 하는 것입니다.

2. 클래스(class)

클래스는 공통된 attribute와 method를 가진 객체들의 설계도입니다.
클래스 내부에는 데이터와 함수를 정의할 수 있습니다.
모든 클래스의 최상위 클래스는 type클래스입니다. 메타클래스라고도 합니다.
그러므로 클래스도 객체입니다.
type(int)를 찍어보면 type을 return합니다.

2.1. 인스턴스(instance)

인스턴스란 특정 클래스의 실제 데이터 입니다.
앞에서 파이썬의 모든 것은 객체라고 하였는데, 모든 객체는 특정 클래스의 인스턴스 입니다.

클래스가 설계도라면 인스턴스는 클래스를 통해 만들어진 실제 객체 입니다.
예를 들면 데이터 a=1 이 있을 때, 1은 객체이고 Interger클래스의 인스턴스라고 명할 수 있습니다.

아래의 코드는 클래스의 선언과 인스턴스 생성입니다.

# Person 클래스
class Person:
    pass

# yu는 Person 클래스의 인스턴스
p1 = Person()    # ()가 붙는 이유는 생성자 메서드이기 때문입니다.
p2 = Person()

# p 변수에 담긴 인스턴스가 Person 클래스의 인스턴스인지 확인해봅시다.
# isinstance 함수를 활용합니다.
# type은 class 이지만 소문자로 작성 됐습니다.
isinstance(p,Person), isinstance([],tuple), type(None)
# 결과 (True, False, NoneType)

# p1객체와 p2객체의 타입을 비교해 봅니다.
type(p1),type(p2)
# 타입이 같다는 것을 알 수 있습니다.

# 그렇다면 p1과 p2는 같은 객체일까요?
p1 == p2
# 결과 (False)

2.2. 클래스명 짓기

  • 일반 변수/함수명은 전부 소문자에, 띄어쓰기가 필요하면 _ 로. => snake_case
  • 클래스명은 첫글자 대문자에, 띄어쓰기 필요하면 또 대문자로 => PascalCase, UpperCamelCase

몇몇 예외로 str(),type()등은 method가 아닌 class입니다.

3. attribute와 method

attribute는 java의 fileds(필드)와 같다고 볼 수 있습니다.

3.1. attribute(속성)

속성은 객체의 데이터(상태)를 뜻합니다.
person.name이라고 하면 Person클래스의 객체들이 가지게 될 데이터입니다.

class Person:
    pass

# yu는 Person 클래스의 인스턴스
p1 = Person()
p2 = Person()

p1.name = '난 p1'    # 인스턴스 변수
p2.name = '난 p2'

image

3.1.1. 인스턴스 변수

각 인스턴스들의 고유한 데이터로 생성자 메서드에서 self.변수명으로 정의합니다.
인스턴스가 생성된 후 접근할 때는 인스턴스명.변수명으로 접근합니다.

java의 this를 생각하자

3.1.2. 클래스 변수

  • 클래스의 속성(attribute)
  • 모든 인스턴스에서 공유가능
  • 클래스 선언 내부에서 정의
  • 클래스.변수명으로 접근 및 할당
class Circle:
    pi = 3.14

c1 = Circle()
c2 = Circle()
print(c1.pi, c2.pi)
# 결과값 (3.14, 3.14)

c2.pi = 0
print(c1.pi, c2.pi)
# 결과값 (3.14, 0)

print(Circle.pi)    # 클래스 변수
# 결과값 (3.14)

인스턴스들은 초기화 pi를 재할당하면 인스턴스간에 값이 바뀌지만 Class변수는 변하지 않으므로 Class변수로 접근하면 모든 인스턴스 간에 공유가 가능하다.

자바의 스태틱 변수와는 어떻게 다를까?

자바의 스태틱 변수와는 어떻게 다를까?

자바의 스태틱 변수(static variable)과 파이썬의 클래스 변수(class variable)는 몇 가지 다른 점이 있습니다.

  1. 초기화 시점:
  • 자바의 스태틱 변수는 클래스가 로드될 때 초기화됩니다. 클래스의 인스턴스 생성과는 독립적으로 존재하며, 클래스의 정적 블록에서 초기화할 수 있습니다.
  • 파이썬의 클래스 변수는 클래스가 정의될 때 초기화됩니다. 클래스의 인스턴스 생성과는 독립적으로 존재하며, 클래스 정의 내부에서 할당됩니다.

2.접근 방법:

  • 자바의 스태틱 변수는 클래스 이름을 통해 접근할 수 있습니다. 예를 들어, ClassName.staticVariable과 같이 접근합니다.
  • 파이썬의 클래스 변수는 클래스 이름 또는 클래스의 인스턴스를 통해 접근할 수 있습니다. 예를 들어, ClassName.classVariable 또는 instanceName.classVariable과 같이 접근합니다.
  1. 상속과 오버라이딩:

-자바의 스태틱 변수는 상속에 따른 오버라이딩을 지원하지 않습니다. 즉, 자식 클래스에서 스태틱 변수를 재정의할 수 없습니다. 슈퍼 클래스의 스태틱 변수와 같은 이름의 스태틱 변수를 자식 클래스에서 선언하면, 자식 클래스만의 독립적인 스태틱 변수가 생성됩니다.
-파이썬의 클래스 변수는 상속에 따른 오버라이딩을 지원합니다. 자식 클래스에서 클래스 변수를 재정의하면, 자식 클래스의 클래스 변수가 슈퍼 클래스의 클래스 변수를 가리키게 됩니다. 하지만 인스턴스 변수와 마찬가지로 인스턴스에서 클래스 변수를 오버라이딩할 수는 없습니다.

  1. 사용 목적:

-자바의 스태틱 변수는 클래스 수준의 데이터를 저장하고 공유하는 용도로 사용됩니다. 여러 인스턴스 간에 동일한 값을 공유할 필요가 있는 경우 자주 사용됩니다.
-파이썬의 클래스 변수도 마찬가지로 클래스 수준의 데이터를 저장하고 공유하는 용도로 사용됩니다. 인스턴스 간에 동일한 값을 공유하거나, 클래스의 모든 인스턴스가 접근 가능한 값을 저장할 때 사용됩니다.

3.2. 인스턴스 method(행위)

클래스 내부에 정의되는 메서드는 기본적으로 인스턴스 메서드로 생성됩니다.
인스턴스의 메서드는 자동으로 항상 자기자신을 인자로 추가 합니다.
특정 데이터 타입(또는 클래스)의 객체에 공통적으로 적용 가능한 행위(behavior)들을 의미합니다.

인스턴스는 기본적으로 인스턴스 메서드, 클래스 메서드, 스태틱메서드 모두 접근할 수 있지만,
인스턴스가 할 행동은 모두 인스턴스 메서드로 한정 지어서 설계합니다.

dir(객체)를 사용하면 해당 객체가 사용한 메서드 목록을 볼 수 있습니다.

class Person:
    def talk(self):
            print(f'안녕하세요 {self.name}입니다.')

p = Person()
p.name = '라라'
p.talk()    # 인자로 아무것도 넣지 않았음에도 메서드가 실행된다. 자기자신을 자동으로 인자로 넣기 때문이다.
# 결과값(안녕하세요 라라입니다.)

3.2.1. 생성자 메서드(constructor)

인스턴스 객체가 생성될 때 자동으로 호출되는 함수입니다.
반드시 __init__이라는 이름으로 정의합니다.

class Person:
    def __init__(self,name):
        print('생성될 때 자동으로 호출되는 메서드입니다.')
        self.name = name    # 생성될 때 MyClass('lala')로 초기화와 동시에 attribute를 정의할 수 있습니다.

    def talk(self):
        print(f'안녕, 나는 {self.name}')

p = Person('lala')
print(p.name)
p.talk()    # 생성자로 name을 인스턴스 속성으로 지정했기 때문에 따로 name attribute를 지정 안해줘도 출력이 가능
# 결과값 : lala, 안녕 나는 lala

image

이때 p2 = Person()으로 객체를 생성하려하면 오류가 발생하게 됩니다.
이때는 name 매개변수에 기본값을 지정하여 오류를 해결할 수 있습니다.
def __init__(self,name='default')
혹은 가변인자(args)나 키워드인자(kwargs)로 설정하는 것도 가능합니다.
def __init__(slef, *name)

3.2.2. 소멸자 메서드(destructor)

인스턴스 객체가 소멸(파괴)되기 직전에 자동으로 호출되는 함수입니다.
반드시 __del__ 이라는 이름으로 정의합니다.
인스턴스명을 재할당 한다면 역시 소멸자 메서드가 실행됩니다.

# 소멸자 정의
def __del__(self):
    print('소멸될 때 자동으로 호출되는 메서드입니다.')

# 소멸자 활용
del 인스턴스

# 재할당
p = 123 # 이 경우에도 소멸자 메서드가 실행됩니다. 참조를 잃은 객체는 가비지 컬렉터에 의해 소멸되기 때문입니다.

3.2.3. 스페셜 메서드

더블언더스코어(__)가 있는 메서드는 특별한 일을 하기 위해 만들어진 메서드이기 때문에 스페셜 메서드 혹은 매직 메서드라고 불립니다.
스페셜 메서드를 오버라이드 하면 인스턴스간 대/소비교가 가능한 등의 기능을 작성할 수 있습니다.

'__str__(self)', # 객체 print시 보여줄 내용
'__len__(self)',
'__repr__(self)',
'__lt__(self, other)',
'__le__(self, other)',
'__eq__(self, other)',
'__ne__(self, other)',
'__gt__(self, other)',
'__ge__(self, other)',

3.2.4. 클래스 메서드

클래스가 사용할 메서드에 해당합니다.
@classmethod 데코레이터를 사용하여 정의합니다.
메서드 호출시, 첫 번째 인자로 클래스 cls가 전달됩니다

클래스 자체(cls)와 클래스 속성에 접근할 필요가 있다면 클래스 메서드로 정의합니다.

class MyClass:
    @classmethod
    def class_method(cls, arg1, arg2, ...):
        ...

# 자동으로 첫 번째 인자로 클래스(MyClass)가 들어갑니다.
MyClass.class_method(.., ..)  

3.2.5. 스태틱 메서드

클래스가 사용할 메서드에 해당합니다.
인스턴스와 독립적으로 동작하는 메서드입니다.(인스턴스의 생성없이 사용이 가능)
@staticmethod 데코레이터를 사용하여 정의합니다.
호출시, 어떠한 인자도 자동으로(self, cls)전달되지 않습니다.
그러므로 인스턴스에 접근할 수 없습니다.
속성을 다루지 않고(인스턴스에 의존하지 않고) 단지 기능(행동)만을 하는 메서드를 정의할 때 사용합니다.

클래스와 클래스 속성에 접근할 필요가 없다면 정적 메서드로 정의합니다.

class MyClass:
    class_variable = 10

    def __init__(self):
        self.instance_variable = 20

    def instance_method(self):
        print("Instance method")

    @staticmethod
    def static_method():
        print("Static method")

# 인스턴스 생성
obj = MyClass()

# 인스턴스 메서드 호출
obj.instance_method()

# 스태틱 메서드 호출
MyClass.static_method()

클래스메서드와 스태틱메서드의 차이

클래스메서드와 스태틱메서드의 차이

  1. 첫 번째 인자:
  • 클래스 메서드는 첫 번째 인자로 클래스 자신을 나타내는 cls를 받습니다. 보통 cls라는 이름이 관례적으로 사용됩니다. 클래스 메서드 내에서는 cls를 사용하여 클래스 수준의 작업을 수행할 수 있습니다.
  • 스태틱 메서드는 첫 번째 인자로 클래스나 인스턴스를 나타내는 것이 아닌 특정한 인자를 받지 않습니다. 따라서 스태틱 메서드는 클래스나 인스턴스와 독립적으로 동작합니다.

2.클래스 변수 접근:

  • 클래스 메서드는 cls를 통해 클래스 변수에 접근할 수 있습니다. 클래스 변수는 클래스 전체에서 공유되는 변수입니다. cls를 사용하여 클래스 변수를 조작하거나 클래스 수준의 동작을 수행할 수 있습니다.
  • 스태틱 메서드는 클래스 변수에 직접 접근할 수 없습니다. 스태틱 메서드는 클래스와 인스턴스와 독립적으로 동작하기 때문에, 클래스 변수에는 접근할 수 없습니다. 스태틱 메서드 내부에서는 클래스 변수 대신에 전역 변수나 다른 지역 변수를 사용해야 합니다.
  1. 상속:
  • 클래스 메서드는 상속에 따른 메서드 오버라이딩을 지원합니다. 자식 클래스에서 동일한 이름의 클래스 메서드를 정의하면, 자식 클래스의 메서드가 호출됩니다.
  • 스태틱 메서드는 상속과 관련하여 메서드 오버라이딩을 지원하지 않습니다. 스태틱 메서드는 클래스와 인스턴스와 독립적으로 동작하므로, 자식 클래스에서 스태틱 메서드를 재정의하더라도 슈퍼 클래스의 스태틱 메서드가 가려지지 않습니다.

4. 인스턴스와 클래스 간의 이름 공간(namespace)

네임스페이스(namespace)는 클래스 내부에서 변수와 메서드가 정의되고 사용되는 영역입니다.
네임스페이스는 변수와 메서드의 이름을 저장하고 관리하는 공간으로, 각 클래스 인스턴스마다 별도의 네임스페이스를 가지게 됩니다.
클래스를 정의하면 클래스와 함께 참조(이름)가 생성됩니다.
인스턴스를 만들면 인스턴스 객체가 생성되고 참조가 생성됩니다.
인스턴스에서 특정 속성에 접근하면, 인스턴스-클래스-상위클래스 순으로 탐색합니다.

클래스의 네임스페이스에는 다음과 같은 요소들이 포함될 수 있습니다:

  • 인스턴스 변수: 클래스의 인스턴스마다 고유한 값을 가지는 변수입니다. 각 인스턴스마다 독립적인 인스턴스 변수가 생성되며, 인스턴스 내부의 네임스페이스에 저장됩니다.
  • 클래스 변수: 클래스 전체에서 공유되는 변수입니다. 모든 인스턴스가 동일한 클래스 변수를 참조하게 됩니다. 클래스 변수는 클래스 내부의 네임스페이스에 저장됩니다.
  • 메서드: 클래스의 동작을 정의하는 함수입니다. 메서드는 클래스 내부의 네임스페이스에 저장되며, 클래스의 인스턴스들이 해당 메서드를 공유하여 호출할 수 있습니다.

변수와 메서드는 LEGB rule을 따릅니다. 그러므로

a = 100

class Sample:
    a = 1    # 클래스 변수입니다.

    def func(self):    # 함수이므로 scope가 LEGB rule을 따릅니다.
        b = 2

        # return self.a + b    # 결과값 3
        return a + b    # 결과값 102

s = Sameple
s.func()

image

댓글남기기