python/기초

[파이썬 기초] Class / 함수 (args,kwargs)

끼발자 2021. 10. 13. 14:06
반응형

모든 언어에서 클래스 객체 생성과 함수선언은

매우매우매우 중요하다.

 

여러분이 클래스를 얼마나 이해하고 있는지는 잘 모르겠으나,

간략하게 소개하고 지나간다.

다 알고 있다면 아래로 내려 본문으로 이동하자.

Class

class <클래스명> 으로 선언이 가능하다.

처음 클래스에 대한 설명을 들었을 때, 

보통 붕어빵으로 예시를 많이 하는데, 그땐 잘 이해가 안갔다.

 

근데 그만큼 확실한 예시도 없는 것 같다.

혹시 메이플스토리나 기타 RPG게임을 해 본적이 있다면 그걸 예시로 들어보자.

 

 

클래스는 함수와 마찬가지로 그 자체로는 아무런 기능이 없다.

유명한 시 구절에도 있지않은가.

 

내가 그의 이름을 불러주었을 때 그는 나에게로 와서 꽃이 되었다.

 

부르기 전까진 아무것도 하지 않는다.

저작권이 무서워 직접 그렸다

 

 

모자

 

상의    무기

 

하의

 

신발

 

 

대충 이렇게 장비창이 열려있고, 모든 장비를 착용하지 않으면 하나의 유저라고 생각하지 않는다.

즉, 클래스에서 정의한 틀에는 모자, 상의, 하의, 신발, 무기가 속성으로 있고, 이 속성을 모두 채워줘야

하나의 캐릭터가 생성된다. 라는 의미이다. 설명이 이해가 안간다면 댓글로 질문하면 작성자가 확인후 답변 하겠다.

 

캐릭터 클래스를 만들어보자.

class Character:
    def __init__(self,hat,top,down,shoe,weapon,name):
        self.hat = hat
        self.top = top
        self.down = down
        self.shoe = shoe
        self.weapon = weapon
        self.name = name

장비 외에 이름도 넣어주었다.

 

캐릭터라는 클래스명을 만들어놓고, __init__으로 생성자를 지정해준다.

생성자가 무엇이냐.

클래스를 만들어놓고 해당 클래스에 값을 넣어주는 함수라고 생각하면 된다.

kakao = Character('오토바이헬멧','나시','비닐바지','나막신','닭 뼈','kakao')
print(kakao)
#<__main__.Character object at 0x7fee3122ddc0>

카카오라는 변수는 캐릭터라는 클래스라는 틀을 가진 하나의 객체 이며, 장비와 이름을 입력해준다.

카카오를 프린트해보면 오브젝트가 출력된다.

그도 그럴것이 객체는 생성했지만 어떤 명령도 주지 않았기 때문이다.

만약 객체 자체를 호출했을 때, 어떤 기능을 주고 싶다면

class Character:
    def __init__(self,hat,top,down,shoe,weapon,name):
        self.hat = hat
        self.top = top
        self.down = down
        self.shoe = shoe
        self.weapon = weapon
        self.name = name
    def __repr__(self):
        return f'Welcome {self.name}'
kakao = Character('오토바이헬멧','나시','비닐바지','나막신','닭 뼈','kakao')
print(kakao)

#Welcome kakao

와 같이 __repr__ 함수를 선언하고, 기능을 주면 된다.

 

 

각 변수에 접근하고싶다면

kakao.hat
kakao.top
kakao.down
kakao.shoe
kakao.weapon
kakao.name

등으로 출력하면 접근이 가능하다.

 

한번 생성된 클래스는 다른 속성을 담아 다른 변수에 할당이 가능하다.

kakao = Character('오토바이헬멧','나시','비닐바지','나막신','닭 뼈','kakao')
naver = Character('방탄헬멧','방탄조끼','레깅스','전투화','연사가능한 무반동 저격소총','naver')
print(kakao)
print(naver)


#Welcome kakao
#Welcome naver

이제 현재 착용중인 장비를 반환하는 함수를 클래스 안에 만들어보자.

 

class Character:
    def __init__(self,hat,top,down,shoe,weapon,name):
        self.hat = hat
        self.top = top
        self.down = down
        self.shoe = shoe
        self.weapon = weapon
        self.name = name
    def __repr__(self):
        return f'Welcome {self.name}'
    def status(self):
        return f'현재 착용중인 장비는 {self.hat } { self.top } { self.down } { self.shoe } { self.weapon}입니다.'
        
        
kakao = Character('오토바이헬멧','나시','비닐바지','나막신','닭 뼈','kakao')
naver = Character('방탄헬멧','방탄조끼','레깅스','전투화','연사가능한 무반동 저격소총','naver')
print(kakao.status())
print(naver.status())

#현재 착용중인 장비는 오토바이헬멧 나시 비닐바지 나막신 닭 뼈입니다.
#현재 착용중인 장비는 방탄헬멧 방탄조끼 레깅스 전투화 연사가능한 무반동 저격소총입니다.

 

여기서 의문이 생긴다.

왜 클래스 안에서 생성된 함수에는 self가 맨 처음 인자로 들어갈까?

 

__init__을 보면, self.<변수명> = <변수명>

으로 담아줬다. self는 생성자로 받아온 파라미터들을 클래스 전역에서 사용가능하도록 지정해주는 메서드이다.

실제로 생성자에서 self로 따로 명시해주지않으면, 클래스 내에 다른 함수에서는 사용이 불가능하다.

 

 

생각해보니 좀 억울하다. 나는 무기 하나만 들고, 혹은 무기없이 맨손으로 캐릭터를 만들고싶다.

혹은 다른 장비도 같이 지정해주고 싶다면? 클래스별 속성을 다양하게 가지고 싶다면 사용할 수 있는 파라미터가

**kwargs

이다

class Custom_Chracter:
    def __init__(self,name,**kwargs):
        self.name = name
        self.kwargs = kwargs
    def status(self):
        return f'현재 착용중인 장비는 {" ".join([self.kwargs[i] for i in self.kwargs])}입니다.'

print(Custom_Chracter('kakao',weapon = '나막신').status())
#현재 착용중인 장비는 나막신입니다.
print(Custom_Chracter('kakao',weapon = '나막신').kwargs)
#{'weapon' : '나막신' }

kwargs는 정확하게 {파라미터 = 값} 으로 입력해주어야 클래스의 파라미터로 인식한다.

**kwargs는 출력해보면 { key : value }의 사전형태로 출력된다.

즉 함수 혹은 클래스 사용자가 직접 변수를 생성할 수 있도록 할 때, kwargs를 사용한다.

 

 

어떤 장비를 착용하길 원하는지 모르므로 리스트컴프리헨션으로 다 뽑아주고 join으로 한 칸씩 띄어서 문자열을 반환한다.

더보기

사실 통상적으로 kwargs를 사용하지만, ** < 이 별 두개가 중요한 역할을 한다.

즉 **asd나 **thanks **hi 등을 써도 모두 올바르게 작동한다.

 

다음은 변수를 이름없이 사용하고 싶을 때는

*args

를 사용한다.

미리 정의해놓은 변수보다 많은 파라미터가 입력되면, 모두 args에 저장된다.

class Custom_Chracter:
    def __init__(self, name,*args, **kwargs):
        self.name = name
        self.kwargs = kwargs
        self.args = args
    def status(self):
        return self.args
        #return f'현재 착용중인 장비는 {" ".join([self.kwargs[i] for i in self.kwargs])}입니다.'

print(Custom_Chracter('kakao',12354,874953,68432,'qwe',weapon = '나막신').status())

#(12354, 874953, 68432, 'qwe')

status를 출력하면 self.args를 반환하게 했고,

name = 'kakao'가 입력되고 weapon='나막신' 처럼 변수명을 주지 않은 중간에 모든 값들이 args로 입력된다.

출력은 튜플형태로 묶이며, 슬라이싱으로 추출 가능하다.

숫자를 입력받아 연산하는 클래스나 함수를 구성하는데 사용하면,

입력받은 모든 값을 연산하는 코드를 만들 수 있다.

 

**kwargs , *args는 모두 클래스 밖 함수에서도 사용 가능하니 참고해서 fancy한 개발자가 되길 바란다.

반응형