ch02
This commit is contained in:
parent
ff85709895
commit
583ec6a898
6
ch02/README.md
Normal file
6
ch02/README.md
Normal file
@ -0,0 +1,6 @@
|
||||
Chapter 2 data files
|
||||
====================
|
||||
|
||||
The files in this folder are not supposed to work if run.
|
||||
They serve as source for the book chapters, and to provide a
|
||||
quick copy/paste tool for whoever would need their content.
|
||||
18
ch02/bytearray.py
Normal file
18
ch02/bytearray.py
Normal file
@ -0,0 +1,18 @@
|
||||
# bytearray.py
|
||||
|
||||
|
||||
>>> bytearray() # empty bytearray object
|
||||
bytearray(b'')
|
||||
>>> bytearray(10) # zero-filled instance with given length
|
||||
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
|
||||
>>> bytearray(range(5)) # bytearray from iterable of integers
|
||||
bytearray(b'\x00\x01\x02\x03\x04')
|
||||
>>> name = bytearray(b'Lina') #A - bytearray from bytes
|
||||
>>> name.replace(b'L', b'l')
|
||||
bytearray(b'lina')
|
||||
>>> name.endswith(b'na')
|
||||
True
|
||||
>>> name.upper()
|
||||
bytearray(b'LINA')
|
||||
>>> name.count(b'L')
|
||||
1
|
||||
24
ch02/chainmap.py
Normal file
24
ch02/chainmap.py
Normal file
@ -0,0 +1,24 @@
|
||||
# chainmap.py
|
||||
|
||||
|
||||
>>> from collections import ChainMap
|
||||
>>> default_connection = {'host': 'localhost', 'port': 4567}
|
||||
>>> connection = {'port': 5678}
|
||||
>>> conn = ChainMap(connection, default_connection) # map creation
|
||||
>>> conn['port'] # port is found in the first dictionary
|
||||
5678
|
||||
>>> conn['host'] # host is fetched from the second dictionary
|
||||
'localhost'
|
||||
>>> conn.maps # we can see the mapping objects
|
||||
[{'port': 5678}, {'host': 'localhost', 'port': 4567}]
|
||||
>>> conn['host'] = 'packtpub.com' # let's add host
|
||||
>>> conn.maps
|
||||
[{'port': 5678, 'host': 'packtpub.com'},
|
||||
{'host': 'localhost', 'port': 4567}]
|
||||
>>> del conn['port'] # let's remove the port information
|
||||
>>> conn.maps
|
||||
[{'host': 'packtpub.com'}, {'host': 'localhost', 'port': 4567}]
|
||||
>>> conn['port'] # now port is fetched from the second dictionary
|
||||
4567
|
||||
>>> dict(conn) # easy to merge and convert to regular dictionary
|
||||
{'host': 'packtpub.com', 'port': 4567}
|
||||
143
ch02/dateandtime.py
Normal file
143
ch02/dateandtime.py
Normal file
@ -0,0 +1,143 @@
|
||||
|
||||
# imports
|
||||
>>> from datetime import date, datetime, timedelta, timezone
|
||||
>>> import time
|
||||
>>> import calendar as cal
|
||||
>>> from zoneinfo import ZoneInfo
|
||||
|
||||
|
||||
# date
|
||||
>>> today = date.today()
|
||||
>>> today
|
||||
datetime.date(2021, 3, 28)
|
||||
>>> today.ctime()
|
||||
'Sun Mar 28 00:00:00 2021'
|
||||
>>> today.isoformat()
|
||||
'2021-03-28'
|
||||
>>> today.weekday()
|
||||
6
|
||||
>>> cal.day_name[today.weekday()]
|
||||
'Sunday'
|
||||
>>> today.day, today.month, today.year
|
||||
(28, 3, 2021)
|
||||
>>> today.timetuple()
|
||||
time.struct_time(
|
||||
tm_year=2021, tm_mon=3, tm_mday=28,
|
||||
tm_hour=0, tm_min=0, tm_sec=0,
|
||||
tm_wday=6, tm_yday=87, tm_isdst=-1
|
||||
)
|
||||
|
||||
# time
|
||||
>>> time.ctime()
|
||||
'Sun Mar 28 15:23:17 2021'
|
||||
>>> time.daylight
|
||||
1
|
||||
>>> time.gmtime()
|
||||
time.struct_time(
|
||||
tm_year=2021, tm_mon=3, tm_mday=28,
|
||||
tm_hour=14, tm_min=23, tm_sec=34,
|
||||
tm_wday=6, tm_yday=87, tm_isdst=0
|
||||
)
|
||||
>>> time.gmtime(0)
|
||||
time.struct_time(
|
||||
tm_year=1970, tm_mon=1, tm_mday=1,
|
||||
tm_hour=0, tm_min=0, tm_sec=0,
|
||||
tm_wday=3, tm_yday=1, tm_isdst=0
|
||||
)
|
||||
>>> time.localtime()
|
||||
time.struct_time(
|
||||
tm_year=2021, tm_mon=3, tm_mday=28,
|
||||
tm_hour=15, tm_min=23, tm_sec=50,
|
||||
tm_wday=6, tm_yday=87, tm_isdst=1
|
||||
)
|
||||
>>> time.time()
|
||||
1616941458.149149
|
||||
|
||||
|
||||
# datetime, timezones and tiemdeltas
|
||||
>>> now = datetime.now()
|
||||
>>> utcnow = datetime.utcnow()
|
||||
>>> now
|
||||
datetime.datetime(2021, 3, 28, 15, 25, 16, 258274)
|
||||
>>> utcnow
|
||||
datetime.datetime(2021, 3, 28, 14, 25, 22, 918195)
|
||||
>>> now.date()
|
||||
datetime.date(2021, 3, 28)
|
||||
>>> now.day, now.month, now.year
|
||||
(28, 3, 2021)
|
||||
>>> now.date() == date.today()
|
||||
True
|
||||
>>> now.time()
|
||||
datetime.time(15, 25, 16, 258274)
|
||||
>>> now.hour, now.minute, now.second, now.microsecond
|
||||
(15, 25, 16, 258274)
|
||||
>>> now.ctime()
|
||||
'Sun Mar 28 15:25:16 2021'
|
||||
>>> now.isoformat()
|
||||
'2021-03-28T15:25:16.258274'
|
||||
>>> now.timetuple()
|
||||
time.struct_time(
|
||||
tm_year=2021, tm_mon=3, tm_mday=28,
|
||||
tm_hour=15, tm_min=25, tm_sec=16,
|
||||
tm_wday=6, tm_yday=87, tm_isdst=-1
|
||||
)
|
||||
>>> now.tzinfo
|
||||
>>> utcnow.tzinfo
|
||||
>>> now.weekday()
|
||||
6
|
||||
>>> f_bday = datetime(
|
||||
1975, 12, 29, 12, 50, tzinfo=ZoneInfo('Europe/Rome')
|
||||
)
|
||||
>>> h_bday = datetime(
|
||||
1981, 10, 7, 15, 30, 50, tzinfo=timezone(timedelta(hours=2))
|
||||
)
|
||||
>>> diff = h_bday - f_bday
|
||||
>>> type(diff)
|
||||
<class 'datetime.timedelta'>
|
||||
>>> diff.days
|
||||
2109
|
||||
>>> diff.total_seconds()
|
||||
182223650.0
|
||||
>>> today + timedelta(days=49)
|
||||
datetime.date(2021, 5, 16)
|
||||
>>> now + timedelta(weeks=7)
|
||||
datetime.datetime(2021, 5, 16, 15, 25, 16, 258274)
|
||||
|
||||
|
||||
# parsing (stdlib)
|
||||
>>> datetime.fromisoformat('1977-11-24T19:30:13+01:00')
|
||||
datetime.datetime(
|
||||
1977, 11, 24, 19, 30, 13,
|
||||
tzinfo=datetime.timezone(datetime.timedelta(seconds=3600))
|
||||
)
|
||||
|
||||
>>> datetime.fromtimestamp(time.time())
|
||||
datetime.datetime(2021, 3, 28, 15, 42, 2, 142696)
|
||||
|
||||
>>> datetime.now()
|
||||
datetime.datetime(2021, 3, 28, 15, 42, 1, 120094)
|
||||
|
||||
|
||||
# arrow small demo
|
||||
>>> import arrow
|
||||
>>> arrow.utcnow()
|
||||
<Arrow [2021-03-28T14:43:20.017213+00:00]>
|
||||
>>> arrow.now()
|
||||
<Arrow [2021-03-28T15:43:39.370099+01:00]>
|
||||
|
||||
>>> local = arrow.now('Europe/Rome')
|
||||
>>> local
|
||||
<Arrow [2021-03-28T16:59:14.093960+02:00]>
|
||||
>>> local.to('utc')
|
||||
<Arrow [2021-03-28T14:59:14.093960+00:00]>
|
||||
>>> local.to('Europe/Moscow')
|
||||
<Arrow [2021-03-28T17:59:14.093960+03:00]>
|
||||
>>> local.to('Asia/Tokyo')
|
||||
<Arrow [2021-03-28T23:59:14.093960+09:00]>
|
||||
>>> local.datetime
|
||||
datetime.datetime(
|
||||
2021, 3, 28, 16, 59, 14, 93960,
|
||||
tzinfo=tzfile('/usr/share/zoneinfo/Europe/Rome')
|
||||
)
|
||||
>>> local.isoformat()
|
||||
'2021-03-28T16:59:14.093960+02:00'
|
||||
18
ch02/defaultdict.py
Normal file
18
ch02/defaultdict.py
Normal file
@ -0,0 +1,18 @@
|
||||
# defaultdict.py
|
||||
|
||||
|
||||
>>> d = {}
|
||||
>>> d['age'] = d.get('age', 0) + 1 # age not there, we get 0 + 1
|
||||
>>> d
|
||||
{'age': 1}
|
||||
>>> d = {'age': 39}
|
||||
>>> d['age'] = d.get('age', 0) + 1 # age is there, we get 40
|
||||
>>> d
|
||||
{'age': 40}
|
||||
|
||||
|
||||
>>> from collections import defaultdict
|
||||
>>> dd = defaultdict(int) # int is the default type (0 the value)
|
||||
>>> dd['age'] += 1 # short for dd['age'] = dd['age'] + 1
|
||||
>>> dd
|
||||
defaultdict(<class 'int'>, {'age': 1}) # 1, as expected
|
||||
123
ch02/dicts.py
Normal file
123
ch02/dicts.py
Normal file
@ -0,0 +1,123 @@
|
||||
# dicts.py
|
||||
|
||||
|
||||
>>> a = dict(A=1, Z=-1)
|
||||
>>> b = {'A': 1, 'Z': -1}
|
||||
>>> c = dict(zip(['A', 'Z'], [1, -1]))
|
||||
>>> d = dict([('A', 1), ('Z', -1)])
|
||||
>>> e = dict({'Z': -1, 'A': 1})
|
||||
>>> a == b == c == d == e # are they all the same?
|
||||
True # They are indeed
|
||||
|
||||
|
||||
# zip
|
||||
>>> list(zip(['h', 'e', 'l', 'l', 'o'], [1, 2, 3, 4, 5]))
|
||||
[('h', 1), ('e', 2), ('l', 3), ('l', 4), ('o', 5)]
|
||||
>>> list(zip('hello', range(1, 6))) # equivalent, more pythonic
|
||||
[('h', 1), ('e', 2), ('l', 3), ('l', 4), ('o', 5)]
|
||||
|
||||
|
||||
# basic
|
||||
>>> d = {}
|
||||
>>> d['a'] = 1 # let's set a couple of (key, value) pairs
|
||||
>>> d['b'] = 2
|
||||
>>> len(d) # how many pairs?
|
||||
2
|
||||
>>> d['a'] # what is the value of 'a'?
|
||||
1
|
||||
>>> d # how does `d` look now?
|
||||
{'a': 1, 'b': 2}
|
||||
>>> del d['a'] # let's remove `a`
|
||||
>>> d
|
||||
{'b': 2}
|
||||
>>> d['c'] = 3 # let's add 'c': 3
|
||||
>>> 'c' in d # membership is checked against the keys
|
||||
True
|
||||
>>> 3 in d # not the values
|
||||
False
|
||||
>>> 'e' in d
|
||||
False
|
||||
>>> d.clear() # let's clean everything from this dictionary
|
||||
>>> d
|
||||
{}
|
||||
|
||||
|
||||
|
||||
# views
|
||||
>>> d = dict(zip('hello', range(5)))
|
||||
>>> d
|
||||
{'h': 0, 'e': 1, 'l': 3, 'o': 4}
|
||||
>>> d.keys()
|
||||
dict_keys(['h', 'e', 'l', 'o'])
|
||||
>>> d.values()
|
||||
dict_values([0, 1, 3, 4])
|
||||
>>> d.items()
|
||||
dict_items([('h', 0), ('e', 1), ('l', 3), ('o', 4)])
|
||||
>>> 3 in d.values()
|
||||
True
|
||||
>>> ('o', 4) in d.items()
|
||||
True
|
||||
|
||||
|
||||
# other methods
|
||||
>>> d
|
||||
{'h': 0, 'e': 1, 'l': 3, 'o': 4}
|
||||
>>> d.popitem() # removes a random item (useful in algorithms)
|
||||
('o', 4)
|
||||
>>> d
|
||||
{'h': 0, 'e': 1, 'l': 3}
|
||||
>>> d.pop('l') # remove item with key `l`
|
||||
3
|
||||
>>> d.pop('not-a-key') # remove a key not in dictionary: KeyError
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 1, in <module>
|
||||
KeyError: 'not-a-key'
|
||||
>>> d.pop('not-a-key', 'default-value') # with a default value?
|
||||
'default-value' # we get the default value
|
||||
>>> d.update({'another': 'value'}) # we can update dict this way
|
||||
>>> d.update(a=13) # or this way (like a function call)
|
||||
>>> d
|
||||
{'h': 0, 'e': 1, 'another': 'value', 'a': 13}
|
||||
>>> d.get('a') # same as d['a'] but if key is missing no KeyError
|
||||
13
|
||||
>>> d.get('a', 177) # default value used if key is missing
|
||||
13
|
||||
>>> d.get('b', 177) # like in this case
|
||||
177
|
||||
>>> d.get('b') # key is not there, so None is returned
|
||||
|
||||
|
||||
# setdefault
|
||||
>>> d = {}
|
||||
>>> d.setdefault('a', 1) # 'a' is missing, we get default value
|
||||
1
|
||||
>>> d
|
||||
{'a': 1} # also, the key/value pair ('a', 1) has now been added
|
||||
>>> d.setdefault('a', 5) # let's try to override the value
|
||||
1
|
||||
>>> d
|
||||
{'a': 1} # no override, as expected
|
||||
|
||||
|
||||
# setdefault example
|
||||
>>> d = {}
|
||||
>>> d.setdefault('a', {}).setdefault('b', []).append(1)
|
||||
>>> d
|
||||
{'a': {'b': [1]}}
|
||||
|
||||
|
||||
# union
|
||||
>>> d = {'a': 'A', 'b': 'B'}
|
||||
>>> e = {'b': 8, 'c': 'C'}
|
||||
>>> d | e
|
||||
{'a': 'A', 'b': 8, 'c': 'C'}
|
||||
>>> e | d
|
||||
{'b': 'B', 'c': 'C', 'a': 'A'}
|
||||
>>> {**d, **e}
|
||||
{'a': 'A', 'b': 8, 'c': 'C'}
|
||||
>>> {**e, **d}
|
||||
{'b': 'B', 'c': 'C', 'a': 'A'}
|
||||
|
||||
>>> d |= e
|
||||
>>> d
|
||||
{'a': 'A', 'b': 8, 'c': 'C'}
|
||||
26
ch02/enum.py
Normal file
26
ch02/enum.py
Normal file
@ -0,0 +1,26 @@
|
||||
>>> GREEN = 1
|
||||
>>> YELLOW = 2
|
||||
>>> RED = 4
|
||||
>>> TRAFFIC_LIGHTS = (GREEN, YELLOW, RED)
|
||||
>>> # or with a dict
|
||||
>>> traffic_lights = {'GREEN': 1, 'YELLOW': 2, 'RED': 4}
|
||||
|
||||
|
||||
|
||||
# using enum
|
||||
>>> from enum import Enum
|
||||
>>> class TrafficLight(Enum):
|
||||
... GREEN = 1
|
||||
... YELLOW = 2
|
||||
... RED = 4
|
||||
...
|
||||
>>> TrafficLight.GREEN
|
||||
<TrafficLight.GREEN: 1>
|
||||
>>> TrafficLight.GREEN.name
|
||||
'GREEN'
|
||||
>>> TrafficLight.GREEN.value
|
||||
1
|
||||
>>> TrafficLight(1)
|
||||
<TrafficLight.GREEN: 1>
|
||||
>>> TrafficLight(4)
|
||||
<TrafficLight.RED: 4>
|
||||
46
ch02/final_considerations.py
Normal file
46
ch02/final_considerations.py
Normal file
@ -0,0 +1,46 @@
|
||||
# final_considerations.py
|
||||
|
||||
|
||||
>>> a = 1000000
|
||||
>>> b = 1000000
|
||||
>>> id(a) == id(b)
|
||||
False
|
||||
|
||||
|
||||
>>> a = 5
|
||||
>>> b = 5
|
||||
>>> id(a) == id(b)
|
||||
True
|
||||
|
||||
|
||||
# how to choose data structures
|
||||
# example customer objects
|
||||
customer1 = {'id': 'abc123', 'full_name': 'Master Yoda'}
|
||||
customer2 = {'id': 'def456', 'full_name': 'Obi-Wan Kenobi'}
|
||||
customer3 = {'id': 'ghi789', 'full_name': 'Anakin Skywalker'}
|
||||
# collect them in a tuple
|
||||
customers = (customer1, customer2, customer3)
|
||||
# or collect them in a list
|
||||
customers = [customer1, customer2, customer3]
|
||||
# or maybe within a dictionary, they have a unique id after all
|
||||
customers = {
|
||||
'abc123': customer1,
|
||||
'def456': customer2,
|
||||
'ghi789': customer3,
|
||||
}
|
||||
|
||||
|
||||
# negative indexing
|
||||
>>> a = list(range(10)) # `a` has 10 elements. Last one is 9.
|
||||
>>> a
|
||||
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
>>> len(a) # its length is 10 elements
|
||||
10
|
||||
>>> a[len(a) - 1] # position of last one is len(a) - 1
|
||||
9
|
||||
>>> a[-1] # but we don't need len(a)! Python rocks!
|
||||
9
|
||||
>>> a[-2] # equivalent to len(a) - 2
|
||||
8
|
||||
>>> a[-3] # equivalent to len(a) - 3
|
||||
7
|
||||
101
ch02/lists.py
Normal file
101
ch02/lists.py
Normal file
@ -0,0 +1,101 @@
|
||||
# lists.py
|
||||
|
||||
|
||||
# creation
|
||||
>>> [] # empty list
|
||||
[]
|
||||
>>> list() # same as []
|
||||
[]
|
||||
>>> [1, 2, 3] # as with tuples, items are comma separated
|
||||
[1, 2, 3]
|
||||
>>> [x + 5 for x in [2, 3, 4]] # Python is magic
|
||||
[7, 8, 9]
|
||||
>>> list((1, 3, 5, 7, 9)) # list from a tuple
|
||||
[1, 3, 5, 7, 9]
|
||||
>>> list('hello') # list from a string
|
||||
['h', 'e', 'l', 'l', 'o']
|
||||
|
||||
|
||||
# main methods
|
||||
>>> a = [1, 2, 1, 3]
|
||||
>>> a.append(13) # we can append anything at the end
|
||||
>>> a
|
||||
[1, 2, 1, 3, 13]
|
||||
>>> a.count(1) # how many `1` are there in the list?
|
||||
2
|
||||
>>> a.extend([5, 7]) # extend the list by another (or sequence)
|
||||
>>> a
|
||||
[1, 2, 1, 3, 13, 5, 7]
|
||||
>>> a.index(13) # position of `13` in the list (0-based indexing)
|
||||
4
|
||||
>>> a.insert(0, 17) # insert `17` at position 0
|
||||
>>> a
|
||||
[17, 1, 2, 1, 3, 13, 5, 7]
|
||||
>>> a.pop() # pop (remove and return) last element
|
||||
7
|
||||
>>> a.pop(3) # pop element at position 3
|
||||
1
|
||||
>>> a
|
||||
[17, 1, 2, 3, 13, 5]
|
||||
>>> a.remove(17) # remove `17` from the list
|
||||
>>> a
|
||||
[1, 2, 3, 13, 5]
|
||||
>>> a.reverse() # reverse the order of the elements in the list
|
||||
>>> a
|
||||
[5, 13, 3, 2, 1]
|
||||
>>> a.sort() # sort the list
|
||||
>>> a
|
||||
[1, 2, 3, 5, 13]
|
||||
>>> a.clear() # remove all elements from the list
|
||||
>>> a
|
||||
[]
|
||||
|
||||
|
||||
# extending
|
||||
>>> a = list('hello') # makes a list from a string
|
||||
>>> a
|
||||
['h', 'e', 'l', 'l', 'o']
|
||||
>>> a.append(100) # append 100, heterogeneous type
|
||||
>>> a
|
||||
['h', 'e', 'l', 'l', 'o', 100]
|
||||
>>> a.extend((1, 2, 3)) # extend using tuple
|
||||
>>> a
|
||||
['h', 'e', 'l', 'l', 'o', 100, 1, 2, 3]
|
||||
>>> a.extend('...') # extend using string
|
||||
>>> a
|
||||
['h', 'e', 'l', 'l', 'o', 100, 1, 2, 3, '.', '.', '.']
|
||||
|
||||
|
||||
# most common operations
|
||||
>>> a = [1, 3, 5, 7]
|
||||
>>> min(a) # minimum value in the list
|
||||
1
|
||||
>>> max(a) # maximum value in the list
|
||||
7
|
||||
>>> sum(a) # sum of all values in the list
|
||||
16
|
||||
>>> from math import prod
|
||||
>>> prod(a) # product of all values in the list
|
||||
105
|
||||
>>> len(a) # number of elements in the list
|
||||
4
|
||||
>>> b = [6, 7, 8]
|
||||
>>> a + b # `+` with list means concatenation
|
||||
[1, 3, 5, 7, 6, 7, 8]
|
||||
>>> a * 2 # `*` has also a special meaning
|
||||
[1, 3, 5, 7, 1, 3, 5, 7]
|
||||
|
||||
|
||||
# cool sorting
|
||||
>>> from operator import itemgetter
|
||||
>>> a = [(5, 3), (1, 3), (1, 2), (2, -1), (4, 9)]
|
||||
>>> sorted(a)
|
||||
[(1, 2), (1, 3), (2, -1), (4, 9), (5, 3)]
|
||||
>>> sorted(a, key=itemgetter(0))
|
||||
[(1, 3), (1, 2), (2, -1), (4, 9), (5, 3)]
|
||||
>>> sorted(a, key=itemgetter(0, 1))
|
||||
[(1, 2), (1, 3), (2, -1), (4, 9), (5, 3)]
|
||||
>>> sorted(a, key=itemgetter(1))
|
||||
[(2, -1), (1, 2), (5, 3), (1, 3), (4, 9)]
|
||||
>>> sorted(a, key=itemgetter(1), reverse=True)
|
||||
[(4, 9), (5, 3), (1, 3), (1, 2), (2, -1)]
|
||||
34
ch02/namedtuple.py
Normal file
34
ch02/namedtuple.py
Normal file
@ -0,0 +1,34 @@
|
||||
# namedtuple.py
|
||||
|
||||
|
||||
# the problem
|
||||
>>> vision = (9.5, 8.8)
|
||||
>>> vision
|
||||
(9.5, 8.8)
|
||||
>>> vision[0] # left eye (implicit positional reference)
|
||||
9.5
|
||||
>>> vision[1] # right eye (implicit positional reference)
|
||||
8.8
|
||||
|
||||
|
||||
# the solution
|
||||
>>> from collections import namedtuple
|
||||
>>> Vision = namedtuple('Vision', ['left', 'right'])
|
||||
>>> vision = Vision(9.5, 8.8)
|
||||
>>> vision[0]
|
||||
9.5
|
||||
>>> vision.left # same as vision[0], but explicit
|
||||
9.5
|
||||
>>> vision.right # same as vision[1], but explicit
|
||||
8.8
|
||||
|
||||
|
||||
# the change
|
||||
>>> Vision = namedtuple('Vision', ['left', 'combined', 'right'])
|
||||
>>> vision = Vision(9.5, 9.2, 8.8)
|
||||
>>> vision.left # still correct
|
||||
9.5
|
||||
>>> vision.right # still correct (though now is vision[2])
|
||||
8.8
|
||||
>>> vision.combined # the new vision[1]
|
||||
9.2
|
||||
180
ch02/numbers.py
Normal file
180
ch02/numbers.py
Normal file
@ -0,0 +1,180 @@
|
||||
# numbers.py
|
||||
|
||||
|
||||
# integers
|
||||
>>> a = 14
|
||||
>>> b = 3
|
||||
>>> a + b # addition
|
||||
17
|
||||
>>> a - b # subtraction
|
||||
11
|
||||
>>> a * b # multiplication
|
||||
42
|
||||
>>> a / b # true division
|
||||
4.666666666666667
|
||||
>>> a // b # integer division
|
||||
4
|
||||
>>> a % b # modulo operation (reminder of division)
|
||||
2
|
||||
>>> a ** b # power operation
|
||||
2744
|
||||
|
||||
>>> from math import pow
|
||||
|
||||
>>> pow(10, 3)
|
||||
1000
|
||||
>>> 10 ** 3
|
||||
1000
|
||||
>>> pow(10, -3)
|
||||
0.001
|
||||
>>> 10 ** -3
|
||||
0.001
|
||||
|
||||
|
||||
>>> pow(123, 4)
|
||||
228886641
|
||||
>>> pow(123, 4, 100)
|
||||
41 # notice: 228886641 % 100 == 41
|
||||
>>> pow(37, -1, 43) # modular inverse of 37 mod 43
|
||||
7
|
||||
>>> 7 * 37 % 43 # proof the above is correct
|
||||
1
|
||||
|
||||
|
||||
|
||||
# integer and true division
|
||||
>>> 7 / 4 # true division
|
||||
1.75
|
||||
>>> 7 // 4 # integer division, truncation returns 1
|
||||
1
|
||||
>>> -7 / 4 # true division again, result is opposite of previous
|
||||
-1.75
|
||||
>>> -7 // 4 # integer div., result not the opposite of previous
|
||||
-2
|
||||
|
||||
# modulo operator
|
||||
>>> 10 % 3 # remainder of the division 10 // 3
|
||||
1
|
||||
>>> 10 % 4 # remainder of the division 10 // 4
|
||||
2
|
||||
|
||||
|
||||
# truncation towards 0
|
||||
>>> int(1.75)
|
||||
1
|
||||
>>> int(-1.75)
|
||||
-1
|
||||
|
||||
# creating ints
|
||||
>>> int('10110', base=2)
|
||||
22
|
||||
|
||||
|
||||
# underscored
|
||||
>>> n = 1_024
|
||||
>>> n
|
||||
1024
|
||||
>>> hex_n = 0x_4_0_0 # 0x400 == 1024
|
||||
>>> hex_n
|
||||
1024
|
||||
|
||||
|
||||
# booleans
|
||||
>>> int(True) # True behaves like 1
|
||||
1
|
||||
>>> int(False) # False behaves like 0
|
||||
0
|
||||
>>> bool(1) # 1 evaluates to True in a boolean context
|
||||
True
|
||||
>>> bool(-42) # and so does every non-zero number
|
||||
True
|
||||
>>> bool(0) # 0 evaluates to False
|
||||
False
|
||||
>>> # quick peak at the operators (and, or, not)
|
||||
>>> not True
|
||||
False
|
||||
>>> not False
|
||||
True
|
||||
>>> True and True
|
||||
True
|
||||
>>> False or True
|
||||
True
|
||||
|
||||
|
||||
# int and bool
|
||||
>>> 1 + True
|
||||
2
|
||||
>>> False + 42
|
||||
42
|
||||
>>> 7 - True
|
||||
6
|
||||
|
||||
|
||||
# reals
|
||||
>>> pi = 3.1415926536 # how many digits of PI can you remember?
|
||||
>>> radius = 4.5
|
||||
>>> area = pi * (radius ** 2)
|
||||
>>> area
|
||||
63.617251235400005
|
||||
|
||||
|
||||
# sys.float_info
|
||||
>>> import sys
|
||||
>>> sys.float_info
|
||||
sys.float_info(
|
||||
max=1.7976931348623157e+308, max_exp=1024, max_10_exp=308,
|
||||
min=2.2250738585072014e-308, min_exp=-1021, min_10_exp=-307,
|
||||
dig=15, mant_dig=53, epsilon=2.220446049250313e-16, radix=2,
|
||||
rounds=1
|
||||
)
|
||||
|
||||
# approximation issue
|
||||
>>> 0.3 - 0.1 * 3 # this should be 0!!!
|
||||
-5.551115123125783e-17
|
||||
|
||||
|
||||
# complex
|
||||
>>> c = 3.14 + 2.73j
|
||||
>>> c = complex(3.14, 2.73) # same as above
|
||||
>>> c.real # real part
|
||||
3.14
|
||||
>>> c.imag # imaginary part
|
||||
2.73
|
||||
>>> c.conjugate() # conjugate of A + Bj is A - Bj
|
||||
(3.14-2.73j)
|
||||
>>> c * 2 # multiplication is allowed
|
||||
(6.28+5.46j)
|
||||
>>> c ** 2 # power operation as well
|
||||
(2.4067000000000007+17.1444j)
|
||||
>>> d = 1 + 1j # addition and subtraction as well
|
||||
>>> c - d
|
||||
(2.14+1.73j)
|
||||
|
||||
|
||||
# fractions
|
||||
>>> from fractions import Fraction
|
||||
>>> Fraction(10, 6) # mad hatter?
|
||||
Fraction(5, 3) # notice it's been simplified
|
||||
>>> Fraction(1, 3) + Fraction(2, 3) # 1/3 + 2/3 == 3/3 == 1/1
|
||||
Fraction(1, 1)
|
||||
>>> f = Fraction(10, 6)
|
||||
>>> f.numerator
|
||||
5
|
||||
>>> f.denominator
|
||||
3
|
||||
>>> f.as_integer_ratio()
|
||||
(5, 3)
|
||||
|
||||
|
||||
# decimal
|
||||
>>> from decimal import Decimal as D # rename for brevity
|
||||
>>> D(3.14) # pi, from float, so approximation issues
|
||||
Decimal('3.140000000000000124344978758017532527446746826171875')
|
||||
>>> D('3.14') # pi, from a string, so no approximation issues
|
||||
Decimal('3.14')
|
||||
>>> D(0.1) * D(3) - D(0.3) # from float, we still have the issue
|
||||
Decimal('2.775557561565156540423631668E-17')
|
||||
>>> D('0.1') * D(3) - D('0.3') # from string, all perfect
|
||||
Decimal('0.0')
|
||||
>>> D('1.4').as_integer_ratio() # 7/5 = 1.4 (isn't this cool?!)
|
||||
(7, 5)
|
||||
37
ch02/objects.py
Normal file
37
ch02/objects.py
Normal file
@ -0,0 +1,37 @@
|
||||
# objects.py
|
||||
|
||||
# code block # 1
|
||||
>>> age = 42
|
||||
>>> age
|
||||
42
|
||||
>>> age = 43 #A
|
||||
>>> age
|
||||
43
|
||||
|
||||
|
||||
# code block # 2
|
||||
>>> age = 42
|
||||
>>> id(age)
|
||||
4377553168
|
||||
>>> age = 43
|
||||
>>> id(age)
|
||||
4377553200
|
||||
|
||||
|
||||
# code block # 3
|
||||
>>> class Person:
|
||||
... def __init__(self, age):
|
||||
... self.age = age
|
||||
...
|
||||
>>> fab = Person(age=42)
|
||||
>>> fab.age
|
||||
42
|
||||
>>> id(fab)
|
||||
4380878496
|
||||
>>> id(fab.age)
|
||||
4377553168
|
||||
>>> fab.age = 25 # I wish!
|
||||
>>> id(fab) # will be the same
|
||||
4380878496
|
||||
>>> id(fab.age) # will be different
|
||||
4377552624
|
||||
1
ch02/requirements/main.in
Normal file
1
ch02/requirements/main.in
Normal file
@ -0,0 +1 @@
|
||||
arrow
|
||||
12
ch02/requirements/main.txt
Normal file
12
ch02/requirements/main.txt
Normal file
@ -0,0 +1,12 @@
|
||||
#
|
||||
# This file is autogenerated by pip-compile
|
||||
# To update, run:
|
||||
#
|
||||
# pip-compile main.in
|
||||
#
|
||||
arrow==1.0.3
|
||||
# via -r main.in
|
||||
python-dateutil==2.8.1
|
||||
# via arrow
|
||||
six==1.15.0
|
||||
# via python-dateutil
|
||||
103
ch02/sequences.py
Normal file
103
ch02/sequences.py
Normal file
@ -0,0 +1,103 @@
|
||||
# sequences.py
|
||||
|
||||
|
||||
# strings
|
||||
>>> # 4 ways to make a string
|
||||
>>> str1 = 'This is a string. We built it with single quotes.'
|
||||
>>> str2 = "This is also a string, but built with double quotes."
|
||||
>>> str3 = '''This is built using triple quotes,
|
||||
... so it can span multiple lines.'''
|
||||
>>> str4 = """This too
|
||||
... is a multiline one
|
||||
... built with triple double-quotes."""
|
||||
>>> str4 #A
|
||||
'This too\nis a multiline one\nbuilt with triple double-quotes.'
|
||||
>>> print(str4) #B
|
||||
This too
|
||||
is a multiline one
|
||||
built with triple double-quotes.
|
||||
|
||||
>>> s = 'Hello There'
|
||||
>>> s.removeprefix('Hell')
|
||||
'o There'
|
||||
>>> s.removesuffix('here')
|
||||
'Hello T'
|
||||
>>> s.removeprefix('Ooops')
|
||||
'Hello There'
|
||||
|
||||
|
||||
# encode / decode
|
||||
>>> s = "This is üŋíc0de" # unicode string: code points
|
||||
>>> type(s)
|
||||
<class 'str'>
|
||||
>>> encoded_s = s.encode('utf-8') # utf-8 encoded version of s
|
||||
>>> encoded_s
|
||||
b'This is \xc3\xbc\xc5\x8b\xc3\xadc0de' # result: bytes object
|
||||
>>> type(encoded_s) # another way to verify it
|
||||
<class 'bytes'>
|
||||
>>> encoded_s.decode('utf-8') # let's revert to the original
|
||||
'This is üŋíc0de'
|
||||
>>> bytes_obj = b"A bytes object" # a bytes object
|
||||
>>> type(bytes_obj)
|
||||
<class 'bytes'>
|
||||
|
||||
|
||||
# length
|
||||
>>> len(str1)
|
||||
49
|
||||
|
||||
|
||||
# indexing and slicing
|
||||
>>> s = "The trouble is you think you have time."
|
||||
>>> s[0] # indexing at position 0, which is the first char
|
||||
'T'
|
||||
>>> s[5] # indexing at position 5, which is the sixth char
|
||||
'r'
|
||||
>>> s[:4] # slicing, we specify only the stop position
|
||||
'The '
|
||||
>>> s[4:] # slicing, we specify only the start position
|
||||
'trouble is you think you have time.'
|
||||
>>> s[2:14] # slicing, both start and stop positions
|
||||
'e trouble is'
|
||||
>>> s[2:14:3] # slicing, start, stop and step (every 3 chars)
|
||||
'erb '
|
||||
>>> s[:] # quick way of making a copy
|
||||
'The trouble is you think you have time.'
|
||||
|
||||
|
||||
# formatting
|
||||
>>> greet_old = 'Hello %s!'
|
||||
>>> greet_old % 'Fabrizio'
|
||||
'Hello Fabrizio!'
|
||||
>>> greet_positional = 'Hello {}!'
|
||||
>>> greet_positional.format('Fabrizio')
|
||||
'Hello Fabrizio!'
|
||||
>>> greet_positional = 'Hello {} {}!'
|
||||
>>> greet_positional.format('Fabrizio', 'Romano')
|
||||
'Hello Fabrizio Romano!'
|
||||
>>> greet_positional_idx = 'This is {0}! {1} loves {0}!'
|
||||
>>> greet_positional_idx.format('Python', 'Heinrich')
|
||||
'This is Python! Heinrich loves Python!'
|
||||
>>> greet_positional_idx.format('Coffee', 'Fab')
|
||||
'This is Coffee! Fab loves Coffee!'
|
||||
>>> keyword = 'Hello, my name is {name} {last_name}'
|
||||
>>> keyword.format(name='Fabrizio', last_name='Romano')
|
||||
'Hello, my name is Fabrizio Romano'
|
||||
|
||||
|
||||
# formatted string literals
|
||||
>>> name = 'Fab'
|
||||
>>> age = 42
|
||||
>>> f"Hello! My name is {name} and I'm {age}"
|
||||
"Hello! My name is Fab and I'm 42"
|
||||
>>> from math import pi
|
||||
>>> f"No arguing with {pi}, it's irrational..."
|
||||
"No arguing with 3.141592653589793, it's irrational..."
|
||||
|
||||
# f-string debug
|
||||
>>> user = 'heinrich'
|
||||
>>> password = 'super-secret'
|
||||
>>> f"Log in with: {user} and {password}"
|
||||
'Log in with: heinrich and super-secret'
|
||||
>>> f"Log in with: {user=} and {password=}"
|
||||
"Log in with: user='heinrich' and password='super-secret'"
|
||||
51
ch02/sets.py
Normal file
51
ch02/sets.py
Normal file
@ -0,0 +1,51 @@
|
||||
# sets.py
|
||||
|
||||
|
||||
>>> small_primes = set() # empty set
|
||||
>>> small_primes.add(2) # adding one element at a time
|
||||
>>> small_primes.add(3)
|
||||
>>> small_primes.add(5)
|
||||
>>> small_primes
|
||||
{2, 3, 5}
|
||||
>>> small_primes.add(1) # Look what I've done, 1 is not a prime!
|
||||
>>> small_primes
|
||||
{1, 2, 3, 5}
|
||||
>>> small_primes.remove(1) # so let's remove it
|
||||
>>> 3 in small_primes # membership test
|
||||
True
|
||||
>>> 4 in small_primes
|
||||
False
|
||||
>>> 4 not in small_primes # negated membership test
|
||||
True
|
||||
>>> small_primes.add(3) # trying to add 3 again
|
||||
>>> small_primes
|
||||
{2, 3, 5} # no change, duplication is not allowed
|
||||
>>> bigger_primes = set([5, 7, 11, 13]) # faster creation
|
||||
>>> small_primes | bigger_primes # union operator `|`
|
||||
{2, 3, 5, 7, 11, 13}
|
||||
>>> small_primes & bigger_primes # intersection operator `&`
|
||||
{5}
|
||||
>>> small_primes - bigger_primes # difference operator `-`
|
||||
{2, 3}
|
||||
|
||||
|
||||
>>> small_primes = {2, 3, 5, 5, 3}
|
||||
>>> small_primes
|
||||
{2, 3, 5}
|
||||
|
||||
|
||||
|
||||
|
||||
# frozenset
|
||||
>>> small_primes = frozenset([2, 3, 5, 7])
|
||||
>>> bigger_primes = frozenset([5, 7, 11])
|
||||
>>> small_primes.add(11) # we cannot add to a frozenset
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 1, in <module>
|
||||
AttributeError: 'frozenset' object has no attribute 'add'
|
||||
>>> small_primes.remove(2) # neither we can remove
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 1, in <module>
|
||||
AttributeError: 'frozenset' object has no attribute 'remove'
|
||||
>>> small_primes & bigger_primes # intersect, union, etc. allowed
|
||||
frozenset({5, 7})
|
||||
29
ch02/tuples.py
Normal file
29
ch02/tuples.py
Normal file
@ -0,0 +1,29 @@
|
||||
# tuples.py
|
||||
|
||||
|
||||
>>> t = () # empty tuple
|
||||
>>> type(t)
|
||||
<class 'tuple'>
|
||||
>>> one_element_tuple = (42, ) # you need the comma!
|
||||
>>> three_elements_tuple = (1, 3, 5) # braces are optional here
|
||||
>>> a, b, c = 1, 2, 3 # tuple for multiple assignment
|
||||
>>> a, b, c # implicit tuple to print with one instruction
|
||||
(1, 2, 3)
|
||||
>>> 3 in three_elements_tuple # membership test
|
||||
True
|
||||
|
||||
|
||||
# swap
|
||||
>>> a, b = 1, 2
|
||||
>>> c = a # we need three lines and a temporary var c
|
||||
>>> a = b
|
||||
>>> b = c
|
||||
>>> a, b # a and b have been swapped
|
||||
(2, 1)
|
||||
|
||||
|
||||
# pythonic swap
|
||||
>>> a, b = 0, 1
|
||||
>>> a, b = b, a # this is the Pythonic way to do it
|
||||
>>> a, b
|
||||
(1, 0)
|
||||
Loading…
x
Reference in New Issue
Block a user