산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Industrial programming >> python

파이썬 객체지향 프로그래밍 마스터하기: 종합 가이드

파이썬은 처음부터 객체지향 언어였습니다. 따라서 클래스와 객체를 생성하고 사용하는 것이 매우 쉽습니다. 이 장에서는 파이썬의 객체지향 프로그래밍 지원을 전문적으로 사용하는 데 도움을 드립니다.

객체지향(OO) 프로그래밍에 대한 이전 경험이 없다면, 기본 개념을 파악하기 위해 입문 강의를 듣거나 튜토리얼을 참조하는 것이 좋습니다.

하지만 여기 여러분을 빠르게 이해할 수 있도록 객체지향 프로그래밍(OOP)에 대한 간단한 소개를 제공합니다.

OOP 용어 개요

클래스 생성하기

class 문은 새로운 클래스 정의를 만듭니다. 클래스 이름은 키워드 class 바로 뒤에 콜론과 함께 옵니다.

class ClassName:
    'Optional class documentation string'
    class_suite

예제

다음은 간단한 파이썬 클래스의 예입니다.

class Employee:
    'Common base class for all employees'
    empCount = 0
    def __init__(self, name, salary):
        self.name = name
        self.salary = salary
        Employee.empCount += 1
    def displayCount(self):
        print("Total Employee %d" % Employee.empCount)
    def displayEmployee(self):
        print("Name : ", self.name, ", Salary: ", self.salary)

인스턴스 객체 생성하기

클래스의 인스턴스를 생성하려면 클래스 이름을 사용하여 클래스를 호출하고 __init__ 메서드가 받는 인수를 전달합니다.

"Employee 클래스의 첫 번째 객체 생성"
emp1 = Employee("Zara", 2000)
"Employee 클래스의 두 번째 객체 생성"
emp2 = Employee("Manni", 5000)

속성 접근하기

객체와 함께 점 연산자를 사용하여 객체의 속성에 접근합니다. 클래스 변수는 클래스 이름을 사용하여 접근합니다.

emp1.displayEmployee()
emp2.displayEmployee()
print("Total Employee %d" % Employee.empCount)

이제 모든 개념을 종합해 보겠습니다.

#!/usr/bin/python
class Employee:
    'Common base class for all employees'
    empCount = 0
    def __init__(self, name, salary):
        self.name = name
        self.salary = salary
        Employee.empCount += 1
    def displayCount(self):
        print("Total Employee %d" % Employee.empCount)
    def displayEmployee(self):
        print("Name : ", self.name, ", Salary: ", self.salary)

"This would create first object of Employee class"
emp1 = Employee("Zara", 2000)
"This would create second object of Employee class"
emp2 = Employee("Manni", 5000)
emp1.displayEmployee()
emp2.displayEmployee()
print("Total Employee %d" % Employee.empCount)

위 코드를 실행하면 다음과 같은 결과가 나옵니다.

Name : Zara ,Salary: 2000
Name : Manni ,Salary: 5000
Total Employee 2

클래스와 객체의 속성은 언제든지 추가, 제거, 수정할 수 있습니다.

emp1.age = 7  # 'age' 속성 추가
emp1.age = 8  # 'age' 속성 수정
del emp1.age  # 'age' 속성 삭제

일반적인 문장을 사용하여 속성에 접근하는 대신 다음 함수를 사용할 수 있습니다.

hasattr(emp1, 'age')  # 'age' 속성이 있으면 True 반환
getattr(emp1, 'age')  # 'age' 속성 값 반환
setattr(emp1, 'age', 8)  # 'age' 속성을 8로 설정
delattr(emp1, 'age')  # 'age' 속성 삭제

내장 클래스 속성

모든 파이썬 클래스는 다음과 같은 내장 속성을 유지하며, 다른 속성처럼 점 연산자를 사용하여 접근할 수 있습니다.

위 클래스로 이 모든 속성에 접근해 보겠습니다.

#!/usr/bin/python
class Employee:
    'Common base class for all employees'
    empCount = 0
    def __init__(self, name, salary):
        self.name = name
        self.salary = salary
        Employee.empCount += 1
    def displayCount(self):
        print("Total Employee %d" % Employee.empCount)
    def displayEmployee(self):
        print("Name : ", self.name, ", Salary: ", self.salary)

print("Employee.__doc__:", Employee.__doc__)
print("Employee.__name__:", Employee.__name__)
print("Employee.__module__:", Employee.__module__)
print("Employee.__bases__:", Employee.__bases__)
print("Employee.__dict__:", Employee.__dict__)

위 코드를 실행하면 다음과 같은 결과가 나옵니다.

Employee.__doc__: Common base class for all employees
Employee.__name__: Employee
Employee.__module__: __main__
Employee.__bases__: ()
Employee.__dict__: {'__module__': '__main__', 'displayCount': , 'empCount': 2, 'displayEmployee': , '__doc__': 'Common base class for all employees', '__init__': }

객체 파괴 (가비지 컬렉션)

파이썬은 불필요한 객체(내장 타입 또는 클래스 인스턴스)를 자동으로 삭제하여 메모리 공간을 확보합니다. 파이썬이 더 이상 사용되지 않는 메모리 블록을 주기적으로 회수하는 과정을 가비지 컬렉션(Garbage Collection)이라고 합니다.

파이썬의 가비지 컬렉터는 프로그램 실행 중에 작동하며 객체의 참조 카운트가 0에 도달하면 트리거됩니다. 객체의 참조 카운트는 이를 가리키는 별칭의 수에 따라 변경됩니다.

객체에 새 이름이 할당되거나 컨테이너(리스트, 튜플, 딕셔너리)에 배치되면 참조 카운트가 증가합니다. del로 삭제되거나, 참조가 재할당되거나, 참조가 범위를 벗어나면 참조 카운트가 감소합니다. 객체의 참조 카운트가 0에 도달하면 파이썬이 자동으로 수집합니다.

a = 40  # 객체 <40> 생성
b = a     # <40>의 참조 카운트 증가
c = [b]   # <40>의 참조 카운트 증가
del a     # <40>의 참조 카운트 감소
b = 100   # <40>의 참조 카운트 감소
c[0] = -1 # <40>의 참조 카운트 감소

일반적으로 가비지 컬렉터가 고아 인스턴스를 파괴하고 공간을 회수하는 것을 알아차리지 못합니다. 하지만 클래스는 인스턴스가 파괴되기 직전에 호출되는 특수 메서드 __del__()을 구현할 수 있으며, 이를 소멸자라고 합니다. 이 메서드는 인스턴스가 사용하는 비메모리 리소스를 정리하는 데 사용될 수 있습니다.

예제

이 __del__() 소멸자는 파괴될 인스턴스의 클래스 이름을 출력합니다.

#!/usr/bin/python
class Point:
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y
    def __del__(self):
        class_name = self.__class__.__name__
        print(class_name, "destroyed")

pt1 = Point()
pt2 = pt1
pt3 = pt1
print(id(pt1), id(pt2), id(pt3))  # 객체들의 id 출력
del pt1
del pt2
del pt3

위 코드를 실행하면 다음과 같은 결과가 나옵니다.

3083401324 3083401324 3083401324
Point destroyed

참고 - 이상적으로는 클래스를 별도 파일에 정의한 다음 import 문을 사용하여 메인 프로그램 파일에서 임포트해야 합니다.

클래스 상속

새로운 클래스 이름 뒤에 괄호로 부모 클래스를 나열하여 기존 클래스에서 파생된 클래스를 만들 수 있습니다.

자식 클래스는 부모 클래스의 속성을 상속받으며, 마치 자식 클래스에서 정의된 것처럼 해당 속성을 사용할 수 있습니다. 자식 클래스는 부모의 데이터 멤버와 메서드를 오버라이드할 수도 있습니다.

구문

파생 클래스는 부모 클래스와 매우 유사하게 선언되지만, 클래스 이름 뒤에 상속받을 기본 클래스 목록이 주어집니다.

class SubClassName (ParentClass1[, ParentClass2, ...]):
    'Optional class documentation string'
    class_suite

예제

#!/usr/bin/python
class Parent:
    # 부모 클래스 정의
    parentAttr = 100
    def __init__(self):
        print("Calling parent constructor")
    def parentMethod(self):
        print('Calling parent method')
    def setAttr(self, attr):
        Parent.parentAttr = attr
    def getAttr(self):
        print("Parent attribute :", Parent.parentAttr)

class Child(Parent):
    # 자식 클래스 정의
    def __init__(self):
        print("Calling child constructor")
    def childMethod(self):
        print('Calling child method')

c = Child()  # 자식 인스턴스
c.childMethod()  # 자식의 메서드 호출
c.parentMethod()  # 부모의 메서드 호출
c.setAttr(200)  # 다시 부모의 메서드 호출
c.getAttr()  # 다시 부모의 메서드 호출

위 코드를 실행하면 다음과 같은 결과가 나옵니다.

Calling child constructor
Calling child method
Calling parent method
Parent attribute : 200

비슷한 방식으로 여러 부모 클래스에서 클래스를 파생시킬 수 있습니다.

class A:
    # 클래스 A 정의 .....
class B:
    # 클래스 B 정의 .....
class C(A, B):
    # A와 B의 서브클래스 .....

issubclass() 또는 isinstance() 함수를 사용하여 두 클래스와 인스턴스의 관계를 확인할 수 있습니다.

메서드 오버라이딩

부모 클래스 메서드를 언제든지 오버라이드할 수 있습니다. 부모 메서드를 오버라이드하는 이유 중 하나는 서브클래스에서 특별하거나 다른 기능을 원하기 때문일 수 있습니다.

예제

#!/usr/bin/python
class Parent:
    # 부모 클래스 정의
    def myMethod(self):
        print('Calling parent method')

class Child(Parent):
    # 자식 클래스 정의
    def myMethod(self):
        print('Calling child method')

c = Child()  # 자식 인스턴스
c.myMethod()  # 자식은 오버라이드된 메서드 호출

위 코드를 실행하면 다음과 같은 결과가 나옵니다.

Calling child method

기본 오버로딩 메서드

다음 표는 자체 클래스에서 오버라이드할 수 있는 몇 가지 일반적인 기능을 나열합니다.

번호 메서드, 설명 및 샘플 호출
1

__init__ ( self [,args...] )

생성자 (선택적 인수 포함)

샘플 호출: obj = className(args)

2

__del__( self )

소멸자, 객체 삭제

샘플 호출: del obj

3

__repr__( self )

평가 가능한 문자열 표현

샘플 호출: repr(obj)

4

__str__( self )

출력 가능한 문자열 표현

샘플 호출: str(obj)

5

__cmp__ ( self, x )

객체 비교

샘플 호출: cmp(obj, x)

연산자 오버로딩

2차원 벡터를 나타내는 Vector 클래스를 만들었다고 가정해 보겠습니다. 더하기 연산자를 사용하여 두 벡터를 더하면 어떻게 될까요? 아마 파이썬이 에러를 낼 것입니다.

그러나 클래스에 __add__ 메서드를 정의하여 벡터 덧셈을 수행하면 더하기 연산자가 예상대로 작동합니다.

예제

#!/usr/bin/python
class Vector:
    def __init__(self, a, b):
        self.a = a
        self.b = b
    def __str__(self):
        return 'Vector (%d, %d)' % (self.a, self.b)
    def __add__(self, other):
        return Vector(self.a + other.a, self.b + other.b)

v1 = Vector(2, 10)
v2 = Vector(5, -2)
print(v1 + v2)

위 코드를 실행하면 다음과 같은 결과가 나옵니다.

Vector(7, 8)

데이터 은닉

객체의 속성은 클래스 정의 외부에서 보일 수도 있고 보이지 않을 수도 있습니다. 속성 이름에 이중 밑줄 접두사를 붙이면 외부에서 직접 보이지 않게 됩니다.

예제

#!/usr/bin/python
class JustCounter:
    __secretCount = 0
    def count(self):
        self.__secretCount += 1
        print(self.__secretCount)

counter = JustCounter()
counter.count()
counter.count()
print(counter.__secretCount)

위 코드를 실행하면 다음과 같은 결과가 나옵니다.

1
2
Traceback (most recent call last):
  File "test.py", line 12, in 
    print(counter.__secretCount)
AttributeError: JustCounter instance has no attribute '__secretCount'

파이썬은 클래스 이름을 포함하여 내부적으로 이름을 변경하여 해당 멤버를 보호합니다. object._className__attrName 형태로 이러한 속성에 접근할 수 있습니다. 마지막 줄을 다음과 같이 바꾸면 작동합니다.

print(counter._JustCounter__secretCount)

위 코드를 실행하면 다음과 같은 결과가 나옵니다.

1
2
2

python

  1. C# 클래스와 객체: 견고한 OOP를 위한 기초 다지기
  2. 파이썬 데이터 타입 마스터하기: 실전 가이드
  3. 파이썬 연산자 마스터하기: 종합 가이드
  4. 파이썬 pass 문 마스터하기: 실전 가이드
  5. Python 딕셔너리 마스터하기: 생성, 조작, 고급 기법
  6. Python 사용자 정의 예외 마스터하기: 실전 가이드
  7. Python 객체지향 프로그래밍 마스터하기: 클래스, 상속, 캡슐화, 다형성
  8. Python 상속 마스터하기: 개념, 문법, 실전 예제
  9. Java 싱글톤 패턴 완벽 가이드: 안전하게 구현하고 사용하기
  10. 라즈베리파이와 OpenCV로 자동화된 비전 기반 객체 추적 시스템