新功能手册:https://docs.python.org/3.8/whatsnew/3.8.html
>>> walrus = False
>>> print(walrus)
False
>>> print(walrus := True)
True
inputs = list()
current = input("Write something: ")
while current != "quit":
inputs.append(current)
current = input("Write something: ")
inputs = list()
while True:
current = input("Write something: ")
if current == "quit":
break
inputs.append(current)
inputs = list()
while (current := input("Write something: ")) != "quit":
inputs.append(current)
PEP572中描述了复制表达式的所有细节,大家可以深入阅读。https://www.python.org/dev/peps/pep-0572/ https://www.python.org/dev/peps/pep-0572/#examples
>>> float("3.8")
3.8
>>> help(float)
class float(object)
| float(x=0, /)
|
| Convert a string or number to a floating point number, if possible.
[...]
PEP 457 -- Notation For Positional-Only Parametershttps://www.python.org/dev/peps/pep-0457/
>>> float(x="3.8")
Traceback (most recent call last):
File "", line 1, in
TypeError: float() takes no keyword arguments
>>> def incr(x):
... return x + 1
...
>>> incr(3.8)
4.8
>>> incr(x=3.8)
4.8
>>> def incr(x, /):
... return x + 1
...
>>> incr(3.8)
4.8
>>> incr(x=3.8)
Traceback (most recent call last):
File "", line 1, in
TypeError: incr() got some positional-only arguments passed as
keyword arguments: 'x'
>>> def greet(name, /, greeting="Hello"):
... return f"{greeting}, {name}"
...
>>> greet("Łukasz")
'Hello, Łukasz'
>>> greet("Łukasz", greeting="Awesome job")
'Awesome job, Łukasz'
>>> greet(name="Łukasz", greeting="Awesome job")
Traceback (most recent call last):
File "", line 1, in
TypeError: greet() got some positional-only arguments passed as
keyword arguments: 'name'
>>> def to_fahrenheit(*, celsius):
... return 32 + celsius * 9 / 5
...
>>> to_fahrenheit(40)
Traceback (most recent call last):
File "", line 1, in
TypeError: to_fahrenheit() takes 0 positional arguments but 1 was given
>>> to_fahrenheit(celsius=40)
104.0
>>> def headline(text, /, border="♦", *, width=50):
... return f" {text} ".center(width, border)
...
>>> headline("Positional-only Arguments")
'♦♦♦♦♦♦♦♦♦♦♦ Positional-only Arguments ♦♦♦♦♦♦♦♦♦♦♦♦'
>>> headline(text="This doesn't work!")
Traceback (most recent call last):
File "", line 1, in
TypeError: headline() got some positional-only arguments passed as
keyword arguments: 'text'
>>> headline("Python 3.8", "=")
'=================== Python 3.8 ==================='
>>> headline("Real Python", border=":")
':::::::::::::::::: Real Python :::::::::::::::::::'
>>>
>>> headline("Python", "", width=38)
' Python '
>>> headline("Python", "", 38)
Traceback (most recent call last):
File "", line 1, in
TypeError: headline() takes from 1 to 2 positional arguments
but 3 were given
def double(number: float) -> float:
return 2 * number
>>> double(3.14)
6.28
>>> double("I'm not a float")
"I'm not a floatI'm not a float"
PEP 484https://www.python.org/dev/peps/pep-0484/
# draw_line.py
def draw_line(direction: str) -> None:
if direction == "horizontal":
... # Draw horizontal line
elif direction == "vertical":
... # Draw vertical line
else:
raise ValueError(f"invalid direction {direction!r}")
draw_line("up")
$ mypy draw_line.py
draw_line.py:15: error:
Argument 1 to "draw_line" has incompatible type "Literal['up']";
expected "Union[Literal['horizontal'], Literal['vertical']]"
Found 1 error in 1 file (checked 1 source file)
# calculator.py
from typing import Union
ARABIC_TO_ROMAN = [(1000, "M"), (900, "CM"), (500, "D"), (400, "CD"),
(100, "C"), (90, "XC"), (50, "L"), (40, "XL"),
(10, "X"), (9, "IX"), (5, "V"), (4, "IV"), (1, "I")]
def _convert_to_roman_numeral(number: int) -> str:
"""Convert number to a roman numeral string"""
result = list()
for arabic, roman in ARABIC_TO_ROMAN:
count, number = divmod(number, arabic)
result.append(roman * count)
return "".join(result)
def add(num_1: int, num_2: int, to_roman: bool = True) -> Union[str, int]:
"""Add two numbers"""
result = num_1 + num_2
if to_roman:
return _convert_to_roman_numeral(result)
else:
return result
# calculator.py
from typing import Literal, overload, Union
ARABIC_TO_ROMAN = [(1000, "M"), (900, "CM"), (500, "D"), (400, "CD"),
(100, "C"), (90, "XC"), (50, "L"), (40, "XL"),
(10, "X"), (9, "IX"), (5, "V"), (4, "IV"), (1, "I")]
def _convert_to_roman_numeral(number: int) -> str:
"""Convert number to a roman numeral string"""
result = list()
for arabic, roman in ARABIC_TO_ROMAN:
count, number = divmod(number, arabic)
result.append(roman * count)
return "".join(result)
@overload
def add(num_1: int, num_2: int, to_roman: Literal[True]) -> str: ...
@overload
def add(num_1: int, num_2: int, to_roman: Literal[False]) -> int: ...
def add(num_1: int, num_2: int, to_roman: bool = True) -> Union[str, int]:
"""Add two numbers"""
result = num_1 + num_2
if to_roman:
return _convert_to_roman_numeral(result)
else:
return result
from typing import Final
ID: Final = 1
...
ID += 1
from typing import final
@final
class Base:
...
class Sub(Base):
..
from typing import TypedDict
class PythonVersion(TypedDict):
version: str
release_year: int
py38 = PythonVersion(version="3.8", release_year=2019
当我看到一只鸟走路像鸭子,游泳像鸭子,像鸭子一样嘎嘎叫时,我把它称为鸭子。
from typing import Protocol
class Named(Protocol):
name: str
def greet(obj: Named) -> None:
print(f"Hi {obj.name}"
>>>
>>> style = "formatted"
>>> f"This is a {style} string"
'This is a formatted string'
官方文档https://docs.python.org/3/library/string.html#format-specification-mini-language
>>> import math
>>> r = 3.8
>>> f"Diameter {(diam := 2 * r)} gives circumference {math.pi * diam:.2f}"
'Diameter 7.6 gives circumference 23.88'
>>> python = 3.8
>>> f"{python=}"
'python=3.8'
>>> python = 3.7
>>> f"python={python}"
'python=3.7'
>>> f"{name.upper()[::-1] = }"
"name.upper()[::-1] = 'CIRE'"
PyCon 2019上的Python指导委员会。从左至右:Barry Warsaw,Brett Cannon,Carol Willing,Guido van Rossum和Nick Coghlan(图片来源:Geir Arne Hjelle)
importlib.metadata
>>> from importlib import metadata
>>> metadata.version("pip")
'19.2.3'
>>> pip_metadata = metadata.metadata("pip")
>>> list(pip_metadata)
['Metadata-Version', 'Name', 'Version', 'Summary', 'Home-page', 'Author',
'Author-email', 'License', 'Keywords', 'Platform', 'Classifier',
'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier',
'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier',
'Classifier', 'Classifier', 'Requires-Python']
>>> pip_metadata["Home-page"]
'https://pip.pypa.io/'
>>> pip_metadata["Requires-Python"]
'>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*'
>>> len(metadata.files("pip"))
668
>>> [p for p in metadata.files("realpython-reader") if p.suffix == ".py"]
[PackagePath('reader/__init__.py'), PackagePath('reader/__main__.py'),
PackagePath('reader/feed.py'), PackagePath('reader/viewer.py')]
>>> init_path = _[0] # Underscore access last returned value in the REPL
>>> print(init_path.read_text())
"""Real Python feed reader
Import the `feed` module to work with the Real Python feed:
>>> from reader import feed
>>> feed.get_titles()
['Logging in Python', 'The Best Python Books', ...]
See https://github.com/realpython/reader/ for more information
"""
# Version of realpython-reader package
__version__ = "1.0.0"
...
>>> metadata.requires("realpython-reader")
['feedparser', 'html2text', 'importlib-resources', 'typing']
try:
from importlib import metadata
except ImportError:
import importlib_metadata as metadata
...
>>> import math
>>> math.prod((2, 8, 7, 7))
784
>>> 2 * 8 * 7 * 7
784
>>> import statistics
>>> data = [9, 3, 2, 1, 1, 2, 7, 9]
>>> statistics.fmean(data)
4.25
>>> statistics.geometric_mean(data)
3.013668912157617
>>> statistics.multimode(data)
[9, 2, 1]
>>> statistics.quantiles(data, n=4)
[1.25, 2.5, 8.5]
>>> import random
>>> import statistics
>>> from timeit import timeit
>>> # Create 10,000 random numbers
>>> data = [random.random() for _ in range(10_000)]
>>> # Measure the time it takes to run mean() and fmean()
>>> t_mean = [timeit("statistics.mean(data)", number=100, globals=globals())
... for _ in range(30)]
>>> t_fmean = [timeit("statistics.fmean(data)", number=100, globals=globals())
... for _ in range(30)]
>>> # Create NormalDist objects based on the sampled timings
>>> n_mean = statistics.NormalDist.from_samples(t_mean)
>>> n_fmean = statistics.NormalDist.from_samples(t_fmean)
>>> # Look at sample mean and standard deviation
>>> n_mean.mean, n_mean.stdev
(0.825690647733245, 0.07788573997674526)
>>> n_fmean.mean, n_fmean.stdev
(0.010488564966666065, 0.0008572332785645231)
>>> # Calculate the lower 1 percentile of mean
>>> n_mean.quantiles(n=100)[0]
0.64450132212
>>> # Python 3.7
>>> version = "3.7"
>>> version is "3.7"
False
>>> # Python 3.8
>>> version = "3.8"
>>> version is "3.8"
:1: SyntaxWarning: "is" with a literal. Did you mean "=="?
False
>>> version == "3.8"
True
>>> [
... (1, 3)
... (2, 4)
... ]
:2: SyntaxWarning: 'tuple' object is not callable; perhaps
you missed a comma?
Traceback (most recent call last):
File "", line 2, in
TypeError: 'tuple' object is not callable
优化
>>>
>>> import collections
>>> from timeit import timeit
>>> Person = collections.namedtuple("Person", "name twitter")
>>> raymond = Person("Raymond", "@raymondh")
>>> # Python 3.7
>>> timeit("raymond.twitter", globals=globals())
0.05876131607996285
>>> # Python 3.8
>>> timeit("raymond.twitter", globals=globals())
0.0377705999400132
>>> import sys
>>> # Python 3.7
>>> sys.getsizeof(list(range(20191014)))
181719232
>>> # Python 3.8
>>> sys.getsizeof(list(range(20191014)))
161528168
https://docs.python.org/3.8/whatsnew/3.8.html#porting-to-python-3-8
https://www.python.org/downloads/release/python-380/
https://realpython.com/python38-new-features/ https://docs.python.org/3.8/whatsnew/3.8.html
◆
精彩推荐
◆