title: How are __repr__ and __str__ implemented in print function
body: <p>The way that I understand about <code>__str__</code> and <code>__repr__</code> through googling is that <code>__str__</code>is called when <code>print</code>or <code>__str__()</code> function is used and the output is always string. <code>__repr__</code> is called when <code>repr()</code> or <code>__repr__()</code> function is used and while <code>repr()</code> can only output string, <code>__repr__()</code> could be any valid python expression such as tuple, dictionary, string etc.</p>
  
  <p>So I was creating a two class Person and CircularQueue. In person class, it contains variable <strong>name</strong>, <strong>age</strong> and I defined <code>__str__</code> and <code>__repr__</code>. For CircularQueue class, it is ordinal CQ except it only accepts Person class.  </p>
  
  <p>For <code>print(cg.dequeue())</code> it prints only the <strong>name</strong> as I expected with <code>__str__</code>. However, when I run <code>print(cg.multi_dequeue(3))</code>, it gives the output of <code>__repr__</code> and not <code>__str__</code>. I thought that since I used <code>print</code> it would use <code>__str__</code>.</p>
  
  <ol>
  <li><p>Why <code>print(cg.dequeue())</code> output using <code>__str__</code> while <code>print(cg.multi_dequeue(3))</code> output using <code>__repr__</code>?  </p></li>
  <li><p>This question is not really connected to the topic but why can't I use <code>return self</code> in <code>__repr__</code> even if I use <code>cg.multi_dequeue(3).__repr__()</code>? It gives <code>TypeError: __repr__ returned non-string (type Person)</code> error.</p></li>
  </ol>
  
  <pre><code>class Person:
          name = ""
          age = 0
  
          def __init__(self, name, age):
              self.name = name
              self.age = age
          def __repr__(self):
              return ("[Person(name: " + self.name + ", age: " + str(self.age) + ")")
              #return self
          def __str__(self):
              return self.name
  
  class CircularQueue:
  ...
      def enqueue(self, element):
          check = isinstance(element,Person)
          #check if CQ is full
          if self.is_full():
              print("Queue is full!")
              return 0
          #check if input is Person class
          elif check != True:
              print("Element is not a Person class element")
              return 0
          #add element to CQ
          else:
              self.queue[self.rear] = element
              self.rear = (self.rear + 1) % self.M
      def dequeue(self):
          #check if CQ is empty
          if self.is_empty():
              print("Queue is empty")
              return 0
          #return element
          else:
              temp = self.queue[self.front]
              self.queue[self.front] = None
              self.front = (self.front +1) % self.M
              return temp
      def multi_dequeue(self, count):
          temp = []
          for i in  range(count):
              temp.append(self.dequeue())
          return temp
  
  def main():
      cg = CircularQueue(10)
      cg.enqueue(Person("hi",1))
      cg.enqueue(Person("bye",1))
      cg.enqueue(Person("dd",3))
      cg.enqueue(Person("ss",3))
      cg.enqueue(Person("aa",3))
      print(cg.dequeue())
      print(cg.multi_dequeue(3))
  
  main()
  
  </code></pre>
  
  <p>output</p>
  
  <pre><code>hi
  [[Person(name: bye, age: 1), [Person(name: dd, age: 3), [Person(name: ss, age: 3)]
  </code></pre>