Python-객체 지향
파이썬은 존재 한 이후로 객체 지향 언어였습니다. 이 때문에 클래스와 객체를 만들고 사용하는 것은 매우 쉽습니다. 이 장은 Python의 객체 지향 프로그래밍 지원을 사용하는 전문가가되는 데 도움이됩니다.
객체 지향 (OO) 프로그래밍에 대한 이전 경험이없는 경우 기본 개념을 파악할 수 있도록 이에 대한 입문 과정이나 적어도 일종의 자습서를 참조 할 수 있습니다.
그러나 여기에 OOP (Object-Oriented Programming)에 대한 간략한 소개가 있습니다.
OOP 용어 개요
Class− 클래스의 모든 객체를 특성화하는 속성 집합을 정의하는 객체에 대한 사용자 정의 프로토 타입. 속성은 점 표기법을 통해 액세스되는 데이터 멤버 (클래스 변수 및 인스턴스 변수) 및 메서드입니다.
Class variable− 클래스의 모든 인스턴스가 공유하는 변수. 클래스 변수는 클래스 내에서 정의되지만 클래스의 메서드 외부에서 정의됩니다. 클래스 변수는 인스턴스 변수만큼 자주 사용되지 않습니다.
Data member − 클래스 및 그 객체와 관련된 데이터를 보유하는 클래스 변수 또는 인스턴스 변수.
Function overloading− 특정 기능에 하나 이상의 행동을 할당하는 것. 수행되는 작업은 관련된 개체 또는 인수의 유형에 따라 다릅니다.
Instance variable − 메서드 내에서 정의되고 클래스의 현재 인스턴스에만 속하는 변수.
Inheritance − 클래스의 특성을 파생 된 다른 클래스로 이전하는 것.
Instance− 특정 클래스의 개별 개체. 예를 들어 Circle 클래스에 속하는 객체 obj는 Circle 클래스의 인스턴스입니다.
Instantiation − 클래스의 인스턴스 생성.
Method − 클래스 정의에 정의 된 특별한 종류의 함수.
Object− 해당 클래스에 의해 정의 된 데이터 구조의 고유 한 인스턴스. 객체는 데이터 멤버 (클래스 변수 및 인스턴스 변수)와 메서드로 구성됩니다.
Operator overloading − 특정 연산자에 하나 이상의 기능 할당.
클래스 생성
클래스 문은 새로운 클래스 정의를 작성합니다. 클래스의 이름은 다음과 같이 키워드 class 다음에 콜론이 뒤 따릅니다.
class ClassName:
'Optional class documentation string'
class_suite
클래스에는 ClassName .__ doc__ 를 통해 액세스 할 수있는 문서 문자열이 있습니다 .
class_suite는 클래스 멤버, 데이터 속성과 기능을 정의하는 모든 구성 요소 문장들로 구성되어 있습니다.
예
다음은 간단한 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
가변 empCount는 그 값이 클래스의 인스턴스들 사이에서 공유되는 클래스 변수이다. 이는 클래스 내부 또는 클래스 외부에서 Employee.empCount 로 액세스 할 수 있습니다 .
첫 번째 메서드 __init __ () 는이 클래스의 새 인스턴스를 만들 때 Python이 호출하는 클래스 생성자 또는 초기화 메서드라고하는 특수 메서드입니다.
각 메서드의 첫 번째 인수가 self 인 것을 제외하고 일반 함수와 같은 다른 클래스 메서드를 선언 합니다. Python 은 목록에 self 인수를 추가합니다 . 메서드를 호출 할 때 포함 할 필요가 없습니다.
인스턴스 개체 만들기
클래스의 인스턴스를 만들려면 클래스 이름을 사용하여 클래스를 호출하고 __init__ 메서드가 허용 하는 인수를 전달 합니다.
"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
이제 모든 개념을 종합하여
#!/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 # Add an 'age' attribute.
emp1.age = 8 # Modify 'age' attribute.
del emp1.age # Delete 'age' attribute.
일반 문을 사용하여 속성에 액세스하는 대신 다음 함수를 사용할 수 있습니다.
그만큼 getattr(obj, name[, default]) − 객체의 속성에 액세스합니다.
그만큼 hasattr(obj,name) − 속성이 존재하는지 여부를 확인합니다.
그만큼 setattr(obj,name,value)− 속성을 설정합니다. 속성이 없으면 생성됩니다.
그만큼 delattr(obj, name) − 속성을 삭제합니다.
hasattr(emp1, 'age') # Returns true if 'age' attribute exists
getattr(emp1, 'age') # Returns value of 'age' attribute
setattr(emp1, 'age', 8) # Set attribute 'age' at 8
delattr(empl, 'age') # Delete attribute 'age'
내장 클래스 속성
모든 Python 클래스는 다음과 같은 내장 속성을 유지하며 다른 속성과 마찬가지로 도트 연산자를 사용하여 액세스 할 수 있습니다.
__dict__ − 클래스의 네임 스페이스를 포함하는 사전.
__doc__ − 정의되지 않은 경우 클래스 문서 문자열 또는 없음.
__name__ − 클래스 이름.
__module__− 클래스가 정의 된 모듈 이름. 이 속성은 대화식 모드에서 "__main__"입니다.
__bases__ − 기본 클래스 목록에서 발생하는 순서대로 기본 클래스를 포함하는 빈 튜플.
위 클래스의 경우 이러한 모든 속성에 액세스 해 보겠습니다.
#!/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':
<function displayCount at 0xb7c84994>, 'empCount': 2,
'displayEmployee': <function displayEmployee at 0xb7c8441c>,
'__doc__': 'Common base class for all employees',
'__init__': <function __init__ at 0xb7c846bc>}
개체 삭제 (가비지 컬렉션)
Python은 불필요한 객체 (내장 유형 또는 클래스 인스턴스)를 자동으로 삭제하여 메모리 공간을 확보합니다. 파이썬이 더 이상 사용되지 않는 메모리 블록을 주기적으로 회수하는 프로세스를 가비지 수집이라고합니다.
Python의 가비지 수집기는 프로그램 실행 중에 실행되며 객체의 참조 수가 0에 도달하면 트리거됩니다. 객체를 가리키는 별칭의 수가 변경되면 객체의 참조 수가 변경됩니다.
개체의 참조 횟수는 새 이름이 할당되거나 컨테이너 (목록, 튜플 또는 사전)에 배치 될 때 증가합니다. 객체의 참조 횟수는 del로 삭제 되거나 참조가 재 할당되거나 참조가 범위를 벗어나면 감소합니다. 객체의 참조 횟수가 0이되면 Python은 자동으로이를 수집합니다.
a = 40 # Create object <40>
b = a # Increase ref. count of <40>
c = [b] # Increase ref. count of <40>
del a # Decrease ref. count of <40>
b = 100 # Decrease ref. count of <40>
c[0] = -1 # Decrease ref. count of <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) # prints the ids of the obejcts
del pt1
del pt2
del pt3
위의 코드가 실행되면 다음과 같은 결과가 생성됩니다.
3083401324 3083401324 3083401324
Point destroyed
Note− 이상적으로는 별도의 파일에 클래스를 정의한 다음 import 문을 사용하여 주 프로그램 파일로 가져와야 합니다.
클래스 상속
처음부터 시작하는 대신 새 클래스 이름 뒤에 괄호 안에 부모 클래스를 나열하여 기존 클래스에서 파생하여 클래스를 만들 수 있습니다.
자식 클래스는 부모 클래스의 속성을 상속하며 이러한 속성을 자식 클래스에 정의 된 것처럼 사용할 수 있습니다. 자식 클래스는 부모의 데이터 멤버와 메서드를 재정의 할 수도 있습니다.
통사론
파생 클래스는 부모 클래스와 매우 유사하게 선언됩니다. 그러나 상속 할 기본 클래스 목록은 클래스 이름 다음에 제공됩니다.
class SubClassName (ParentClass1[, ParentClass2, ...]):
'Optional class documentation string'
class_suite
예
#!/usr/bin/python
class Parent: # define parent class
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): # define child class
def __init__(self):
print "Calling child constructor"
def childMethod(self):
print 'Calling child method'
c = Child() # instance of child
c.childMethod() # child calls its method
c.parentMethod() # calls parent's method
c.setAttr(200) # again call parent's method
c.getAttr() # again call parent's method
위의 코드가 실행되면 다음과 같은 결과가 생성됩니다.
Calling child constructor
Calling child method
Calling parent method
Parent attribute : 200
비슷한 방법으로 다음과 같이 여러 부모 클래스에서 클래스를 구동 할 수 있습니다.
class A: # define your class A
.....
class B: # define your class B
.....
class C(A, B): # subclass of A and B
.....
issubclass () 또는 isinstance () 함수를 사용하여 두 클래스와 인스턴스의 관계를 확인할 수 있습니다.
그만큼 issubclass(sub, sup) 부울 함수는 주어진 서브 클래스가 sub 실제로 슈퍼 클래스의 하위 클래스입니다. sup.
그만큼 isinstance(obj, Class)부울 함수는 obj 가 Class 클래스 의 인스턴스이거나 Class 의 하위 클래스 인스턴스 인 경우 true를 반환합니다.
메서드 재정의
언제든지 부모 클래스 메서드를 재정의 할 수 있습니다. 부모의 메서드를 재정의하는 한 가지 이유는 하위 클래스에서 특수하거나 다른 기능을 원할 수 있기 때문입니다.
예
#!/usr/bin/python
class Parent: # define parent class
def myMethod(self):
print 'Calling parent method'
class Child(Parent): # define child class
def myMethod(self):
print 'Calling child method'
c = Child() # instance of child
c.myMethod() # child calls overridden method
위의 코드가 실행되면 다음과 같은 결과가 생성됩니다.
Calling child method
기본 오버로딩 방법
다음 표는 자신의 클래스에서 재정의 할 수있는 몇 가지 일반적인 기능을 나열합니다.
Sr. 아니. | 방법, 설명 및 샘플 호출 |
---|---|
1 | __init__ ( self [,args...] ) 생성자 (선택적 인수 포함) 샘플 호출 : obj = className (args) |
2 | __del__( self ) 소멸자, 개체 삭제 샘플 호출 : del obj |
삼 | __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 <module>
print counter.__secretCount
AttributeError: JustCounter instance has no attribute '__secretCount'
Python은 클래스 이름을 포함하도록 이름을 내부적으로 변경하여 해당 멤버를 보호합니다. object._className__attrName 과 같은 속성에 액세스 할 수 있습니다 . 마지막 줄을 다음과 같이 바꾸면 작동합니다.
.........................
print counter._JustCounter__secretCount
위의 코드가 실행되면 다음과 같은 결과가 생성됩니다.
1
2
2