Python 객체지향
Python은 처음부터 객체지향 언어였기 때문에 Python에서는 클래스와 객체를 쉽게 만들 수 있습니다. 이번 장에서는 Python의 객체지향 프로그래밍을 자세히 소개하겠습니다.
이전에 객체지향 프로그래밍 언어를 접해본 적이 없다면 먼저 객체지향 언어의 몇 가지 기본 기능을 이해하고 기본적인 객체지향 개념을 머릿속에 형성해야 할 수도 있습니다. 이는 Python에서 객체 지향 프로그래밍을 쉽게 배우는 데 도움이 될 것입니다.
다음으로 객체지향의 기본적인 특징을 간략하게 알아보겠습니다.
객체지향 기술 소개
클래스(Class): 는 동일한 속성과 메서드를 가진 객체의 집합을 설명하는 데 사용됩니다. 컬렉션의 모든 개체에 공통적인 속성과 메서드를 정의합니다. 객체는 클래스의 인스턴스입니다.
클래스 변수: 클래스 변수는 인스턴스화된 객체 전체에서 공통입니다. 클래스 변수는 클래스 내부와 함수 본문 외부에 정의됩니다. 클래스 변수는 일반적으로 인스턴스 변수로 사용되지 않습니다.
데이터 멤버: 클래스 변수 또는 인스턴스 변수는 클래스 및 해당 인스턴스 객체와 관련된 데이터를 처리하는 데 사용됩니다.
메서드 재작성: 상위 클래스에서 상속된 메소드가 하위 클래스의 요구 사항을 충족할 수 없는 경우 이를 재작성할 수 있습니다. , 메서드 재정의라고도 합니다.
인스턴스 변수: 메서드에 정의된 변수는 현재 인스턴스의 클래스에만 적용됩니다.
상속: 즉, 파생 클래스는 기본 클래스의 필드와 메서드를 상속합니다. 상속을 사용하면 파생 클래스의 개체를 기본 클래스 개체로 처리할 수도 있습니다. 예를 들어, 다음과 같은 디자인이 있습니다. Dog 유형의 개체는 "is-a" 관계를 시뮬레이션하는 Animal 클래스에서 파생됩니다(예: Dog is an Animal).
인스턴스화: 클래스의 특정 개체인 클래스의 인스턴스를 만듭니다.
메서드: 클래스에 정의된 함수입니다.
객체: 클래스에 의해 정의된 데이터 구조의 인스턴스입니다. 개체에는 두 개의 데이터 멤버(클래스 변수 및 인스턴스 변수)와 메서드가 포함됩니다.
클래스 만들기
class 문을 사용하여 새 클래스를 만들고, 그 뒤에 class가 클래스 이름이고 콜론으로 끝납니다. 다음 예에서는
class ClassName: '类的帮助信息' #类文档字符串 class_suite #类体
클래스의 도움말 정보를 ClassName.__doc__를 통해 볼 수 있습니다.
class_suite는 클래스 멤버, 메소드, 데이터 속성으로 구성됩니다.
인스턴스
다음은 간단한 Python 클래스 예입니다.
#!/usr/bin/python # -*- coding: UTF-8 -*- class Employee: '所有员工的基类' 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 변수는 클래스 변수이며 해당 값은 이 클래스에 있습니다. Shared 모든 인스턴스 사이. 내부 클래스나 외부 클래스에서 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 # -*- coding: UTF-8 -*- class Employee: '所有员工的基类' 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 "创建 Employee 类的第一个对象" emp1 = Employee("Zara", 2000) "创建 Employee 类的第二个对象" 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' 属性
다음 함수를 사용하여 속성에 액세스할 수도 있습니다.
getattr(obj, name[ , 기본값]): 객체의 속성에 액세스합니다.
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__: 클래스의 모든 상위 클래스 구성 요소(모든 상위 클래스로 구성된 튜플 포함)
파이썬의 내장 클래스 속성을 호출하는 예는 다음과 같습니다.
#!/usr/bin/python # -*- coding: UTF-8 -*- class Employee: '所有员工的基类' 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__: 所有员工的基类 Employee.__name__: Employee Employee.__module__: __main__ Employee.__bases__: () Employee.__dict__: {'__module__': '__main__', 'displayCount': <function displayCount at 0x10a939c80>, 'empCount': 0, 'displayEmployee': <function displayEmployee at 0x10a93caa0>, '__doc__': '\xe6\x89\x80\xe6\x9c\x89\xe5\x91\x98\xe5\xb7\xa5\xe7\x9a\x84\xe5\x9f\xba\xe7\xb1\xbb', '__init__': <function __init__ at 0x10a939578>}
python 객체 파괴(가비지 컬렉션)
Java 언어와 마찬가지로 Python도 참조 계산이라는 간단한 기술을 사용하여 메모리의 개체를 추적합니다.
내부적으로 Python은 사용 중인 각 개체의 참조 수를 기록합니다.참조 카운터라고 하는 내부 추적 변수입니다.
객체가 생성되면 해당 객체가 더 이상 필요하지 않을 때 참조 카운트가 생성됩니다. 즉, 이 객체의 참조 횟수가 0이 되면 가비지 수집됩니다. 그러나 재활용은 "즉시" 이루어지지 않습니다. 인터프리터는 적절한 시간에 가비지 객체가 차지하는 메모리 공간을 재활용합니다.
a = 40 # 创建对象 <40> b = a # 增加引用, <40> 的计数 c = [b] # 增加引用. <40> 的计数 del a # 减少引用 <40> 的计数 b = 100 # 减少引用 <40> 的计数 c[0] = -1 # 减少引用 <40> 的计数
가비지 수집 메커니즘은 참조 횟수가 0인 객체를 대상으로 할 뿐만 아니라 순환 참조도 처리할 수 있습니다. 순환 참조는 두 개체가 서로를 참조하지만 다른 변수는 이를 참조하지 않을 때 발생합니다. 이 경우 참조 카운팅만으로는 충분하지 않습니다. Python의 가비지 수집기는 실제로 참조 카운터이자 순환 가비지 수집기입니다. 참조 계산 외에도 가비지 수집기는 대량으로 할당된 개체(및 참조 계산으로 파괴되지 않은 개체)도 살펴봅니다. 이 경우 인터프리터는 일시 중지하고 참조되지 않은 루프를 정리하려고 시도합니다.
Instance
객체가 소멸되면 소멸자 __del__, __del__이 호출됩니다. 객체가 더 이상 사용되지 않으면 __del__ 메서드가 실행됩니다. 위의
#!/usr/bin/python # -*- coding: UTF-8 -*- 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, "销毁" pt1 = Point() pt2 = pt1 pt3 = pt1 print id(pt1), id(pt2), id(pt3) # 打印对象的id del pt1 del pt2 del pt3
실행 결과입니다. 예는 다음과 같습니다.
3083401324 3083401324 3083401324 Point 销毁
참고: 일반적으로 별도의 파일에 클래스를 정의해야 합니다.
클래스 상속
객체- 프로그래밍이 가져오는 주요 이점 중 하나는 코드 재사용이며, 이러한 재사용을 달성하는 방법 중 하나는 상속 메커니즘을 이용하는 것입니다. 상속은 클래스 간의 유형 및 하위 유형 관계로 완전히 이해될 수 있습니다.
주의사항: 상속 구문 class 파생 클래스 이름(기본 클래스 이름): //... 기본 클래스 이름은 괄호 안에 표시되며, 기본 클래스는 클래스 정의 시 튜플에 지정됩니다.
파이썬 상속의 일부 기능:
1: 상속에서 기본 클래스(__init__() 메서드)의 구성은 자동으로 호출되지 않습니다. 파생 클래스의 생성자에서 구체적으로 호출하세요.
2: 기본 클래스의 메서드 호출 시 기본 클래스의 클래스 이름 접두어를 추가해야 하며, self 매개변수 변수를 가져와야 합니다. 클래스에서 일반 함수를 호출하는 것과 달리 self 매개변수를 가져올 필요가 없습니다.
3: Python은 해당 유형의 메소드를 찾을 수 없는 경우 항상 먼저 해당 유형의 메소드를 검색합니다. 파생 클래스 메서드의 메서드를 사용하면 기본 클래스에서 하나씩 검색을 시작합니다. (먼저 이 클래스에서 호출 메서드를 찾은 다음, 찾을 수 없으면 기본 클래스에서 찾아보세요.)
상속 튜플에 두 개 이상의 클래스가 나열되는 경우 이를 "다중 상속"이라고 합니다.
구문:
다음과 같이 클래스 이름 뒤에 상속된 기본 클래스 목록이 있는 상위 클래스와 유사한 파생 클래스 선언:
class SubClassName (ParentClass1[, ParentClass2, ...]): 'Optional class documentation string' class_suite
인스턴스:
#!/usr/bin/python # -*- coding: UTF-8 -*- class Parent: # 定义父类 parentAttr = 100 def __init__(self): print "调用父类构造函数" def parentMethod(self): print '调用父类方法' def setAttr(self, attr): Parent.parentAttr = attr def getAttr(self): print "父类属性 :", Parent.parentAttr class Child(Parent): # 定义子类 def __init__(self): print "调用子类构造方法" def childMethod(self): print '调用子类方法 child method' c = Child() # 实例化子类 c.childMethod() # 调用子类的方法 c.parentMethod() # 调用父类方法 c.setAttr(200) # 再次调用父类的方法 c.getAttr() # 再次调用父类的方法
위 코드 실행 결과는 다음과 같습니다.
调用子类构造方法 调用子类方法 child method 调用父类方法 父类属性 : 200
여러 클래스를 상속할 수 있습니다
class A: # 定义类 A ..... class B: # 定义类 B ..... class C(A, B): # 继承类 A 和 B .....
issubclass() 또는 isinstance( ) 테스트 방법.
issubclass() - 클래스가 하위 클래스인지 다른 클래스의 하위 클래스인지 확인하는 부울 함수, 구문: issubclass(sub,sup)
isinstance(obj, Class) 부울 함수는 obj가 Class 클래스의 인스턴스 객체이거나 Class 하위 클래스의 인스턴스 객체인 경우 true를 반환합니다.
메서드 재작성
부모 클래스 메서드의 기능이 요구 사항을 충족할 수 없는 경우 하위 클래스에서 부모 클래스의 메서드를 재정의할 수 있습니다.
예:
#!/usr/bin/python # -*- coding: UTF-8 -*- class Parent: # 定义父类 def myMethod(self): print '调用父类方法' class Child(Parent): # 定义子类 def myMethod(self): print '调用子类方法' c = Child() # 子类实例 c.myMethod() # 子类调用重写方法
위 코드를 실행했을 때의 출력 결과는 다음과 같습니다.
调用子类方法
기본 오버로드 방법
아래 표는 일부를 나열한 것입니다. common 자신의 클래스에서 함수를 재정의할 수 있습니다.
일련 번호 | 방법, 설명 및 간단한 호출 | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 |
간단한 호출 방법: obj = className(args) | ||||||||||||
2 | < 🎜>__del__ ( self )<🎜> 소멸자 메서드, 객체 삭제 간단한 호출 메서드: dell obj | ||||||||||||
<🎜>__repr__( self )<🎜> 인터프리터가 읽은 형식으로 변환 간단한 호출 방법: repr(obj) | |||||||||||||
4 | <🎜>__str__( self )<🎜> 값을 사람이 읽을 수 있는 Form으로 변환하는 데 사용 간단한 호출 방법 : 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)
클래스 속성
__private_attrs메서드와 클래스의 비공개 속성: 두 개의 밑줄로 시작하고 속성이 비공개이므로 사용하거나 직접 액세스할 수 없음을 선언합니다. 수업 밖에서. self.__private_attrs 클래스 내부의 메서드에서 사용되는 경우.
클래스 메소드
클래스 내에서 def 키워드를 사용하여 클래스에 대한 메소드를 정의할 수 있습니다. 일반 함수 정의와 달리 클래스 메소드에는 self 매개변수가 포함되어야 합니다. 첫 번째 매개변수
클래스의 프라이빗 메서드
__private_method: 두 개의 밑줄로 시작하는 메서드는 프라이빗 메서드로 선언되며 클래스 외부에서 호출할 수 없습니다. 클래스 이름을 포함하도록 이름을 변경하여 클래스 내부에서 self.__private_methods
instance
#!/usr/bin/python # -*- coding: UTF-8 -*- class JustCounter: __secretCount = 0 # 私有变量 publicCount = 0 # 公开变量 def count(self): self.__secretCount += 1 self.publicCount += 1 print self.__secretCount counter = JustCounter() counter.count() counter.count() print counter.publicCount print counter.__secretCount # 报错,实例不能访问私有变量
Python 호출:
1 2 2 Traceback (most recent call last): File "test.py", line 17, in <module> print counter.__secretCount # 报错,实例不能访问私有变量 AttributeError: JustCounter instance has no attribute '__secretCount'
Python은 인스턴스화를 허용하지 않습니다. 클래스는 개인 데이터에 액세스하지만 object._className__attrName을 사용하여 속성에 액세스할 수 있습니다. 위 코드의 마지막 줄을 다음 코드로 바꾸세요.
......................... print counter._JustCounter__secretCount
위 코드를 실행하고 다음을 실행하세요. 결과는 다음과 같습니다:
1 2 2 2