1 of 62

Lecture 21

String representation and Special Methods

2 of 62

mic

3 of 62

String Representations

4 of 62

String Representations

  • An object value should behave like the kind of data it is meant to represent
  • For instance, by producing a string representation of itself

5 of 62

String Representations

  • An object value should behave like the kind of data it is meant to represent
  • For instance, by producing a string representation of itself

In Python, all objects produce two string representations:

  • The str is easy for humans, to be readable
    • Informal representation
  • The repr is easy for the Python interpreter
    • Official representation

6 of 62

String Representations

  • An object value should behave like the kind of data it is meant to represent
  • For instance, by producing a string representation of itself

In Python, all objects produce two string representations:

  • The str is easy for humans
  • The repr is easy for the Python interpreter (expression in Python)

The str and repr strings are often the same, but not always

7 of 62

What is easier to understand?

8 of 62

The repr String for an Object

The result of calling repr on a value is what Python prints in an interactive session

9 of 62

The repr String for an Object

The result of calling repr on a value is what Python prints in an interactive session

10 of 62

The repr String for an Object

The result of calling repr on a value is what Python prints in an interactive session

11 of 62

The repr String for an Object

The result of calling repr on a value is what Python prints in an interactive session

Some objects do not have a simple Python-readable string

12 of 62

The repr String for an Object

The result of calling repr on a value is what Python prints in an interactive session

Some objects do not have a simple Python-readable string

The repr function returns a Python expression (a string) that evaluates to an equal object: https://docs.python.org/3/library/functions.html#repr

13 of 62

eval( ):

utility which lets a Python program run Python code within itself, by evaluating expressions.

  • It is used on sites like codepad.org to allow you to execute scripts in a test environment.

eval(expression, globals=None, locals=None)

  • expression: this string is parsed and evaluated as a Python expression
  • globals (optional): a dictionary to specify the available global methods and variables.
  • locals (optional): another dictionary to specify the available local methods and variables.

(quick demo)

14 of 62

The repr String for an Object

The repr function returns a Python expression (a string) that evaluates to an equal object: https://docs.python.org/3/library/functions.html#repr

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...

15 of 62

The repr String for an Object

The repr function returns a Python expression (a string) that evaluates to an equal object: https://docs.python.org/3/library/functions.html#repr

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

16 of 62

The str String for an Object, Demo

17 of 62

The str String for an Object

18 of 62

The str String for an Object + another Demo

The result of calling str on the value of an expression is what Python prints using the print function:

19 of 62

Question: Output?

name = “ ‘ Marina ‘ ”

eval(name) eval(repr(name)) str(name)

A: ‘ Marina ’ ‘ Marina ’ \” “ ‘ Marina ‘ “ \”

B: Error “ ‘ Marina ‘ “ ‘ Marina ’

C: Marina Error ‘ Marina’

D: “ ‘ Marina ‘ “ ‘ Marina ’ “ ‘ Marina ‘ “

E: ‘ Marina ‘ “ ‘ Marina ‘ “ “ ‘ Marina ‘ “

20 of 62

Question

class Animal:

voice = lambda: "Grrrr"

def __init__(self, type, sound):

self.type = type

self.voice = lambda: sound

a = Animal("dog", "woof-woof")

A: a.voice()

Animal.voice()

B: Animal.voice()

a.voice()

C: a.voice(“woof-woof”)

Animal.voice(“Grrrrr”)

D: Animal.voice(“woof-woof”)

a.voice(“Grrrrr”)

E: Not possible

Desired output:

woof-woof

Grrrr

21 of 62

Polymorphic Functions

22 of 62

Polymorphic Functions

Polymorphic function: A function that applies to many (poly) different forms (morph) of data

str and repr are both polymorphic; they apply to any object:

23 of 62

User defined classes

  • Need to have methods __str__ and __repr__ in order to be able to print string representation of an object.
  • If __str__ does not exist, then __repr__ will be used

  • At the very least, you should implement ___ repr___

class Test():

def __init__(self, n):

self.n = n

def __str__(self):

return 'this is me: ' + str(self.n)

def __repr__(self):

return 'this is a repr'

>>> t = Test(5)

>>> t

this is a repr

>>> print(t)

this is me: 5

24 of 62

User defined classes

  • Need to have methods __str__ and __repr__ in order to be able to print string representation of an object.
  • If __str__ does not exist, then __repr__ will be used

  • At the very least, you should implement ___ repr___

class Test():

def __init__(self, n):

self.n = n

def __str__(self):

return 'this is me: ' + str(self.n)

def __repr__(self):

return 'this is a repr'

>>> t = Test(5)

>>> t.__repr__()

‘this is a repr’

>>> t.__str__()

‘this is me: 5’

25 of 62

User defined classes

  • Need to have methods __str__ and __repr__ in order to be able to print string representation of an object.
  • If __str__ does not exist, then __repr__ will be used

  • At the very least, you should implement ___ repr___

class Test():

def __init__(self, n):

self.n = n

def __repr__(self):

return 'this is a repr'

>>> t = Test(5)

>>> t

this is a repr

>>> print(t)

this is a repr

26 of 62

User defined classes

  • Need to have methods __str__ and __repr__ in order to be able to print string representation of an object.
  • If __str__ does not exist, then __repr__ will be used

  • At the very least, you should implement ___ repr___

class Test():

def __init__(self, n):

self.n = n

>>> t = Test(5)

>>> t

<__main__.Test object at 0x7fd1d8096430>

>>> print(t)

<__main__.Test object at 0x7fd1d8096430>

27 of 62

mic

28 of 62

Recap

  • repr and str
  • __repr__ and __str__

29 of 62

Recap

  • repr and str
  • __repr__ and __str__

class Ratio:

def __init__(self, n, d):

self.numer = n

self.denom = d

30 of 62

Recap

  • repr and str
  • __repr__ and __str__

class Ratio:

def __init__(self, n, d):

self.numer = n

self.denom = d

def __str__(self):

return '{0}/{1}'.format(self.numer, self.denom)

31 of 62

Recap

  • repr and str
  • __repr__ and __str__

class Ratio:

def __init__(self, n, d):

self.numer = n

self.denom = d

def __str__(self):

return '{0}/{1}'.format(self.numer, self.denom)

def __repr__(self):

return 'Ratio({0}, {1})'.format(self.numer, self.denom)

32 of 62

Recap

  • repr and str
  • __repr__ and __str__

class Ratio:

def __init__(self, n, d):

self.numer = n

self.denom = d

def __str__(self):

return '{0}/{1}'.format(self.numer, self.denom)

def __repr__(self):

return 'Ratio({0}, {1})'.format(self.numer, self.denom)

>>> frac1 = Ratio(3, 4)

>>> print(frac1)

3/4

>>> frac1

Ratio(3, 4)

33 of 62

Polymorphic Functions

Polymorphic function: A function that applies to many (poly) different forms (morph) of data

str and repr are both polymorphic; they apply to any object:

repr asks an argument to display itself

invokes a zero-argument method __repr__ on its argument

34 of 62

Polymorphic Functions

Polymorphic function: A function that applies to many (poly) different forms (morph) of data

str and repr are both polymorphic; they apply to any object:

repr invokes a zero-argument method __repr__ on its argument

str invokes a zero-argument method __str__ on its argument

35 of 62

Special Method Names

36 of 62

Special Method Names in Python

Certain names are special because they have built-in behavior. Always start and end with two underscores

37 of 62

Special Method Names in Python

Certain names are special because they have built-in behavior. Always start and end with two underscores

38 of 62

Special Method Names in Python

Certain names are special because they have built-in behavior. Always start and end with two underscores

39 of 62

40 of 62

41 of 62

42 of 62

Example for __add__

43 of 62

Special Methods:

Adding instances of user-defined classes invokes either the __add__ or __radd__ method

44 of 62

Special Methods: demo

Adding instances of user-defined classes invokes either the __add__ or __radd__ method

http://getpython3.com/diveintopython3/special-method-names.html

https://docs.python.org/3/reference/datamodel.html#special-method-names

45 of 62

__radd__ = __add__ line

  • frac1 + 1 is interpreted as frac1.__add__(1)
  • How about 1 + frac1 which is really (1).__add__(frac1)?
  • The 1 is an instance of a int class and its __add__ method doesn't know anything about Ratio class
  • Does not make sense: frac1 + 1 works but 1 + frac1 does not.
  • If you use __radd__
    • Python will first try(1).__add__(frac1), and if that returns NotImplemented
    • Python will check if the right-hand operand implements __radd__, and if it does, it will call frac1.__radd__(1) rather than halting a program.

46 of 62

class Student:

def __init__(self, age):

self.age = age

def __lt__(self, anoter_Student):

if self.age<anoter_Student.age:

return True

s1 = Student(20)

s2 = Student(22)

print(s1<s2)

Answers:

A: True

B: False

C: None

D: <.... >

E: Something else

47 of 62

class Student:

def __init__(self, age):

self.age = age

def __lt__(self, anoter_Student):

if self.age<anoter_Student.age:

return True

s1 = Student(22)

s2 = Student(20)

print(s1<s2)

Answers:

A: True

B: False

C: None

D: <.... >

E: Something else

48 of 62

class Student:

def __init__(self, age):

self.age = age

def __lt__(self, anoter_Student):

if self.age<anoter_Student.age:

return True

s1 = Student(20)

s2 = Student(22)

#print(s1<s2) # it is true

print(s2>s1)

True

Why?

49 of 62

class Student:

def __init__(self, age):

self.age = age

def __lt__(self, anoter_Student):

if self.age<anoter_Student.age:

return True

s1 = Student(20)

s2 = Student(22)

#print(s1<s2)

print(s2>s1)

Answer:

There are no swapped-argument versions of these methods:

  • __lt__() and __gt__() are each other’s reflection,
  • __le__() and __ge__() are each other’s reflection,
  • __eq__() and __ne__() are their own reflection.

50 of 62

class Student:

def __init__(self, age):

self.age = age

def __lt__(self, anoter_Student):

if self.age<anoter_Student.age:

return True

def __eq__(self, anoter_Student):

if self.age == anoter_Student.age:

return True

else:

return False

s1 = Student(20)

s2 = Student(22)

print(s1==s2) <--False

print(s1!=s2) <--True

Answer:

There are no swapped-argument versions of these methods:

  • __lt__() and __gt__() are each other’s reflection,
  • __le__() and __ge__() are each other’s reflection,
  • __eq__() and __ne__() are their own reflection.

51 of 62

Implementing str

and

repr

52 of 62

Checking your understanding!

class Check:

num = 10

def question(self):

print(self.num)

def setter(self, number):

self.num = number

A: 10� 10

B: None

C: Something Else

D: Error

obj1 = Check()

obj2 = Check()

obj1.question()

obj2.question()

53 of 62

Checking your understanding!

class Check:

num = 10

def question(self):

print(self.num)

def setter(self, number):

self.num = number

A: 10� 10

B: None

C: Something Else

D: Error

obj1 = Check()

obj2 = Check()

obj1.setter(17)

obj1.question()

obj2.question()

54 of 62

Checking your understanding!

class Check:

num = 10

def question(self):

print(Check.num)

def setter(self, number):

self.num = number

A: 10� 10

B: None

C: Something Else

D: Error

obj1 = Check()

obj2 = Check()

obj1.setter(17)

obj1.question()

obj2.question()

55 of 62

Implementing repr and str

The behavior of repr is slightly more complicated than invoking __repr__ on its argument:

  • An instance attribute called __repr__ is ignored! Only class attributes are found

How would we implement this behavior? Which of the following function definitions corresponds to a function repr that takes in some argument, looks up the class attribute called __repr__ and invokes it?

A: D:

B: E:

C:

56 of 62

Implementing repr and str

The behavior of str is also complicated:

  • An instance attribute called __str__ is ignored
  • If no __str__ attribute is found, uses repr string
  • (By the way, str is a class, not a function)
    • When you call str, you call a constructor for built-in string type called str

Question: How do we understand this behavior?

(demo)

57 of 62

What will be printed?

58 of 62

class UC(object):

def __init__(self, name):

self.name = name

def __repr__(self):

return "UC('" + self.name + "')"

def __str__(self):

return 'UC ' + self.name

ucsd = UC("San Diego")

print(repr(ucsd))

A: UC San Diego

B: "UC('San Diego')"

C: UC('San Diego')

59 of 62

class UC(object):

def __init__(self, name):

self.name = name

def __repr__(self):

return "UC('" + self.name + "')"

def __str__(self):

return 'UC ' + self.name

ucsd = UC("San Diego")

print(str(ucsd))

A: UC San Diego

B: 'UC('San Diego')'

C: UC('San Diego')

60 of 62

class UC(object):

def __init__(self, name):

self.name = name

def __repr__(self):

return "UC('" + self.name + "')"

def __str__(self):

return 'UC ' + self.name

ucsd = UC("San Diego")

print(ucsd.__repr__())

A: UC San Diego

B: 'UC('San Diego')'

C: UC('San Diego')

61 of 62

class UC(object):

def __init__(self, name):

self.name = name

def __repr__(self):

return "UC('" + self.name + "')"

def __str__(self):

return 'UC ' + self.name

ucsd = UC("San Diego")

repr(str(ucsd)) == repr(ucsd.__str__())

A: True

B: False

62 of 62

class UC(object):

def __init__(self, name):

self.name = name

def __repr__(self):

return "UC('" + self.name + "')"

def __str__(self):

return 'UC ' + self.name

ucsd = UC("San Diego")

print(ucsd.__str__())

A: UC San Diego

B: 'UC('San Diego')'

C: UC('San Diego')