Skip to content

Instantly share code, notes, and snippets.

@trag1c
Last active January 8, 2024 19:44
Show Gist options
  • Save trag1c/30b09346655394518fb1ec410d86b99c to your computer and use it in GitHub Desktop.
Save trag1c/30b09346655394518fb1ec410d86b99c to your computer and use it in GitHub Desktop.
The best of rejected PEPs

The best of rejected PEPs

A collection of my best findings when looking through rejected Python Enhancement Proposals (as of Jan 6, 2024).

PEP 204: Range Literals

(2000, Python 2.0)

>>> [1:10]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> [:5]
[0, 1, 2, 3, 4]
>>> [5:1:-1]
[5, 4, 3, 2]

PEP 210: Decoupling the Interpreter Loop

(2000, Python 2.1)

(it's empty :trollface:)

PEP 211: Adding A New Outer Product Operator

(2000, Python 2.1)

for (i, j) in S @ T:
    pass

would be equivalent to

for i in S:
    for j in T:
        pass

Note

The operator was later added in PEP 465.

PEP 212: Loop Counter Iteration

(2000, Python 2.1)

for i in range(len(sequence)):
    # work with index i


for i, e in zip(range(len(sequence)), sequence):  # enumerate() didn't exist until Python 2.3
    # work with index i and element e

would be replaced with either:

  1. non-reserved keyword indexing
for i indexing sequence:
    # work with index i


for i indexing e in sequence:
    # work with index i and element e
  1. built-in functions indices and irange
for i in indices(sequence):
    # work with index i


for i, e in irange(sequence):
    # work with index i and element e
  1. methods for sequence objects
for i in sequence.indices():
    # work with index i


for i, e in sequence.items():
    # work with index i and element e


# and also
for e in sequence_or_dict.values():
    # do something with element e

PEP 224: Attribute Docstrings

(2000, Python 2.1)

class C:
    "class C doc-string"

    a = 1
    "attribute C.a doc-string (1)"

    b = 2
    "attribute C.b doc-string (2)"

Tip

Even though rejected, some LSPs today support this.

PEP 242: Numeric Kinds

(2001, Python 2.2)

import kinds

tinyint = kinds.int_kind(1)
# tinyint is now a type that accepts ints in the open interval (-10**1, 10**1).

From the Rejection section:

There was no opposition to the proposal but only mild interest in using it, not enough to justify adding the module to the standard library. Instead, it will be made available as a separate distribution item at the Numerical Python site. At the next release of Numerical Python, it will no longer be a part of the Numeric distribution.

Take a guess at what Numerical Python is today :)

PEP 259: Omit printing newline after newline

(2001, Python 2.2)

print "foo\n"  # the trailing newline is ignored
print "bar\nbaz"

would output:

foo
bar
baz

instead of

foo

bar
baz

PEP 270: uniq method for list objects

(2001, Python 2.2)

nums = [6, 1, 6, 5, 3, 1, 4, 2, 4, 1]
nums.uniq()
print nums
# [6, 1, 5, 3, 4, 2]

The PEP was rejected partly because the set type was being added at the same time.

PEP 275: Switching on Multiple Values

(2001, Python 2.6)

One of the solutions this PEP presented was adding a switch statement to Python:

def whatis(x):
    switch(x):
        case "one":
            print "1"
        case "two":
            print "2"
        case "three":
            print "3"
        else:
            print "D'oh!"

PEP 276: Simple Iterator for ints

(2001, Python 2.3)

>>> for i in 3:
...     print i
... 
0
1
2

PEP 284: Integer for-loops

(2002, Python 2.3)

>>> x = 5
>>> for 2 <= value < x:
...     print value
... 
2
3
4

PEP 303: Extend divmod() for Multiple Divisors

(2002, Python 2.3)

def secs_to_wdhms(seconds):
    m, s = divmod(seconds, 60)
    h, m = divmod(m, 60)
    d, h = divmod(h, 24)
    w, d = divmod(d, 7)
    return (w, d, h, m, s)

would become

def secs_to_wdhms(seconds):
    return divmod(seconds, 7, 24, 60, 60)

PEP CCCXIII: Adding Roman Numeral Literals to Python

(2003, Python 2.4)

This is just silly 💀

year = MMIII
print(year + XXI)  # MMXXIV

PEP 315: Enhanced While Loop

(2003, Python 2.5)

while True:
    <setup code>
    if not <condition>:
        break
    <loop body>

would instead be written as

do:
    <setup code>
while condition:
    <loop body>

PEP 319: Python Synchronize/Asynchronize Block

(2003, Python 2.4)

synchronize:
    change_shared_data()

    asynchronize:
       do_blocking_io()

    change_shared_data2()

PEP 351: The freeze protocol

(2005)

>>> class xset(set):
...     def __freeze__(self):
...         return frozenset(self)
...
>>> s = set([1, 2, 3])
>>> {s: 4}
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: set objects are unhashable
>>> t = freeze(s)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "/usr/tmp/python-lWCjBK.py", line 9, in freeze
TypeError: object is not freezable
>>> t = xset(s)
>>> u = freeze(t)
>>> {u: 4}
{frozenset([1, 2, 3]): 4}

PEP 363: Syntax For Dynamic Attribute Access

x.("foo_{}".format(n)) += 1

z = y.("foo_%d" % n).("bar_%s" % s)

PEP 401: BDFL Retirement

(2009)

Note

The website states the status as "April Fool!", although it's specified as "Rejected" in the PEP API.

>>> from __future__ import barry_as_FLUFL
>>> 1 <> 2
True

PEP 455: Adding a key-transforming dictionary to collections

(2013, Python 3.5)

>>> d = TransformDict(str.casefold)
>>> d['SomeKey'] = 5
>>> d['somekey']
5
>>> d['SOMEKEY']
5

PEP 463: Exception-catching expressions

(2014, Python 3.5)

lst = [1, 2]
try:
    value = lst[2]
except IndexError:
    value = "No value"

would become

lst = [1, 2]
value = (lst[2] except IndexError: "No value")

PEP 542: Dot Notation Assignment In Function Header

(2017)

class MyClass:
    ...


def MyClass.my_method(self):
    ...

would be equivalent to

class MyClass:
    def my_method(self):
        ...

PEP 548: More Flexible Loop Control

(2017, Python 3.7)

while True:
    if not condition: break

would become

while True:
    break if not condition

PEP 559: Built-in noop()

(2017, Python 3.7)

Not much to explain...

>>> noop()
>>> 

PEP 640: Unused variable syntax

(2020, Python 3.10)

? = ...
x, ?, z = ...
x, *?, z = ...
for ? in range(3): ...  # including comprehension forms
for x, ?, z in matrix: ...  # including comprehension forms
with open(f) as ?: ...
with func() as (x, ?, z): ...

PEP 677: Callable Type Syntax

(2021, Python 3.11)

from typing import Awaitable, Callable
from app_logic import Response, UserSetting


def customize_response(
    response: Response,
    customizer: Callable[[Response, list[UserSetting]], Awaitable[Response]]
) -> Response:
   ...

would become

from app_logic import Response, UserSetting

def customize_response(
    response: Response,
    customizer: async (Response, list[UserSetting]) -> Response,
) -> Response:
    ...

PEP 3117: Postfix type declarations

(2007, Python 3.0)

Type Declarator
object � (REPLACEMENT CHARACTER)
int ℕ (DOUBLE-STRUCK CAPITAL N)
float ℮ (ESTIMATED SYMBOL)
bool ✓ (CHECK MARK)
complex ℂ (DOUBLE-STRUCK CAPITAL C)
str ✎ (LOWER RIGHT PENCIL)
unicode ✒ (BLACK NIB)
tuple ⒯ (PARENTHESIZED LATIN SMALL LETTER T)
list ♨ (HOT SPRINGS)
dict ⧟ (DOUBLE-ENDED MULTIMAP)
set ∅ (EMPTY SET) (Note: this is also for full sets)
frozenset ☃ (SNOWMAN)
datetime ⌚ (WATCH)
function ƛ (LATIN SMALL LETTER LAMBDA WITH STROKE)
generator ⚛ (ATOM SYMBOL)
Exception ⌁ (ELECTRIC ARROW)

Important

"The declarator for the None type is a zero-width space."
WTF 💀

def fooƛ(xℂ):
    return None

PEP 3136: Labeled break and continue

(2007, Python 3.1)

for a in a_list as a_loop:
    ...
    for b in b_list as b_loop:
        ...
        if condition_one(a, b):
            break b_loop  # same as plain old break
        ...
        if condition_two(a, b):
            break a_loop
        ...
    ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment