3.5. Match Wildcard¶
The wildcard pattern is a single underscore: _
. It always
matches, but does not capture any variable (which prevents
interference with other uses for _
and allows for some
optimizations).
>>> user = 'Mark'
>>>
>>> match user:
... case 'Mark': print('Hello Mark')
... case 'Melissa': print('Hello Melissa')
... case 'Rick': print('Hello Rick')
... case 'Alex': print('Hello Alex')
... case 'Beth': print('Hello Beth')
... case 'Chris': print('Hello Chris')
... case _: raise PermissionError
...
Hello Mark
3.5.1. Use Case - 0x01¶
>>> def html_color(name):
... match name:
... case 'red': return '#ff0000'
... case 'green': return '#00ff00'
... case 'blue': return '#0000ff'
... case _: raise NotImplementedError('Unknown color')
>>> html_color('black')
Traceback (most recent call last):
NotImplementedError: Unknown color
>>> html_color('orange')
Traceback (most recent call last):
NotImplementedError: Unknown color
3.5.2. Use Case - 0x02¶
>>> weekday = 0
>>>
>>> match weekday:
... case 1: print('Monday')
... case 2: print('Tuesday')
... case 3: print('Wednesday')
... case 4: print('Thursday')
... case 5: print('Friday')
... case 6: print('Saturday')
... case 7: print('Sunday')
... case _: raise ValueError('Invalid weekday') # wildcard pattern
...
Traceback (most recent call last):
ValueError: Invalid weekday
3.5.3. Assignments¶
"""
* Assignment: Match Wildcard Range
* Complexity: medium
* Lines of code: 18 lines
* Time: 5 min
English:
1. Write own implementation of a built-in function `range()`
2. Note, that function does not take any keyword arguments
3. How to implement passing only stop argument
`myrange(start=0, stop=???, step=1)`?
4. Use literal pattern and wildcard pattern
5. Run doctests - all must succeed
Polish:
1. Zaimplementuj własne rozwiązanie wbudowanej funkcji `range()`
2. Zauważ, że funkcja nie przyjmuje żanych argumentów nazwanych (keyword)
3. Jak zaimplementować możliwość podawania tylko końca
`myrange(start=0, stop=???, step=1)`?
4. Użyj literal pattern i wildcard pattern
5. Uruchom doctesty - wszystkie muszą się powieść
Hint:
* https://github.com/python/cpython/blob/main/Objects/rangeobject.c#LC75
* match len(args)
* case _
* `raise TypeError('error message')`
Tests:
>>> import sys; sys.tracebacklimit = 0
>>> from inspect import isfunction
>>> assert isfunction(myrange)
>>> myrange(0, 10, 2)
[0, 2, 4, 6, 8]
>>> myrange(0, 5)
[0, 1, 2, 3, 4]
>>> myrange(5)
[0, 1, 2, 3, 4]
>>> myrange()
Traceback (most recent call last):
TypeError: myrange expected at least 1 argument, got 0
>>> myrange(1,2,3,4)
Traceback (most recent call last):
TypeError: myrange expected at most 3 arguments, got 4
>>> myrange(stop=2)
Traceback (most recent call last):
TypeError: myrange() takes no keyword arguments
>>> myrange(start=1, stop=2)
Traceback (most recent call last):
TypeError: myrange() takes no keyword arguments
>>> myrange(start=1, stop=2, step=2)
Traceback (most recent call last):
TypeError: myrange() takes no keyword arguments
"""
# myrange(start=0, stop=???, step=1)
# note, function does not take keyword arguments
# type: Callable[[int,int,int], list[int]]
def myrange(*args, **kwargs):
if kwargs:
raise TypeError('myrange() takes no keyword arguments')
start = ...
stop = ...
step = ...
current = start
result = []
while current < stop:
result.append(current)
current += step
return result