[Python] Method & Decorator

류지수·2023년 6월 27일
0

Study

목록 보기
5/9

#Method

Instance 메소드

self.~~로 선언하는 변수

  • 인스턴스마다 인스턴스 변수값 다름
  • 해당 메서드를 호출한 객체에만 영향을 미침
  • 호출 방법
    • 해당 클래스 안 : self.메소드명()
    • 클래스 밖 : 객체.메소드명()

class 메소드

클래스 전체가 공유하는 변수

  • 클래스가 선언될 때 정해짐
  • 클래스 메소드를 지정하기 위해 @classmethod 사용
  • 클래스명.클래스메서드명, 객체명.클래스메서드명으로 호출 가능
  • cls 사용을 통해 클래스 메서드 내부에서 현재 클래스의 인스턴스를 만들 수 있음
📍Example
class User:
  	cnt = 0
	def __init__(self):
  		User.cnt+=1

  	@classmethod
  	def print_cnt(cls):
  		print(f'{cls.count}명 생성되었습니다')  #클래스 속성 접근 가능

  	@classmethod
  	def create(cls):
  		t = cls()	# 메서드 내부에서 cls()로 현재 클래스의 인스턴스를 만들 수 있음
  		return t

  User1 = User()
  User2 = User()

  User.print_cnt()
  print(User.create())

  => 출력결과
  => 2명이 생성되었습니다
  => <__main__.Person object at 0x00C68238>

Static 메소드

  • @staticmethod 사용
  • 인스턴스를 만들지 않아도 class.method()로 바로 호출 가능
  • self를 인자로 받지 않음
    • 인스턴스 속성에 접근 불가
    • 인스턴스/클래스 메서드 호출 불가
  • 인스턴스의 상태를 변화시키지 않는 메소드를 만들 때 사용

#Decorator

정적 메소드(@staticmethod, @classmethod)

  • 클래스에서 직접 접근할 수 있는 메소드
    • python에서 클래스에 직접 접근 가능한 메소드 : staticmethod, classmethod
  • staticmethod : 특별히 추가되는 인자 없음
  • classmethod : 첫 번째 인자로 클래스(cls)를 입력
  • python에서는 다른 언어와 다르게 정적메소드임에도 불구하고 인스턴스에서도 접근 가능!

@staticmethod

특징

  • instance 변수에 접근할 수 없음
    • @staticmethod에서는 self.~~ 불가능
  • class 변수에 접근할 때는 클래스이름.변수명으로 접근 가능
📍Example
class Korean:
	def __init__(self, height):
    	self.h = height
   	def get_h(self):
    	return self.h
Kim = Korean(175)
print(kim.get_h))
=> 175
class Korean:
	def __init__(self, height):
    	self.h = height
    @staticmethod
   	def get_h():
    	return self.h
Kim = Korean(175)
print(kim.get_h))
=> NameError : name 'self' is not defined
  • 클래스 안에 있는 일반 메소드들의 첫 번째 인자 -> self
    but, @staticmethod에서는 "인스턴스 변수에 접근할 수 없다" == self.변수 개념 사용 불가
📍Example
class Temp:
	def func1(self, arg):
    	return arg*2
    @staticmethod
    def func2(arg): # self를 첫 번째 인자로 받지 않음
    	return arg*3

@classmethod

특징

  • instance 내부가 아닌 class 전체 관점에서 변수를 다룰 수 있음
    • 사용 용도 : class 인스턴스 모두가 공유하는 보편적인 값을 설정하고 싶을 때 사용
    • @classmethod를 쓴 메소드의 첫 번째 인자 => cls
Example
class Example():
	def met1(self, value):
    	self.value = value
    @classmethod
   	def met2(cls, value):
    	self.variable = value

a = Example()
b = Example()
### 오류 ###
a.met1(999)
print(b.variable)
=> 'Error'

### 올바른 사용 ###
a.met2(999)
print(b.variable)
=> 999

사용

📍Example
class Member():
  	_ins = []  # Member._ins

def __init__(self, name, height, weight, fat):
  	self.name = name
  	self.height = height
  	self.weight = weight
  	self.fat = fat

  	self.add_instance(self)

 @classmethod
 def add_instance(cls, ins):
 	cls._ins.append(ins)
 
a = Member('Kim', 180, 77, 24)
b = Member('Lee', 170, 71, 16)
c = Member('Choi', 160, 47, 23)
d = Member('Park', 170, 63, 20)

height_mean = sum([m.height for m in Member._ins])
print(f'height_mean = {height_mean}'

=> height_mean = 170.0

예를들어, 키의 평균을 구한다고 하면 @classmethod를 사용하면 직관적으로 구할 수 있음.
class 생성자 함수에 인스턴스 자기 자신을 class 변수인 list에 저장하도록 하면 class가 선언될 때마다 자동으로 class 변수가 저장됨. => _ins 클래스 변수가 일종의 Member목록이 됨

접근제어자 (Access Modifier) (@property)

접근 제어자에는 public, private, protected, default 가 있음.
파이썬은 다른 언어와 달리 접근 제어자가 없고 작명법으로 접근을 제어할 수 있음.
(python에서는 다른 객체지향 언어와 달리 실제로 접근을 막지 못함)

  • public : 접두사에 아무 밑줄이 없음
  • private : 접두사에 두개의 밑줄(__) 적용
  • protected : 접두사에 한개의 밑줄(_) 적용
📍Example
class Example:
 	def __init__(self):
  		pass

	def public(self):	# 외부에서 자유롭게 접근 가능
  		print('public')

  	def _protected(self):	
  # 부모 클래스에서는 public, 외부에서는 private 취급
  # python에서는 실질적으로 접근을 제어하지 않고 '_'을 붙여 경고(명시)하는 정도로만 사용
  		print(protected(self)

  	def __private(self): # 내부에서만 접근 가능
  		print('private')

  	def access_modifier(self):
  		self.__private() # 내부에서 접근하므로 정상적인 접근 가능

@property

  • 원래 class method를 부를 때는 괄호를 붙여서 함수를 부르듯이 사용
  • @property를 사용할 때는 이름만 부름
    • argument를 받지 못함
📍Example
class Person:
	def __init__(self, name, age):
  		self._name = name
  		self._age = age

  	def name(self):
  		return self._name
  	@property
  	def age(self):
  		return self._age


 p. Person('abc', 29)
 p._name() # 일반 class method 호출
 p.age	# @property로 호출
  • getter, setter 간단히 구현 가능
    • getter에는 @property, setter에는 @메서드이름.setter
      *주의할 점 : @property가 @method.setter보다 위에 있어야 함
📍Example
class Person:
    def __init__(self):
        self.__age = 0

    @property
    def age(self):           # getter
        return self.__age

    @age.setter
    def age(self, value):    # setter
        self.__age = value

james = Person()
james.age = 20      # 인스턴스.속성 형식으로 접근하여 값 저장
print(james.age)    # 인스턴스.속성 형식으로 값을 가져옴


=> 20

Reference

profile
AI Engineer가 될테야

0개의 댓글