8.4. Builtin Printing¶
8.4.1. Escape Characters¶
\r\n
- is used on windows\n
- is used everywhere else
Sequence |
Description |
---|---|
|
New line (LF - Linefeed) |
|
Carriage Return (CR) |
|
Horizontal Tab (TAB) |
|
Single quote |
|
Double quote |
|
Backslash |
Sequence |
Description |
---|---|
|
Bell (BEL) |
|
Backspace (BS) |
|
New page (FF - Form Feed) |
|
Vertical Tab (VT) |
|
Character with 16-bit (2 bytes) hex value |
|
Character with 32-bit (4 bytes) hex value |
|
ASCII character with octal value |
|
ASCII character with hex value |
print('\U0001F680') # 🚀
8.4.2. String Module¶
import string
string.punctuation
# '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
string.whitespace
# ' \t\n\r\x0b\x0c'
string.ascii_lowercase
# 'abcdefghijklmnopqrstuvwxyz'
string.ascii_uppercase
# 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
string.ascii_letters
# 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
string.digits
# '0123456789'
string.hexdigits
# '0123456789abcdefABCDEF'
string.octdigits
# '01234567'
string.printable
# '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'
8.4.3. print
function¶
8.4.4. Function definition¶
def print(*values, sep=' ', end='\n', file=sys.stdout, flush=False):
"""
Prints the values to a stream, or to sys.stdout by default.
Optional keyword arguments:
file: a file-like object (stream); defaults to the current sys.stdout.
sep: string inserted between values, default a space.
end: string appended after the last value, default a newline.
flush: whether to forcibly flush the stream.
"""
...
8.4.5. Intuitive implementation¶
Intuitive implementation of print
function:
def print(*values, sep=' ', end='\n', ...):
return sep.join(values) + end
8.4.6. Printing multiple values¶
name = 'José Jiménez'
print('My name...', name, '!')
# My name... José Jiménez!
name = 'José Jiménez'
print('My name...', name, '!', sep=';')
# My name...;José Jiménez;!
8.4.7. String concatenation¶
+
operator (with side effects)str.join()
str.format()
f-string formatting (preferred)
8.4.8. +
Operator¶
f-string formatting are preferred over
str
additionHow many
str
are in the memory?
name = 'Mark Watney'
'My name... ' + name
# 'My name... José Jiménez'
+
Operator side effect:
name = 'Mark Watney'
age = 42
'My name... ' + name + ' and I am ' + str(age) + ' years old!'
# 'My name... Mark Watney and I am 42 years old!'
8.4.9. str.join()
¶
data = ['Mark Watney', 'Melissa Lewis', 'Rick Martinez']
' '.join(data) # 'Mark Watney Melissa Lewis Rick Martinez'
','.join(data) # 'Mark Watney,Melissa Lewis,Rick Martinez'
', '.join(data) # 'Mark Watney, Melissa Lewis, Rick Martinez'
8.4.10. Variable interpolation¶
8.4.11. Operator: %s
, %d
, %f
¶
positional
keyword
%s
-str
%d
-int
%f
-float
name = 'José Jiménez'
age = 42
pi = 3.141592653589793
'My name... %s' % name # My name... José Jiménez
'My name... %d' % name # TypeError: %d format: a number is required, not str
'My name... %f' % name # TypeError: must be real number, not str
'I have %s years' % age # 'I have 42 years'
'I have %d years' % age # 'I have 42 years'
'I have %f years' % age # 'I have 42.000000 years'
'Number PI is %s' % pi # 'Number PI is 3.141592653589793'
'Number PI is %f' % pi # 'Number PI is 3.141593'
'Number PI is %d' % pi # 'Number PI is 3'
name = 'José Jiménez'
age = 42
'%s has %s years' % (name, age)) # José Jiménez has 42 years
'%s has %s years' % (age, name)) # 42 has José Jiménez years
pi = 3.141592653589793
def square(value):
return value ** 2
'PI squared is %f' % square(pi) # 'PI squared is 9.869604'
data = {
'name': 'José Jiménez',
'age': 42,
}
'%(name)s has %(age)d years' % data
# 'José Jiménez has 42 years'
'%(name)s has %(age)d years' % {'name': 'José Jiménez', 'age': 42}
# 'José Jiménez has 42 years'
name = 'José Jiménez'
age = 42
'My name... %(name)s' % locals()
# 'My name... José Jiménez'
8.4.12. str.format()
¶
name = 'José Jiménez'
age = 42
'{} is {} years'.format(name, age) # 'José Jiménez is 42 years'
'{0} is {1} years'.format(name, age) # 'José Jiménez is 42 years'
'{1} is {0} years'.format(name, age) # '42 is José Jiménez years'
name = 'José Jiménez'
age = 42
'{a} is {b} years'.format(a=name, b=age) # 'José Jiménez is 42 years'
'{name} is {age} years'.format(name=name, age=age) # 'José Jiménez is 42 years'
'{age} is {name} years'.format(**locals()) # '42 is José Jiménez years'
8.4.13. f-strings - Python >= 3.6¶
Preferred way
name = 'José Jiménez'
pi = 3.141592653589793
def square(value):
return value ** 2
f'My name... {name}' # 'My name... José Jiménez'
f'PI squared is {square(pi)}' # 'PI squared is 9.869604401089358'
from datetime import datetime
now = datetime.now()
iso = '%Y-%m-%dT%H:%M:%SZ'
f'Today is: {now:%Y-%m-%d}') # 'Today is: 1969-07-21'
f'Today is: {now:{iso}}') # 'Today is: 1969-07-21T02:56:15Z'
8.4.14. Advanced String Formatting¶
Since Python 3.0: PEP 3101 -- Advanced String Formatting
8.4.15. Basic formatting¶
text = 'PI'
number = 3.14
f'{text} = {number}' # 'PI = 3.14'
8.4.16. Padding and aligning strings¶
text = 'hello'
f'{text:10}' # 'hello '
f'{text:<10}' # 'hello '
f'{text:^10}' # ' hello '
f'{text:>10}' # ' hello'
f'{text:.<10}' # 'hello.....'
f'{text:_^10}' # '__hello___'
8.4.17. Type casting¶
number = 3
f'{number}' # '3'
f'{number:d}' # '3'
f'{number:f}' # '3.000000'
number = 3.141592653589793
f'{number}' # '3.141592653589793'
f'{number:d}' # ValueError: Unknown format code 'd' for object of type 'float'
f'{number:f}' # '3.141593'
text = 'hello'
f'{text}' # 'hello'
f'{text:d}' # ValueError: Unknown format code 'd' for object of type 'str'
f'{text:f}' # ValueError: Unknown format code 'f' for object of type 'str'
f'{14:#b}' # '0b1110'
f'{14:b}' # '1110'
f'{10:#o}' # '0o12'
f'{10:o}' # '12'
f'{255:#x}' # '0xff'
f'{255:x}' # 'ff'
f'{255:X}' # 'FF'
8.4.18. Truncating and rounding¶
text = 'Lorem Ipsum'
f'{text:.5}' # 'Lorem'
f'{text:10.5}' # 'Lorem '
number = 3.141592653589793
f'{number:.2f}' # '3.14'
f'{number: 6.2f}' # ' 3.14'
f'{number:06.2f}' # '003.14'
f'{number:.6.2f}' # ValueError: Invalid format specifier
8.4.19. Signed numbers¶
positive = 42
negative = -42
f'{positive:d}' # '42'
f'{negative:d}' # '-42'
f'{positive: d}' # ' 42'
f'{negative: d}' # '-42'
f'{positive:+d}' # '+42'
f'{negative:+d}' # '-42'
f'{negative:=5d}' # '- 42'
f'{positive:=+5d}' # '+ 42'
8.4.20. Get from dict
¶
data = {
'firstname': 'Mark',
'lastname': 'Watney'
}
f'{data["firstname"]}' # 'Mark'
f'{data["lastname"]}' # 'Watney'
8.4.21. Get from sequence
¶
data = ['a', 'b', 'c']
f'{data[1]}' # 'b'
f'{data[0]} -> {data[2]}' # 'a -> c'
data = ('a', 'b', 'c')
f'{data[1]}' # 'b'
f'{data[0]} -> {data[2]}' # 'a -> c'
data = {'a', 'b', 'c'}
f'{data[1]}'
# Traceback (most recent call last):
# TypeError: 'set' object is not subscriptable
8.4.22. Get from class
¶
class Iris:
species = 'setosa'
measurements = {
'sepal_length': 5.1,
'sepal_width': 3.5,
'petal_length': 1.3,
'petal_width': 0.4,
}
flower = Iris()
f'{flower.species}' # 'setosa'
f'{flower.species:.3}' # 'set'
f'{flower.measurements["sepal_width"]}' # '3.5'
f'{flower.measurements["sepal_width"]:.3f}' # '3.500'
8.4.23. Parametrized formats¶
text = 'hello'
align = '^'
width = 10
f'{text:{align}}' # 'hello'
f'{text:{align}{width}}' # ' hello '
number = 3.14159
align = '>'
width = 10
precision = 2
sign = '+'
f'{number:.{precision}f}' # '3.14'
f'{number:{width}.{precision}f}' # ' 3.14'
f'{number:{align}{sign}{width}.{precision}f}' # ' +3.14'
8.4.24. Datetime¶
from datetime import datetime
now = datetime(1969, 7, 21, 2, 56, 15)
iso = '%Y-%m-%dT%H:%M:%SZ'
date = '%Y-%m-%d'
time = '%H:%M'
f'{now:%Y-%m-%d %H:%M}' # '1969-07-21 02:56'
f'{now:{iso}}' # '1969-07-21T02:56:15Z'
f'{now:{date}}' # '1969-07-21'
f'{now:{time}}' # '02:56'
8.4.25. Custom object formatting¶
class Point:
def __init__(self, x, y, z=0):
self.x = x
self.y = y
self.z = z
def __format__(self, format):
if format == '2D':
return f"({self.x}, {self.y})"
elif format == '3D':
return f"({self.x}, {self.y}, {self.z})"
elif format == 'dict':
return str(self.__dict__)
elif format == 'tuple':
return str(tuple(self.__dict__.values()))
elif format == 'json':
import json
return json.dumps(self.__dict__)
else:
raise ValueError
point = Point(x=1, y=2)
f'{point:2D}' # '(1, 2)'
f'{point:3D}' # '(1, 2, 0)'
f'{point:tuple}' # '(1, 2, 0)'
f'{point:dict}' # "{'x': 1, 'y': 2, 'z': 0}"
f'{point:json}' # '{"x": 1, "y": 2, "z": 0}'
8.4.26. str
and repr
¶
!s
executes__str__()
!r
executes__repr__()
class Point:
def __init__(self, x, y, z=0):
self.x = x
self.y = y
self.z = z
def __str__(self):
return f'({self.x}, {self.y}, {self.z})'
def __repr__(self):
return f'Point(x={self.x}, y={self.y}, z={self.z})'
point = Point(x=1, y=2)
f'{point!s}' # '(1, 2, 0)'
f'{point!r}' # 'Point(x=1, y=2, z=0)'
8.4.27. Quick and easy debugging¶
Since Python 3.8: See https://bugs.python.org/issue36817
f'{expr=}'
expands to the text of the expression, an equal sign, then the repr of the evaluated expression
number = 3
f'{number*9 + 15=}'
# x*9 + 15=42
astronaut = 'Watney'
birthdate = date(1975, 7, 31)
delta = date.today() - member_since
f'{user=} {member_since=}'
# "astronaut='Watney' birthdate=datetime.date(1975, 7, 31)"
f'{astronaut=!s} {delta.days=:,d}'
# 'astronaut=Watney delta.days=16,075'
print(f'{theta=} {cos(radians(theta))=:.3f}')
# theta=30 cos(radians(theta))=0.866
8.4.28. pprint
¶
from pprint import pprint
data = [
{'firstname': 'Mark', 'lastname': 'Watney'},
{'firstname': 'Melissa', 'lastname': 'Lewis'},
{'firstname': 'Rick', 'lastname': 'Martinez'},
]
pprint(data)
# [{'firstname': 'Mark', 'lastname': 'Watney'},
# {'firstname': 'Melissa', 'lastname': 'Lewis'},
# {'firstname': 'Rick', 'lastname': 'Martinez'}]
from pprint import pformat
data = [
{'firstname': 'Mark', 'lastname': 'Watney'},
{'firstname': 'Melissa', 'lastname': 'Lewis'},
{'firstname': 'Rick', 'lastname': 'Martinez'},
]
# returns formatted data
my_string = pformat(data)
8.4.29. Use Case - 0x01¶
>>>
... from time import sleep
...
...
... def progressbar(percent):
... filled = '=' * percent
... empty = ' ' * (100-percent)
... clear = '\b' * 110
... bar = f'{clear}{percent:4}% |{filled}{empty}|'
... print(bar, end='')
...
...
... for i in range(0,101):
... progressbar(i)
... sleep(0.2)
8.4.30. Assignments¶
8.4.30.1. Powielanie napisów¶
Assignment: Powielanie napisów
Complexity: easy
Lines of code: 8 lines
Time: 5 min
- English:
Given string:
text = 'Lorem Ipsum'
Write three functions:
print_1(text)
usingrange()
print_2(text)
usingwhile
loopprint_3(text)
using string multiplication
Each function should print 5 copies of this string
Each string in a separate line
Write doctest for all functions
Run doctests - all must succeed
- Polish:
Dany jest ciąg znaków:
text = 'Lorem Ipsum'
Napisz trzy funkcje:
print_1(text)
wykorzystującąrange()
print_2(text)
wykorzystującą pętlęwhile
print_3(text)
wykorzystującą mnożenie stringów
Każda funkcja ma wyświetlić 5 kopii tego ciągu znaków
Każdy ciąg znaków w osobnej linii
Napisz doctest do wszystkich funkcji
Uruchom doctesty - wszystkie muszą się powieść
8.4.30.2. Przeliczanie temperatury¶
Assignment: Przeliczanie temperatury
Complexity: easy
Lines of code: 8 lines
Time: 13 min
- English:
Write a program that will display a table of Celsius to Fahrenheit conversions in the range from -20 to +40 degrees Celsius (every 5 degrees).
The result must be as shown in the listing below
The sign must always be displayed
Pay attention to the text justification
Pay attention to filling the space not occupied by numbers
Run doctests - all must succeed
- Polish:
Napisz program, który wyświetli tabelę przeliczeń stopni Celsjusza na stopnie Fahrenheita w zakresie od –20 do +40 stopni Celsjusza (co 5 stopni).
Wynik musi być taki jak na listingu poniżej
Znak ma być zawsze wyświetlany
Zwróć uwagę na wyjustowanie tekstu
Zwróć uwagę na wypełnienie miejsca niezajętego przez cyfry
Uruchom doctesty - wszystkie muszą się powieść
- Tests:
>>> import sys; sys.tracebacklimit = 0
------------------------------------------- | Temperature | - 20°C | ....-4....°F | ------------------------------------------- | Temperature | - 15°C | ....+5....°F | ------------------------------------------- | Temperature | - 10°C | ...+14....°F | ------------------------------------------- | Temperature | - 5°C | ...+23....°F | ------------------------------------------- | Temperature | + 0°C | ...+32....°F | ------------------------------------------- | Temperature | + 5°C | ...+41....°F | ------------------------------------------- | Temperature | + 10°C | ...+50....°F | ------------------------------------------- | Temperature | + 15°C | ...+59....°F | ------------------------------------------- | Temperature | + 20°C | ...+68....°F | ------------------------------------------- | Temperature | + 25°C | ...+77....°F | ------------------------------------------- | Temperature | + 30°C | ...+86....°F | ------------------------------------------- | Temperature | + 35°C | ...+95....°F | ------------------------------------------- | Temperature | + 40°C | ...+104...°F |
- Hints:
Fahrenheit to Celsius: (°F - 32) / 1.8 = °C
Celsius to Fahrenheit: (°C * 1.8) + 32 = °F
def celsius_to_fahrenheit(degree): return degree*1.8 + 32