name = "Sabine"
print("My name is %s." % name)
My name is Sabine.
print("My name is {}.".format(name))
My name is Sabine.
name = "Sabine"
print(f"My name is {name}.")
My name is Sabine.
import decimal
width = 10
precision = 4
value = decimal.Decimal("12.34567")
f"result: {value:{width}.{precision}}" # nested fields
'result: 12.35'
hundred_million = 100_000_000
hundred_million
100000000
Image(filename="images/flask.png")
import os
os.urandom(24)
b'\xc9\x19C7\xb3\x8e.\xb7f\xd42\xa6\x85t\x86\xe0,\xc16\x19\xfb\x99\xe0n'
import secrets
secrets.token_bytes(32)
b'\x16\x1f\xe8H,e\x8ar*\xb1\x8d\x7f\x00U\xc5E\x844\xa0\xc8F\x08\x16\xc49\xcd5\x11\x191\r\xd3'
Always use the secrets module for cryptographical secure identifiers!
# always produces the same sequence 9, 0, 6
import random
random.seed(10)
x = random.randint(0, 9)
y = random.randint(0, 9)
z = random.randint(0, 9)
print(x, y, z)
9 0 6
import os
path = '/usr/lib'
type(path)
str
os.path.dirname(path)
'/usr'
Image(filename="images/path.png")
import pathlib
pathobject = pathlib.Path('/usr/lib')
type(pathobject)
pathlib.PosixPath
os.path.dirname(pathobject)
'/usr'
Image(filename="images/asyncio.png")
async def ticker(delay, to):
for i in range(to):
yield i
await asyncio.sleep(delay)
async def run():
starttime = datetime.datetime.now()
print(f"Start at second {starttime.second}")
async for i in ticker(5, 10):
outputtime = datetime.datetime.now()
print(f"output: {i} at second: {outputtime.second}")
import asyncio
import datetime
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(run())
finally:
loop.close()
Start at second 53 output: 0 at second: 53 output: 1 at second: 58 output: 2 at second: 3 output: 3 at second: 8 output: 4 at second: 13 output: 5 at second: 18 output: 6 at second: 23 output: 7 at second: 28 output: 8 at second: 33 output: 9 at second: 38
Image(filename="images/Type_hints.png")
def add(x: int, y:int):
return x + y
add(3,4)
7
add.__annotations__
{'x': int, 'y': int}
Type annotations are now possible everywhere!
from typing import List, Dict
primes: List[int] = []
captain: str # Note: no initial value!
class Starship:
stats: Dict[str, int] = {}
s = Starship()
s.__annotations__
{'stats': typing.Dict[str, int]}
def orderpreserved(**kwargs):
print(list(kwargs.keys()))
orderpreserved(c=1,b=2,a=3)
['c', 'b', 'a']
class OrderPreserved:
c = 1
b = 2
def a(self):
pass
list(OrderPreserved.__dict__.keys())
['__module__', 'c', 'b', 'a', '__dict__', '__weakref__', '__doc__']
Version | DictSize | Dict Ordering |
---|---|---|
Python 2.7 | 280,280,280 | Scrambled (predictable) |
Python 3.5 | 196,196,196 | Randomized (unpredictable): key-sharing dictionary |
Python 3.6 | 112,112,112 | Ordered |
Image(filename="images/pydict.png")
Image(filename="images/hashed_dicts.png")
Image(filename="images/old_dict2.png")
entries = \
[[--, '--', --],
[..001, 'ftp', 21],
[--, '--', --],
[--, '--', --],
[..100, 'smtp', 25],
[..101, 'ssh', 22],
[--, '--', --],
[--, '--', --],
]
entries = \
[[..100, 'smtp', 25],
[..001, 'ftp', 21],
[..101, 'ssh', 22],
]
indices = [None, 1, None, None, 0, 2, None, None]
Image(filename="images/combined_dict.png")
class Superclass(object):
def __init__(self):
print('Do something in the Superclass')
class Subclass(Superclass):
def __init__(self):
super().__init__()
print('Do something in the Subclass')
Subclass()
Do something in the Superclass Do something in the Subclass
<__main__.Subclass at 0x10493c978>
class Superclass(object):
def __init_subclass__(cls, whom, **kwargs):
print(f'Do something with {whom}')
cls.hello = lambda: print(f"Hello from {whom}!")
class MySubclass(Superclass, whom="MySubclass"):
pass
MySubclass.hello()
Do something with MySubclass Hello from MySubclass!
class Stock:
def __init__(self, name, shares, price):
self.name = name
self.shares = shares
self.price = price
s = Stock('GOOG', 10, 25.50)
print(s.name, s.shares, s.price)
GOOG 10 25.5
class Structure:
_fields = []
def __init__(self, *args):
for name, val in zip(self._fields, args):
setattr(self, name, val)
class Stock(Structure):
_fields = ['name', 'shares', 'price']
s = Stock('GOOG', 10, 25.50)
print(s.name, s.shares, s.price)
GOOG 10 25.5
This trick, that messed up the class: no signature, no keyword arguments, no help!
from inspect import Parameter, Signature
def make_signature(names):
return Signature(
Parameter(name, Parameter.POSITIONAL_OR_KEYWORD) for name in names)
class Structure:
__signature__ = make_signature([])
def __init__(self, *args, **kwargs):
bound = self.__signature__.bind(*args, **kwargs)
for name, val in bound.arguments.items():
setattr(self, name, val)
class Stock(Structure):
__signature__ = make_signature(['name', 'shares', 'price'])
s = Stock('GOOG', 10, 25.50)
print(s.name, s.shares, s.price)
GOOG 10 25.5
class StructMeta(type):
def __new__(cls, name, bases, clsdict):
clsobj = super().__new__(cls, name, bases, clsdict)
sig = make_signature(clsobj._fields)
setattr(clsobj, '__signature__', sig)
return clsobj
class Structure(metaclass=StructMeta):
_fields = []
def __init__(self, *args, **kwargs):
bound = self.__signature__.bind(*args, **kwargs)
for name, val in bound.arguments.items():
setattr(self, name, val)
class Stock(Structure):
_fields = ['name', 'shares', 'price']
s = Stock('GOOG', 10, 25.50)
print(s.name, s.shares, s.price)
GOOG 10 25.5
class Structure:
def __init_subclass__(cls, _fields):
sig = make_signature(_fields)
setattr(cls, '__signature__', sig)
def __init__(self, *args, **kwargs):
bound = self.__signature__.bind(*args, **kwargs)
for name, val in bound.arguments.items():
setattr(self, name, val)
class Stock(Structure, _fields=['name', 'shares', 'price']):
pass
s = Stock('GOOG', 10, 25.50)
print(s.name, s.shares, s.price)
GOOG 10 25.5
s = Stock(name='MICROSOFT', price=100, shares=20)
print(s.name, s.shares, s.price)
MICROSOFT 20 100
The tutorial is a lot longer and has a lot more magic with descriptors
__set_name__
class Descriptor:
def __init__(self, minimum, maximum):
self.minimum = minimum
self.maximum = maximum
def __get__(self, instance, owner):
return instance.__dict__[self.key]
def __set__(self, instance, value):
if self.minimum < value < self.maximum:
instance.__dict__[self.key] = value
else:
raise ValueError("value not in range")
def __set_name__(self, owner, name):
self.key = name
import datetime
dt1 = datetime.datetime(2016, 10, 30, 2, 30)
dt1.astimezone().strftime('%D %T %Z%z')
'10/30/16 02:30:00 CEST+0200'
dt2 = datetime.datetime(2016, 10, 30, 2, 30, fold=1)
dt2.astimezone().strftime('%D %T %Z%z')
'10/30/16 02:30:00 CET+0100'
dt2 - dt1
datetime.timedelta(0)
(Read-Eval-Print-Loop)