Proposal: `for in match` within list comprehension

Just for discussion (I’m new to Python by the way). I saw an example for pattern matching with Class in Fluent Python (2nd Edition):

class City(typing.NamedTuple):
    continent: str
    name: str
    country: str

cities = [
    City('Asia', 'Tokyo', 'JP'),
    City('Asia', 'Delhi', 'IN'),
    City('North America', 'Mexico City', 'MX'),
    City('North America', 'New York', 'US'),
    City('South America', 'São Paulo', 'BR'),
]

def match_brazil():
    results = []
    for city in cities:
        match city:
            case City(country='BR', name=name):
                results.append(name)
    return results

It uses 5 lines of code to filter the items in the list (actually, it is filter and map; or flatMap in functional programming).

results = []
for city in cities:
    match city:
        case City(country='BR', name=name):
            results.append(name)

Is that possible use match case within list comprehension in current Python version? like this:

# When using `for ... in ... if ...` for current Python, you need lots of code after `if`.
results = [city.name for city in cities if (type(city) == City) and (city.country == 'BR')]

# Use `match case` instead of `if` in the list comprehension
results = [name for city in cities match case City(country='BR', name=name)]

# To minimize the code, you don't need `case` here (just `match` keyword is enough)
results = [name for city in cities match City(country='BR', name=name)]

# You can omit the `city` because you don't need it in this example (use `for _ in` or `for in`).
results = [name for _ in cities match City(country='BR', name=name)]
results = [name for in cities match City(country='BR', name=name)]

This would increase the readability and coding speed when you have lots logic to check. Maybe it also has chances to increase performance.

The syntax is more like SQL.

# final version (proposal)
def match_brazil():
    return [name for in cities match City(country='BR', name=name)]

That’s my proposal: for in match within list comprehension


PS. since match is not keyword in Python, it may need a colon after match

# from this
[name for in cities match City(country='BR', name=name)]
# to this
[name for in cities match: City(country='BR', name=name)]

I actually find those list comprehensions harder to read. Your example can also be written as:

results = [city.name for city in cities if city.country == 'BR']

because you shouldn’t care about the type, just the structure (i.e. duck typing).

There are not a ton of optimizations in match statements, so it very likely wouldn’t lead to a performance change (and actually dropping the type check in the list comprehension probably makes my example above faster). But honestly, even if it did it wouldn’t be enough to warrant making this change.

I just wrote an equivalent syntax to match. The syntax match case for Class pattern matching does check the type first. In other cases, you may need to check the type for other reasons.

Maybe there should be a syntax to ignore type check within match case for duck typing:

results = []
    for city in cities:
        match city:
            # Original: case City(country='BR', name=name):
            case _(country='BR', name=name):    # use _ to ignore type check 
                results.append(name)

And you can still use that within for in match list comprehension:

# ignore type check (only if you are sure all items have those attributes)
results = [name for in cities match: _(country='BR', name=name)]

The example just shows how the for in match syntax looks like. Yes, using match case just for one case looks weird. When you have multiple attributes to check for extracting the items from a list, pattern matching is still useful syntax.