Python은 처음부터 객체지향 언어였기 때문에 Python에서는 클래스와 객체를 쉽게 만들 수 있습니다. 이번 장에서는 Python의 객체지향 프로그래밍을 자세히 소개하겠습니다.
이전에 객체지향 프로그래밍 언어를 접해본 적이 없다면 먼저 객체지향 언어의 몇 가지 기본 기능을 이해하고 기본적인 객체지향 개념을 머릿속에 형성해야 할 수도 있습니다. 이는 Python에서 객체 지향 프로그래밍을 쉽게 배우는 데 도움이 될 것입니다.
다음으로 객체지향의 몇 가지 기본 특성에 대해 간략하게 알아보겠습니다.
객체지향 기술 소개
클래스: 동일한 속성과 메서드를 가진 객체의 집합을 설명하는 데 사용됩니다. 컬렉션의 모든 개체에 공통적인 속성과 메서드를 정의합니다. 객체는 클래스의 인스턴스입니다.
클래스 변수: 클래스 변수는 인스턴스화된 객체 전체에서 공개됩니다. 클래스 변수는 클래스 내부와 함수 본문 외부에 정의됩니다. 클래스 변수는 일반적으로 인스턴스 변수로 사용되지 않습니다.
데이터 멤버: 클래스 변수 또는 인스턴스 변수는 클래스 및 해당 인스턴스 객체와 관련된 데이터를 처리하는 데 사용됩니다.
메서드 오버로드: 부모 클래스에서 상속된 메서드가 하위 클래스의 요구 사항을 충족할 수 없는 경우 이 프로세스를 메서드 재정의라고 하며, 메서드 오버로딩이라고도 합니다.
인스턴스 변수: 메소드에 정의된 변수는 현재 인스턴스의 클래스에만 작용합니다.
상속: 즉, 파생 클래스는 기본 클래스의 필드와 메서드를 상속합니다. 상속을 사용하면 파생 클래스의 개체를 기본 클래스 개체로 처리할 수도 있습니다. 예를 들어, 다음과 같은 디자인이 있습니다. Dog 유형의 개체는 "is-a" 관계(예: Dog is an Animal)를 시뮬레이션하는 Animal 클래스에서 파생됩니다.
인스턴스화: 클래스의 특정 개체인 클래스의 인스턴스를 만듭니다.
메서드: 클래스에 정의된 함수입니다.
객체: 클래스에 의해 정의된 데이터 구조의 인스턴스입니다. 개체에는 두 개의 데이터 멤버(클래스 변수 및 인스턴스 변수)와 메서드가 포함됩니다.
클래스 만들기
class 문을 사용하여 새 클래스를 만듭니다. 다음 예와 같이 class 뒤에는 클래스 이름이 있고 콜론으로 끝납니다.
class ClassName:
'Optional class document string'#Class document string
class_suite #Class body
수업의 도움말 정보는 ClassName.__doc__를 통해 보실 수 있습니다.
class_suite는 클래스 멤버, 메소드, 데이터 속성으로 구성됩니다.
예
다음은 간단한 Python 클래스 예입니다.
class Employee:
' 모든 직원의 공통 기본 클래스
empCount = 0
def __init__(self, name, 급여):
self.name = name
self.salary = 급여
Employee.empCount += 1
def displayCount(self):
print "총 직원 %d" % Employee.empCount
def displayEmployee(self):
print "Name : ", self.name, ", Salary: ", self.salary
empCount 변수는 클래스 변수이며 해당 값은 이 클래스의 모든 인스턴스에서 공유됩니다. 내부 클래스나 외부 클래스에서 Employee.empCount를 사용하여 액세스할 수 있습니다.
첫 번째 메소드인 __init__() 메소드는 클래스의 생성자 또는 초기화 메소드라고 하는 특수 메소드입니다. 이 메소드는 이 클래스의 인스턴스가 생성될 때 호출됩니다.
인스턴스 객체 생성
클래스의 인스턴스를 생성하려면 클래스 이름을 사용하고 __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:
'모든 직원을 위한 공통 기본 클래스'
empCount = 0
def __init__(self, 이름, 급여):
self.name = 이름
self.salary = 급여
Employee.empCount += 1
def displayCount(self):
print "총 직원 %d" % Employee.empCount
def displayEmployee(self):
print "이름 : ", self.name, ", Salary: ", self.salary
"이것은 Employee 클래스의 첫 번째 객체를 생성합니다."
emp1 = Employee("Zara", 2000)
"이것은 Employee 클래스의 두 번째 객체를 생성합니다."
emp2 = Employee("Manni", 5000)
emp1.displayEmployee()
emp2.displayEmployee()
print "Total Employee %d" % Employee.empCount
위 코드를 실행한 결과는 다음과 같습니다.
이름 : 자라 ,월급: 2000
이름 : Manni ,월급: 5000
총 직원 2
다음과 같이 클래스의 속성을 추가, 삭제, 수정할 수 있습니다.
emp1.age = 7 # 'age' 속성 추가
emp1.age = 8 # 'age' 속성 수정
del emp1.age # 'age' 속성 삭제
다음 함수를 사용하여 속성에 액세스할 수도 있습니다.
getattr(obj, name[, default]): 객체의 속성에 액세스합니다.
hasattr(obj,name) : 속성이 존재하는지 확인합니다.
setattr(obj,name,value): 속성을 설정합니다. 속성이 없으면 새 속성이 생성됩니다.
delattr(obj, name): 속성을 삭제합니다.
hasattr(emp1, 'age') # 'age' 속성이 존재하면 True를 반환합니다.
getattr(emp1, 'age') # 'age' 속성 값을 반환합니다.
setattr(emp1, 'age', 8) # 'age' 속성에 값을 추가합니다. / 8
delattr(empl, 'age') #'age' 속성 삭제
Python 내장 클래스 속성
__dict__: 클래스 속성(클래스의 데이터 속성으로 구성된 사전 포함)
__doc__: 클래스의 문서 문자열
__name__: 클래스 이름
__module__: 클래스가 정의된 모듈(클래스 전체 이름은 '__main__.className'입니다. 클래스가 가져온 모듈 mymod에 있는 경우 className.__module__은 mymod와 동일합니다)
__bases__: 클래스의 모든 상위 클래스 요소(모든 상위 클래스 포함)
Python 내장 클래스 속성 호출 예제로 구성된 튜플은 다음과 같습니다.
#!/usr/bin/python
class Employee:
'모든 직원을 위한 공통 기본 클래스'
empCount = 0
def __init__(self, 이름, 급여):
self.name = 이름
self.salary = 급여
직원 .empCount += 1
def displayCount(self):
print "총 직원 %d" % Employee.empCount
def displayEmployee(self):
print " Name : ", self.name, ", Salary: ", self.salary
print "Employee.__doc__ :", Employee.__doc__
인쇄 "Employee.__name__:", Employee.__name__
인쇄 "Employee.__module__:", Employee.__module__
인쇄 "Employee. __bases__:", Employee.__bases__
print "Employee .__dict__:", Employee.__dict__
위 코드를 실행한 출력 결과
Employee.__doc__: 모든 직원을 위한 공통 기본 클래스
Employee.__name__: Employee
Employee .__module__: __main__
Employee.__bases__: ()
Employee.__dict__: {'__module__': '__main__', 'displayCount':
'displayEmployee': < 0xb7c8441c의 함수 displayEmployee>,
'__doc__': '모든 직원을 위한 공통 기본 클래스',
'__init__':
Python 객체 파괴(가비지 수집)
Java 언어와 마찬가지로, Python은 참조 계산이라는 간단한 기술을 사용하여 메모리의 개체를 추적합니다.
내부적으로 Python은 사용 중인 각 개체의 참조 수를 기록합니다.
참조 카운터라고 하는 내부 추적 변수입니다.
객체가 생성되면 참조 횟수가 생성됩니다. 객체가 더 이상 필요하지 않을 때, 즉 객체의 참조 횟수가 0이 되면 가비지 수집됩니다. 그러나 재활용은 "즉시" 이루어지지 않습니다. 인터프리터는 적절한 시간에 가비지 개체가 차지하는 메모리 공간을 재활용합니다.
a = 40 # 객체 생성 <40>
b = a # 참조 증가, 개수 <40>
c = [b] # 참조 개수를 늘립니다.
del a # 참조 개수를 줄입니다.
b = 100 # 참조 <40> 개수 줄이기
c[0] = -1 # 참조 개수 줄이기 <40>
가비지 재활용 메커니즘은 참조 횟수가 0인 객체를 대상으로 할 뿐만 아니라 순환 참조도 처리할 수 있습니다. 순환 참조는 두 개체가 서로를 참조하지만 다른 변수는 이를 참조하지 않을 때 발생합니다. 이 경우 참조 카운팅만으로는 충분하지 않습니다. Python의 가비지 수집기는 실제로 참조 카운터이자 순환 가비지 수집기입니다. 참조 계산 외에도 가비지 수집기는 대량으로 할당된 개체(및 참조 계산으로 파괴되지 않은 개체)도 살펴봅니다. 이 경우 인터프리터는 일시 중지하고 참조되지 않은 루프를 정리하려고 시도합니다.
인스턴스
객체가 사라지면 소멸자 __del__, __del__이 호출됩니다. 객체가 더 이상 사용되지 않으면 __del__ 메서드가 실행됩니다.
#!/usr/bin/python
클래스 포인트:
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
인쇄 ID (pt1), id(pt2), id(pt3) # 객체의 id를 출력
del pt1
del pt2
del pt3
포인트 파괴 참고: 일반적으로 별도의 파일에 클래스를 정의해야 합니다. , 클래스 상속객체 지향 프로그래밍이 가져오는 주요 이점 중 하나는 코드 재사용이며, 이러한 재사용을 달성하는 방법 중 하나는 상속 메커니즘을 이용하는 것입니다. 상속은 클래스 간의 유형 및 하위 유형 관계로 완전히 이해될 수 있습니다. 참고 사항: 상속 구문 클래스 파생 클래스 이름(기본 클래스 이름): //... 기본 클래스 이름은 클래스 정의 시 튜플에 지정됩니다. 의. 파이썬 상속의 일부 기능: 1: 상속에서 기본 클래스(__init__() 메서드)의 구성은 자동으로 호출되지 않으며 파생 클래스를 개인적으로 호출합니다. 2: 기본 클래스의 메서드 호출 시 기본 클래스의 클래스 이름 접두어를 추가해야 하며, self 매개변수 변수를 가져와야 합니다. 클래스에서 일반 함수를 호출하는 것과 달리 self 매개변수를 가져올 필요가 없습니다. 3: Python은 항상 먼저 해당 유형의 메서드를 검색합니다. 파생 클래스에서 해당 메서드를 찾을 수 없으면, 기본 클래스에서 하나씩 검색을 시작합니다. (먼저 이 클래스에서 호출 메서드를 찾은 다음, 찾을 수 없으면 기본 클래스에서 찾아보세요.) 상속 튜플에 두 개 이상의 클래스가 나열되는 경우 이를 "다중 상속"이라고 합니다. 구문: 다음과 같이 클래스 이름 뒤에 상속된 기본 클래스 목록을 사용하여 상위 클래스와 유사한 파생 클래스 선언:
class SubClassName (ParentClass1[, ParentClass2, ...]): '선택적 클래스 문서 문자열' class_suite
인스턴스: #!/usr/bin/python 클래스 상위: # 상위 클래스 정의 parentAttr = 100 def __init__(self): 사용 사용 사용 사용 내내 통과 밖으로 통과 밖으로 통과 오프 ‐ ‐ ‐ ‐ ‐‐‐‐ 이동해야 하는 부모 행. 🎜> 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 "자식 생성자 호출"
def childMethod(self):
print 'Calling child method'
c = Child() # 하위 클래스 인스턴스화
c.childMethod() # 호출 하위 클래스 메소드
c.parentMethod() # 상위 클래스 메소드 호출
c.setAttr(200) # 상위 클래스 메소드 다시 호출
c.getAttr () # 상위 클래스의 메소드를 다시 호출
>자식 생성자 호출
자식 메소드 호출
상위 메소드 호출
상위 속성 : 200
여러 클래스에서 상속할 수 있습니다
클래스 A: # 클래스 A 정의
....
클래스 B: # 클래스 B 정의
.....
class C(A, B): # A와 B의 하위 클래스
....
issubclass() 또는 isinstance() 메소드를 사용하여 감지합니다.
issubclass() - 클래스가 하위 클래스인지 다른 클래스의 하위 클래스인지 확인하는 부울 함수, 구문: issubclass(sub,sup)
isinstance(obj, Class) obj인 경우 부울 함수 Class 클래스의 인스턴스 객체이거나 Class 하위 클래스의 인스턴스 객체인 경우 true를 반환합니다.
오버로드된 메서드
상위 클래스 메서드의 기능이 요구 사항을 충족할 수 없는 경우 하위 클래스에서 상위 클래스의 메서드를 오버로드할 수 있습니다.
예:
#!/usr/bin/python
클래스 상위: > def myMethod(self):
print 'Calling parent method'
class Child(Parent): # Define subclass
def myMethod( self):
print 'Calling child method'
c = Child() # 하위 클래스 인스턴스
c.myMethod() # 하위 클래스 오버로드된 메서드 호출
위 코드를 실행한 결과는 다음과 같습니다.
자식 메소드 호출
기본 오버로드된 메서드
다음 표에는 자신의 클래스에서 재정의할 수 있는 몇 가지 일반적인 함수가 나열되어 있습니다.
일련 번호
방법, 설명 및 단순 호출
1 __init__ ( self [,args...] )
생성자간단한 호출 방법: obj = className(args )
2 __del__(self)
소멸자 메서드, 객체 삭제간단한 호출 메서드: dell obj
3 __repr__( self )
는 다음 형식으로 변환됩니다. 읽을 인터프리터간단한 호출 방법: repr(obj)
4 __str__( self )
를 사용하여 값을 사람이 읽을 수 있는 형식으로 변환합니다.
간단한 호출 방법: str( obj)5 __cmp__ (self, x)
객체 비교
간단한 호출 방법: cmp(obj, x)연산자 오버로딩
Python도 지원합니다. 연산자 오버로딩의 예는 다음과 같습니다:
#!/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
Python은 클래스를 포함하도록 이름을 변경합니다. 이름 :
1
2
추적(가장 최근 호출 마지막):
파일 " test .py", 12행,
print counter.__secretCount
AttributeError: JustCounter 인스턴스에 '__secretCount' 속성이 없습니다
Python은 인스턴스화된 클래스가 숨겨진 데이터에 액세스하는 것을 허용하지 않지만 object._className__attrName을 사용하여 속성에 액세스할 수 있습니다. 위 코드의 마지막 줄을 다음 코드로 바꿉니다.
........................
카운터 인쇄._JustCounter__secretCount
위 코드를 실행해 보면 실행 결과는 다음과 같습니다.
1
2
2