dev/Python

[Python]클래스

mingracle 2022. 1. 23. 01:44

객체

  : 객체마다 고유한 성격을 가진다.

    동일 클래스로 만든 객체들은 서로 전혀 영향을 주지 않는다.

인스턴스: 특정 객체가 어떤 클래스의 객체인지 관계 위주로 설명할 때 사용

class Cookie:
	pass #기능 없음
    
a = Cookie() # Cookie()의 결괏값을 돌려받는 객체 a, b
b = Cookie() # a, b는 Cookie의 인스턴스

 

메서드

  : 클래스 안에 구현된 함수.

def 함수명(매개변수):
    수행문
    ...

※ 메서드를 호출한 객체가 매개변수 self에 자동으로 전달된다.

   (객체를 호출할 때 호출한 객체 자신이 전달되기 때문에 self를 사용)

class FourCal:
	def setdata(self, first, second):
    	self.first = first  # a.first = 4 (a객체에 객체변수 first생성. 값 4 저장)
        self.second = second  # a.second = 2 (a객체에 객체변수 second생성. 값 2 저장)
        
# 메서드 호출방법1: 객체.메서드 => self를 반드시 생략해서 호출해야한다.
b = FourCal()
a = FourCal()

a.setdata(4, 2)
b.setdata(3, 7)

# 각 객체의 객체변수는 다른 객체의 객체변수와 상관없이 독립적인 값을 유지한다. 주소값이 다름
print(a.first)  # a의 객체변수 first의 값 4 
print(b.first)  # b의 객체변수 first의 값 3


# 메서드 호출방법2: 클래스명.메서드 => 객체 a를 첫번째 매개변수인 self에 반드시 전달해야한다.(잘 사용X)
# a = FourCal()
# FourCal.setdata(a, 4, 2)

 

- 클래스에 더하기/곱하기/빼기/나누기 기능 만들기

class FourCal:
    def setdata(self, first, second):
        self.first = first
        self.second = second
    def add(self):
        result = self.first + self.second
        return result
    def mul(self):
        result = self.first * self.second
        return result
    def sub(self):
        result = self.first - self.second
        return result
    def div(self):
        result = self.first / self.second
        return result
a = FourCal()
a.setdata(4, 2)
#객체 a에 의해 add메서드가 수행되면 add메서드의 self에는 객체a가 자동으로 입력된다.
print(a.add())  # 6 출력
print(a.mul())  # 8 출력
print(a.sub())  # 2 출력
print(a.div())  # 2 출력

b = FourCal()
b.setdata(3, 8)
print(b.add())  # 11 출력
print(b.mul())  # 24 출력
print(b.sub())  # -5 출력
print(b.div())  # 0.375 출력

위 처럼 초깃값을 설정해야하는 경우 메서드(setdata)를 호출해 초깃값을 설정하기보다 생성자를 구현하는 것이 안전

 

- 생성자

  : 객체가 생성될 때 자동으로 호출되는 메서드.

    파이썬 메서드 이름으로 __init__을 사용하면 해당 메서드는 생성자가 된다. 객체가 생성되는 시점에 자동으로 호출

# setdata 메서드와 이름만 다르고 모든게 동일하다.
# __init__은 생성자로 인식되어 객체가 생성되는 시점에 자동으로 호출되는 차이가 있다.

class FourCal:
	def __init__(self, first, second):
		self.first = first
   		self.second = second
    
# a = FourCal()  # __init__이 호출되어 오류 발생. first, second에 해당하는 값이 전달되지 않았기 때문
a = FourCal(4, 2) # 값을 넣어 전달해 객체를 생성해야 한다.

print(a.first) # 4 출력
print(a.second) # 2 출력

 

- 클래스의 상속

  : 기존 클래스를 변경하지 않고 기능을 추가하거나 기존기능을 변경할 때 사용한다.

   (기존클래스가 라이브러리 형태로 제공되거나 수정이 허용되지 않은 상황에 사용)

class 클래스명(상속할 클래스명)
class MoreFourCal(FourCal): #MoreFourCal은 FourCal을 상속했으므로 FourCal클래스의 모든 기능을 사용할 수 있다.
	def pow(self):
    	result = self.first ** self.second
        return result

a = MoreFourCal(4, 2)
a.add()  #6
a.mul()  #8
a.sub()  #2
a.div()  #2
a.pow()  #16 #기능 확장에 상속을 사용

 

- 메서드 오버라이딩

  : 부모 클래스에 있는 메서드를 동일한 이름으로 다시 만드는 것.

# 나누는 값이 0이면 error가 발생한다.(ZeroDivisionError) 
# FourCal에 있는 div메서드를 동일한 이름으로 다시 작성 = 메서드 오버라이딩

class SafeFourCal(FourCal):
	def div(self):
    	if self.second == 0:  #나누는 값이 0이면 숫자 0을 돌려주도록 수정
        	return 0
        else:
        	return self.first / self.second

a = SafeFourCal(4, 0)
a.div()  #0 출력

 

- 클래스 변수

  : 객체변수는 다른 객체들에 영향을 받지 않고 그 값을 유지한다. 클래스변수는 객체변수와 성격이 다르다.

   클래스 변수는 클래스로 만든 모든 객체에 공유된다. (id함수를 사용해 모두 같은 값을 가지고있음을 확인)

class Family:
	lastname = "김"
    
print(Family.lastname) # 김 출력
a = Family()
b = Family()
print(a.lastname) # 김 출력
print(b.lastname) # 김 출력

# 클래스 변수 값을 변경하면 클래스로 만든 모든 객체의 lastname값도 변경된다.
# 김 -> 박으로 변경시키면 모두 박으로 변경된다.
Family.lastname = "박"
print(a.lastname) # 박 출력
print(b.lastname) # 박 출력

 

- 정적 메서드 @sataticmethod

  : 객체생성 없이(인스턴스 없이) 호출 가능

#@: 데코레이션

class A:
    @staticmethod  #정적 메서드: 매개변수에 self를 지정하지 않는다.
    def add(a, b):
        print(a+b)

    @staticmethod 
    def minus(a,b):
        print(a-b)

A.add(3, 5) #정적메서드이기 때문에 객체생성 없이 클래스로부터 함수에 바로 접근함
  # 8 출력
A.minus(5, 3)
  # 2 출력

 

- 클래스 메서드 @classmethod

: 정적메서드처럼 인스턴스 없이 호출이 가능하다.

  단, 클래스 메서드는 메서드 안에서 클래스 속성, 클래스 메서드에 접근해야 할 때 사용한다.

class Person:
    cnt = 0
    def __init__(self): #init함수: 인스턴스가 만들어질 때 호출되는 부분.
        Person.cnt += 1 # 클래스 속성 cnt에 1을 더한다

    @classmethod
    def pr(cls): #cls: class의 줄임말. 현재클래스 Person이 들어온다.
        print(cls.cnt) #cls로 클래스 속성에 접근해 cnt가 출력된다.

a = Person()
b = Person()
Person.pr()
a.pr()

 

- 예제

class Person:
    def __init__(self, *args):
        self.name = args[0]
        self.age = args[1]
        self.addr = args[2]
    def hi(self):
        print("{0}".format(self.name))

m = Person(*['ming', 11, '서울'])
m.hi() # ming 출력

- 예제

  __변수명: 해당 변수를 비공개메서드로 만들어준다.(클래스 안의 메서드에서만 접근할 수 있음)

class Stu:
    def __init__(self,name,age,adr,diary):
        self.hello="hi"
        self.name=name #클래스 바깥에서도 접근이 가능하다.(인스턴스.속성)
        self.age=age
        self.adr=adr
        self.__diary = diary #변수 앞에 __를 붙여 비공개 속성으로 만들어짐
        #클래스 안에서만 사용할 수 있는 비공개 속성: __속성
    def pr(self, price):
        self.__diary += price #비공개 속성은 클래스 안에 있는 메서드에서만 접근 가능
        print(self.__diary)
a = Stu('희망', 9, '서울', 30000)
print(a.name)
#a.__diary += 30000 #클래스 밖에서 비공개 속성에 접근하면 error
a.pr(3000) 
  # 33000 출력