티스토리 뷰

Python

객체지향 - 여러가지 메서드

lluna 2021. 11. 29. 12:22

파이썬은 객체 지향 언어이다. 클래스를 바탕으로 인스턴스를 생성하는데, 각 인스턴스가 대상이라면 그 행동은 메서드가 된다.

메서드에는 4가지 종류가 있다. 여기서는 정적메서드를 제외한 3가지에 대해 살펴보려고 한다.

 

1. 인스턴스 메서드

2. 클라스 메서드

3. 던더 메서드

 

1. 인스턴스 메서드

인스턴스 메서드는 말그대로 인스턴스의 행위이다.

 

2. 클라스 메서드는 클래스 전체에 적용된다.

@classmethod Decorator를 통해 적용할 수 있다.

클래스 메서드를 작성하여 인스턴스를 생성할 수 있다.

 

3. 던더(Dunder) 메서드는 스페셜 메서드로, 특수한 기능을 지닌다.

__str__ 의 경우 문자열을 반환하고, __init__의 경우 인스턴스가 실행될때 속성을 initialize(초기 셋팅)한다. 

__init__ 은 self 라는 인스턴스 변수를 사용하기 때문에 인스턴스 메서드라 할 수 있다.

 

다음 예시를 보자.

먼저 클래스를 정의하자. (define class)

 

class Student:
    pass

 

그리고 인스턴스를 생성하자. (create an object of the class)

 

std = Student()

 

Student()는 Student class의 object를 반환하며 이는 local variable 인 std에 할당된다.

인스턴스 메서드는 인스턴스 변수를 사용하거나 인스턴스 변수에 값을 설정한다.

 

class Student:
	def say_hello(some_student):
    	print("hi, my name is {}.".format(some_student.name))

student1 = Student()
student1.name = "jessie"

 

인스턴스 메서드를 사용해보자.
## 2번의 경우 인스턴스 자신이 첫 번째 파라미터로 자동 전달된다.

# 1. class 에서 메서드 호출
Student.say_hello(student1)
>>> "hi, my name is jessie."

# 2. instance에서 메서드 호출 -> 인스턴스가 첫 번째 파라미터로 자동 전달됨
student1.say_hello()
>>> "hi, my name is jessie."

 

 

클래스 속성을 부여해보자. 

클래스 속성은 모든 인스턴스가 공유하며 class name과 object를 사용하여 접근할 수 있다.

 

class Student:
    schoolName = 'XYZ School'

 

모든 object에 동일하게 적용된다.

 

>>> Student.schoolName
'XYZ School' 
>>> std = Student()
>>> std.schoolName
'XYZ School'

 

 

As you can see, a class attribute is accessed by  Student.schoolName as well as std.schoolName.
Changing the value of class attribute using the class name would change it across all instances.
However, changing class attribute value using instance will not reflect to other instances or class.

 

class 속성은 <클래스명>.<속성명> 또는 <인스턴스명>.<속성명> 으로 접근이 가능하다.

클래스 속성값을 class name을 사용하여 바꾸면 모든 인스턴스도 그 값을 적용받게 되지만, 인스턴스를 사용하여

클래스 속성값을 바꾸면 다른 인스턴스나 클래스에는 적용이 되지 않는다.

 

>>> Student.schoolName = 'ABC School' # change attribute value using class name
>>> std = Student()
>>> std.schoolName
'ABC School'   # value changed for all instances
>>> std.schoolName = 'My School'  # changing instance's attribute
>>> std.schoolName
'My School' 
>>> Student.schoolName # instance level change not reflectd to class attribute
'ABC School' 
>>> std2 = Student()
>>> std2.schoolName
'ABC School'

 

파이썬에서는 @classmethod 를 제공하는데, 이를 통해 method를 클래스 메서드로 선언할 수 있다.

classmethod() 함수대신 사용을 권장한다. (syntactic sugar이기 때문)

 

class Student:
    name = 'unknown' # class attribute
    def __init__(self):
        self.age = 20  # instance attribute

    @classmethod
    def tostring(cls):
        print('Student Class Attributes: name=',cls.name)

 

클래스 메서드의 first parameter는 반드시 cls여야 한다. 

위 예시에서 Student class는 class attribute 'name'과 instance attribute 'age'를 가지고 있다.

tostering() 메서드는 @classmethod decorator로 인해 class method가 되었으며 Student.tostring()으로 호출한다.

 

클래스 메서드를 사용해보자.
## 두 경우 모두 첫 번째 파라미터로 클래스가 자동 전달된다.

# 1
Student.tostring()
>>> Student Class Attributes: name=unknown

# 2
student1.tostring()
>>> Student Class Attributes: name=jessie

 

class method는 class attribute에만 접근 가능하며, instance attribute에는 접근할 수 없다.

 

class Student:
    name = 'unknown' # class attribute
    def __init__(self):
        self.age = 20  # instance attribute

    @classmethod
    def tostring(cls):
        print('Student Class Attributes: name=',cls.name,', age=', cls.age)
>>> Student.tostring()
Traceback (most recent call last):
  File "<pyshell#22>", line 1, in <module>
    Student.tostring()
  File "<pyshell#21>", line 7, in display
    print('Student Class Attributes: name=',cls.name,', age=', cls.age)
AttributeError: type object 'Student' has no attribute 'age'

 

 

클래스 메소드로 인스턴스를 생성해보자.
class Student:
    
    def __init__(self, name, age):
        self.name = name  # instance attribute
        self.age = age # instance attribute

    @classmethod
    def getobject(cls):
    	name = 'Steve'
        age = 25
        return cls(name, age)

클래스 메소드의 첫번째 파라미터 cls로 Student 클래스가 자동 전달되기 때문에 이하 코드는 같은 코드이다.

Student("Steve", 25)
cls("Steve", 25)

 

따라서 class method에서 cls를 리턴할 때, 파라미터값을 주면 instance가 생성된다.

" The following calls the class method to get an object. "

 

>>> std = Student.getobject()
>>> std.name
'Steve'    
>>> std.age
25

 


 

 

던더 메서드는 double underscores 가 앞뒤에 붙는 특별한 매직메서드이다. certain action 발생시 실행된다. 

 

__str__() : int class에서 __str__() 메서드를 호출함.

str() 함수와 같은 역할을 한다.

num = 12

# 1
str(num) 

# 2
int.__str__(num)

 

print문에 인스턴스를 넣으면 __str__ 메서드가 실행된다.

아래 코드에서 self.posts 는 리스트 안에 2개의 인스턴스가 들어가있는 형태가 된다.

print(self.posts) 

-----------------------
[<__main__.Post object at 0x7f609e0c8e20>, <__main__.Post object at 0x7f609e0320d0>]

 

이대로는 str 형식으로 "게시글1", "게시글2"를 출력할 수가 없다. 

따라서 for문을 돌리면서 각각의 게시글을 출력해줘야 한다.

print문에 각 instance를(Post의 object) 넣으면 Post 클래스가 원래 가지고 있던 던더메서드가 실행되면서 __str__ 메서드가 작동한다.

 

for post in self.posts:
    print(post)

-------------------------
작성 날짜: 2019년 8월 30일
내용:
게시글 1

작성 날짜: 
2019년 8월 31일
내용:
게시글 2

 

class Post:
    # 게시글 클래스
    def __init__(self, date, content):
        # 게시글은 속성으로 작성 날짜와 내용을 갖는다
        self.date = date
        self.content = content

    def __str__(self):
        # 게시글의 정보를 문자열로 리턴하는 메소드
        return "작성 날짜: {}\n내용: {}".format(self.date, self.content)
    
    
class BlogUser:
    # 블로그 유저 클래스
    def __init__(self, name):
        """
        블로그 유저는 속성으로 이름, 게시글들을 갖는다
        posts는 빈 배열로 초기화한다
        """
        self.name = name
        self.posts = []

    def add_post(self, date, content):
        # 새로운 게시글 추가
        post = Post(date, content)
        self.posts.append(post)

    def show_all_posts(self):
        # 블로그 유저의 모든 게시글 출력
        for post in self.posts:
            print(post)
        # print(self.posts)
blog_user_1 = BlogUser("jessie")

# 블로그 유저 인스턴스 출력(인사, 이름)
print(blog_user_1)

# 블로그 유저 게시글 2개 추가
blog_user_1.add_post("2019년 8월 30일", """
게시글 1
""")

blog_user_1.add_post("2019년 8월 31일", """
게시글 2
""")

# 블로그 유저의 모든 게시글 출력
blog_user_1.show_all_posts()

 

주요 메서드

__new__(cls, other) To get called in an object's instantiation.
__init__(self, other) To get called by the __new__ method.
__del__(self) Destructor method.

 

 

 

참고

https://www.tutorialsteacher.com/python/classmethod-decorator

 

Python Class Method Decorator @classmethod

Python Class Method Decorator @classmethod In Python, the @classmethod decorator is used to declare a method in the class as a class method that can be called using ClassName.MethodName(). The class method can also be called using an object of the class. T

www.tutorialsteacher.com

 

댓글