wefree 2023. 8. 20. 18:58

https://betterprogramming.pub/87-lesser-known-python-features-635180720a29

 

87 Lesser-known Python Features

This post is for people who use Python daily, but have never actually sat down and read through all the documentation.

betterprogramming.pub

 

str.endswith(), isinstance() take a tuple 

if filename.endswith((".csv", ".xls", ".xlsx"))
  # Do something spreadsheety
  
assert isinstance(7, (float, int))
assert isinstance(7, float | int)

 

Create a dict from tuples

keys = ["a", "b", "c"]
vals = [1, 2, 3]

assert dict(zip(keys, vals)) == {'a': 1, 'b': 2, 'c': 3}

 

Use ‘or’ to set defaults

def make_list(start_list: list = None):
    start_list = start_list or []
    ...

# def make_list(start_list: list = None):
#     if start_list is None:
#         start_list = []
#     ...

 

Format a number

pct = 0.1234
assert f"{pct * 100:.1f}%" == "12.3%"  # The old way
assert f"{pct:.1%}" == "12.3%"  # The new way

num = 1234.56
assert f"{num:,}" == "1,234.56"
assert f"{num:,.0f}" == "1,235"

 

Print an expression and its value with ‘=’

def get_value():
    return 77

assert f"{get_value() = }" == "get_value() = 77"

 

 

Use Path for dealing with files

from pathlib import Path


file_contents = Path("my.log").read_text()  # one big string
file_lines = Path("my.log").read_text().splitlines()  # list of lines

path = Path(__file__).parent / "config.json"  # relative to this module
path.write_text(json.dumps(...))  # save as JSON

Path.cwd()  # current work dir

 

getpass(), not input()

from getpass import getpass

password = getpass("What's your password?")

 

copy() doesn’t always really copy

from copy import deepcopy, copy

my_list = [{"one": 1}]

shallow_copy = my_list.copy()
# shallow_copy = copy(my_list)
deep_copy = deepcopy(my_list)

# Change the original
my_list.append({"two": 2})
my_list[0]["one"] = 77

# Look at the changes
assert my_list == [{"one": 77}, {"two": 2}]
assert shallow_copy == [{"one": 77}]  # Mutated!
assert deep_copy == [{"one": 1}]

 

Flatten a list 

list_of_lists = [
    [1, 2, 3],
    [3, 4, 5],
    [5, 6, 7],
]

flat_list = [item for row in list_of_lists for item in row]

import itertools
flat_list = itertools.chain(*list_of_lists)

 

 Final: prevent a value from being changed

from typing import Final

MY_CONST: Final = 12

 

Fractions, Decimals: interesting

from fractions import Fraction

assert Fraction("1/10") + Fraction("2/10") == Fraction("3/10")
assert Fraction(1, 10) + Fraction(2, 10) == Fraction(3, 10)
assert Fraction(1 / 10) + Fraction(2 / 10) != Fraction(3 / 10)  # Not equal!

from decimal import Decimal

assert Decimal("0.1") + Decimal("0.2") == Decimal("0.3")
assert Decimal(0.1) + Decimal(0.2) != Decimal(0.3)  # Not equal!

 

Euclidean distance with math.dist()

import math

assert math.dist([0, 0], [3, 4]) == 5

 

Use default_timer as your … default timer

start_time = timeit.default_timer()

# Python 3.11
start_time = time.perf_counter()
start_time = time.perf_counter_ns() # nanoseconds