python
으로 LinkedList
를 자료구조를 구현해보라고?note
LinkedList
를 구현한 걸 인터넷에서 찾아 보니 __repr__(self)
함수가 보인다. 안의 내용은LinkedList
내부 노드를 출력하기 위해 한 것인데 처음 보는 놈이다. 아놔 저건 뭐하는 놈인고!
클래스를 정의할 때 __init__
함수를 정의하게 된다. 이렇게 함수명 앞뒤로 __
가 붙어 있는 함수를 Dunder 또는 Magic 함수 라고 부른다.
__
언더스코어가 붙은 함수를 말한다.int
함수를 살펴보면, 많은 Dunder 함수가 정의되어 있음을 확인할 수 있다.>>> print(dir(int))
output:
['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__
', '__getnewargs__', '__gt__', '__hash__', '__index__', '__init__', '__init_subclass__', '__int__', '__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__
pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rrshift__', '__rshi
ft__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'i
mag', 'numerator', 'real', 'to_bytes']
__repr__
함수를 처음 봤을 때는 java
의 toString
과 비슷한 줄 알았다. 하지만, 공식 문서를 찾아 보니 전혀 아니다.
repr(object)
함수란?Return a string containing a printable representation of an object. For many types, this function makes an attempt to return a string that would yield an object with the same value when passed to eval(); otherwise, the representation is a string enclosed in angle brackets that contains the name of the type of the object together with additional information often including the name and address of the object. A class can control what this function returns for its instances by defining a
__repr__()
method. If sys.displayhook() is not accessible, this function will raise RuntimeError.
"Return a string containing a printable representation of an object" 문장 때문에 __repr__()
을 __str__()
처럼 재 정의 해서 사용하는 경우가 있는 것이 아닌지?
더 중요한 건!
eval(repr(object)) 를 했을 때 객체를 생성할 수 있어야 한다는 것! 이다.
예를 들어 설명하면,
repr()
함수를 사용하면 eval()
함수로 객체를 생성할 수 있다.a = 'Difference between str() and repr()'
b = repr(a)
c = eval(b)
print(c)
output:
Difference between str() and repr()
str()
을 사용하면 eval()
함수로 객체를 사용할 수 없다.a = 'Difference between str() and repr()'
b = str(a) # b에 str(a) 를 사용한 것에 집중!
c = eval(b)
output:
Traceback (most recent call last):
File "/workspace/firstContainer/data_structure/Person.py", line 27, in <module>
c = eval(b)
File "<string>", line 1
Difference between str() and repr()
^
SyntaxError: invalid syntax
__repr()__
함수를 재정의 해보자!이제 __repr()__
함수를 재정의 하여 eval() 를 이용하여 객체를 생성할 수 있도록 하자.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
클래스를 위와 같이 정리해 놓고 객체를 생성하여 print()
로 출력해 보자.
한 번은 그냥 출력하고, 또 한번은 repr()
함수를 사용하여 출력한다.
tom = Person('Tom', 20)
print(tom)
print(repr(tom))
output:
<__main__.Person object at 0x7f85cd1dd490>
<__main__.Person object at 0x7f85cd1dd490>
print(tom)
와 print(repr(tom))
모두 동일한 값을 출력 함을 알 수 있다.
이제 __str()__
함수를 재정의 하고 객체를 print()
로 출력해 보자.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __del__(self):
print('Bye! Bye! ' + self.name)
def __str__(self):
return 'My name is ' + self.name + '. I am ' + str(self.age) + '.'
tom = Person('Tom', 20)
print(tom)
print(repr(tom))
output:
My name is Tom. I am 20.
<__main__.Person object at 0x7f27e44a9590>
자, 이제 eval()
함수를 이용하여 객체를 생성할 수 있도록 __repr()__
를 재정의하자.
어려울 것 없다.
그 객체에 해당하는 생성자 를 호출하는 구문을 넘겨주면 된다.
Tom 의 경우는 repr(tom)
을 했을 경우 Person('Tom', 20)
값이 반환되면 된다.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __del__(self):
print('Bye! Bye! ' + self.name)
def __str__(self):
return 'My name is ' + self.name + '. I am ' + str(self.age) + '.'
def __repr__(self):
return 'Person(\''+ self.name +'\', ' + str(self.age) +')'
print(tom)
print(repr(tom))
print(eval(repr(tom)))
output:
My name is Tom. I am 20.
Person('Tom', 20)
My name is Tom. I am 20.
print(repr(tom))
값이 생성자를 호출하는 문자열
임을 결과에서 볼수 있다.
그리고 eval()
함수를 통해 객체를 생성하고 print()
함수를 호출했을 때, __str__(self)
가 호출되어 결과가 나오는 것을 확인 할 수 있다.
class
를 정의할 때 print()
함수 대신 __str__(self)
를 정의해서 쓰자!__repr__(self)
는 eval()
을 사용하여 객체를 사용할 수 있도록 재정의 하자!__str__(self)
가 정의되어 있지 않으면, default
로 __repr__(self)
가 호출된다는 것을!