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 자신의 클래스에서 함수를 재정의할 수 있습니다.

< td>3
일련 번호 방법, 설명 및 간단한 호출
1
序号方法, 描述 & 简单的调用
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)
__init__ ( self [,args...] )<🎜>< br />생성자
간단한 호출 방법: 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