Pampy cukup kecil (150 baris), cukup cepat, dan sering kali membuat kode Anda lebih mudah dibaca sehingga lebih mudah untuk dipikirkan. Ada juga versi JavaScript yang disebut Pampy.js.
Pola dievaluasi sesuai urutan kemunculannya.
Operator _ berarti "kasus lain yang tidak terpikirkan oleh saya".
dari pencocokan impor pampy, _def fibonacci(n):return match(n,1, 1,2, 1,_, lambda x: fibonacci(x-1) + fibonacci(x-2) )
dari kecocokan impor pampy, REST, _def lisp(exp):return match(exp,int, lambda x: x,callable, lambda x: x, (dapat dipanggil, REST), lambda f, istirahat: f(*map(lisp, rest)),tuple, lambda t: list(map(lisp, t)), )plus = lambda a, b: a + bminus = lambda a, b: a - bfrom functools import Reducelisp((plus, 1, 2)) # => 3lisp((plus, 1, (minus, 4, 2)) ) # => 3lisp((kurangi, tambah, (kisaran, 10))) # => 45
match(x,3, "ini cocok dengan angka 3",int, "cocok dengan bilangan bulat apa pun", (str, int), lambda a, b: "sebuah tupel (a, b) yang dapat Anda gunakan dalam suatu fungsi", [1, 2, _], "daftar 3 elemen apa pun yang dimulai dengan [1, 2]", {'x': _}, "dikt apa pun dengan kunci 'x' dan nilai apa pun yang terkait",_, "apa pun")
dari kecocokan impor pampy, HEAD, TAIL, _x = [1, 2, 3]match(x, [1, TAIL], lambda t: t) # => [2, 3]match(x, [HEAD, TAIL] , lambda h, t: (h, t)) # => (1, [2, 3])
TAIL
dan REST
sebenarnya memiliki arti yang sama.
dari kecocokan impor pampy, _x = [1, [2, 3], 4]cocok(x, [1, [_, 3], _], lambda a, b: [1, [a, 3], b] ) # => [1, [2, 3], 4]
pet = { 'type': 'dog', 'details': { 'age': 3 } }match(pet, { 'details': { 'age': _ } }, lambda age: age) # => 3match (hewan peliharaan, { _ : { 'usia': _ } }, lambda a, b: (a, b)) # => ('detail', 3)
Rasanya memasukkan beberapa _ ke dalam dicts seharusnya tidak berhasil. Bukankah memesan dalam dicts tidak dijamin? Tapi itu terjadi karena di Python 3.7, dict mempertahankan urutan kunci penyisipan secara default
class Pet: passclass Dog(Pet): passclass Cat(Pet): passclass Hamster(Pet): passdef what_is(x):return match(x,Dog, 'dog',Cat, 'cat',Pet, 'hewan peliharaan lainnya ', _, 'ini sama sekali bukan hewan peliharaan', )what_is(Cat()) # => 'cat'what_is(Dog()) # => 'dog'what_is(Hamster()) # => 'pet lain'what_is(Pet()) # => 'any other pet'what_is(42) # => 'ini sama sekali bukan hewan peliharaan'
Pampy mendukung kelas data Python 3.7. Anda dapat meneruskan operator _
sebagai argumen dan itu akan cocok dengan bidang tersebut.
@dataclassclass Pet:nama: strage: intpet = Pet('rover', 7)match(pet, Pet('rover', _), lambda age: age) # => 7match(pet, Pet(_, 7), nama lambda: nama) # => 'rover'match(pet, Pet(_, _), nama lambda, umur: (nama, umur)) # => ('rover', 7)
Pampy mendukung anotasi pengetikan.
class Pet: passclass Dog(Pet): passclass Cat(Pet): passclass Hamster(Pet): passtimestamp = NewType("year", Union[int, float])def annotated(a: Tuple[int, float], b: str, c: E) -> stempel waktu:passmatch((1, 2), Tuple[int, int], lambda a, b: (a, b)) # => (1, 2)match(1, Union[str, int], lambda x: x) # => 1match('a', Union[str, int], lambda x: x) # => 'a'match('a', Opsional[str], lambda x: x) # => 'a'match(Tidak ada, Opsional[str], lambda x: x) # => Nonematch(Pet, Tipe[Pet], lambda x: x) # => Petmatch(Kucing, Ketik[Hewan Peliharaan], lambda x: x) # => Catmatch(Anjing, Apa Saja, lambda x: x) # => Dogmatch(Anjing, Ketik[Apa pun], lambda x: x) # => Dogmatch( 15, stempel waktu, lambda x: x) # => 15match(10.0, stempel waktu, lambda x: x) # => 10.0match([1, 2, 3], Daftar[int], lambda x: x) # => [1, 2, 3]cocok({'a': 1, 'b': 2}, Dict[str, int], lambda x: x) # = > {'a': 1, 'b': 2}match(beranotasi, Callable[[Tuple[int, float], str, Pet], stempel waktu], lambda x: x) # => dianotasi
Untuk obat generik yang dapat diubah, tipe nilai sebenarnya ditebak berdasarkan elemen pertama.
cocok([1, 2, 3], Daftar[int], lambda x: x) # => [1, 2, 3]cocok([1, "b", "a"], Daftar[int], lambda x: x) # => [1, "b", "a"]match(["a", "b", "c"], List[int], lambda x: x) # memunculkan MatchErrormatch([" a", "b", "c"], Daftar[Union[str, int]], lambda x: x) # ["a", "b", "c"]cocok({"a": 1, "b": 2}, Dict[str, int ], lambda x: x) # {"a": 1, "b": 2}cocok({"a": 1, "b": "anjing"}, Dict[str, int], lambda x: x ) #{"a": 1, "b": "anjing"}cocok({"a": 1, 1: 2}, Dict[str, int], lambda x: x) # {"a": 1, 1: 2}cocok({2 : 1, 1: 2}, Dict[str, int], lambda x: x) # memunculkan MatchErrormatch({2: 1, 1: 2}, Dict[Union[str, int], int], lambda x: x) # {2:1, 1:2}
Obat generik yang dapat diubah juga cocok dengan subtipe mana pun.
cocok([1, 2, 3], Dapat diubah[int], lambda x: x) # => [1, 2, 3]cocok({1, 2, 3}, Dapat diubah[int], lambda x: x) # => {1, 2, 3}cocok(rentang(10), Dapat diubah[int], lambda x: x) # => rentang(10)cocok([1, 2, 3], Daftar[int], lambda x: x) # => [1, 2, 3]cocok({1, 2, 3}, Daftar[int], lambda x: x) # => memunculkan MatchErrormatch(range(10) , Daftar[int], lambda x: x) # => memunculkan MatchErrormatch([1, 2, 3], Set[int], lambda x: x) # => memunculkan MatchErrormatch({1, 2, 3}, Set[int], lambda x: x) # => {1, 2, 3}match(range(10), Set[int], lambda x: x) # => memunculkan MatchError
Untuk Callable, argumen apa pun tanpa anotasi diperlakukan sebagai Any.
def beranotasi(a: int, b: int) -> float:passdef not_annotated(a, b):passdef part_annotated(a, b: float):passmatch(beranotasi, Callable[[int, int], float], lambda x : x) # => annotatedmatch(not_annotated, Callable[[int, int], float], lambda x: x) # => menaikkan MatchErrormatch(not_annotated, Callable[[Any, Any], Any], lambda x: x) # => not_annotatedmatch(annotated, Callable[[Any, Any], Any], lambda x: x) # => memunculkan MatchErrormatch(partially_annotated , Dapat dipanggil[[Apa saja, mengambang], Apa saja], lambda x: x) # => dianotasi sebagian
TypeVar tidak didukung.
Sebagai Pola, Anda dapat menggunakan tipe Python apa pun, kelas apa pun, atau nilai Python apa pun.
Operator _
dan tipe bawaan seperti int
atau str
, mengekstrak variabel yang diteruskan ke fungsi.
Jenis dan Kelas dicocokkan melalui instanceof(value, pattern)
.
Pola Iterable
cocok secara rekursif melalui semua elemennya. Hal yang sama berlaku untuk kamus.
Contoh Pola | Apa artinya | Contoh yang Cocok | Argumen Diteruskan agar berfungsi | Contoh TIDAK Cocok |
---|---|---|---|---|
"hello" | hanya string "hello" yang cocok | "hello" | Tidak ada apa-apa | nilai lainnya |
None | hanya None | None | Tidak ada apa-apa | nilai lainnya |
int | Bilangan bulat apa pun | 42 | 42 | nilai lainnya |
float | Nomor pelampung apa pun | 2.35 | 2.35 | nilai lainnya |
str | Tali apa pun | "hello" | "hello" | nilai lainnya |
tuple | tupel apa pun | (1, 2) | (1, 2) | nilai lainnya |
list | Daftar apa pun | [1, 2] | [1, 2] | nilai lainnya |
MyClass | Setiap contoh MyClass. Dan objek apa pun yang memperluas MyClass. | MyClass() | contoh itu | objek lainnya |
_ | Objek apa pun (bahkan Tidak Ada) | nilai itu | ||
ANY | Sama seperti _ | nilai itu | ||
(int, int) | Tuple yang terbuat dari dua bilangan bulat apa pun | (1, 2) | 1 dan 2 | (Benar, Salah) |
[1, 2, _] | Daftar yang dimulai dengan 1, 2 dan diakhiri dengan nilai apa pun | [1, 2, 3] | 3 | [1, 2, 3, 4] |
[1, 2, TAIL] | Daftar yang dimulai dengan 1, 2 dan diakhiri dengan urutan apa pun | [1, 2, 3, 4] | [3, 4] | [1, 7, 7, 7] |
{'type':'dog', age: _ } | Perintah apa pun dengan type: "dog" dan usia | {"type":"dog", "age": 3} | 3 | {"type":"cat", "age":2} |
{'type':'dog', age: int } | Dict apa pun dengan type: "dog" dan dengan usia int | {"type":"dog", "age": 3} | 3 | {"type":"dog", "age":2.3} |
re.compile('(w+)-(w+)-cat$') | String apa pun yang cocok dengan ekspresi reguler expr | "my-fuffy-cat" | "my" dan "puffy" | "fuffy-dog" |
Pet(name=_, age=7) | Kelas data hewan peliharaan apa pun dengan age == 7 | Pet('rover', 7) | ['rover'] | Pet('rover', 8) |
Any | Sama seperti _ | nilai itu | ||
Union[int, float, None] | Bilangan bulat atau bilangan mengambang apa pun atau Tidak Ada | 2.35 | 2.35 | nilai lainnya |
Optional[int] | Sama seperti Union[int, None] | 2 | 2 | nilai lainnya |
Type[MyClass] | Subkelas apa pun dari MyClass. Dan kelas apa pun yang memperluas MyClass. | MyClass | kelas itu | objek lainnya |
Callable[[int], float] | Semua yang dapat dipanggil dengan tanda tangan persis seperti itu | def a(q:int) -> float: ... | fungsi itu | def a(q) -> float: ... |
Tuple[MyClass, int, float] | Sama seperti (MyClass, int, float) | |||
Mapping[str, int] Subtipe Mapping apa pun juga dapat diterima | pemetaan atau subtipe pemetaan apa pun dengan kunci string dan nilai integer | {'a': 2, 'b': 3} | dikte itu | {'a': 'b', 'b': 'c'} |
Iterable[int] Semua subtipe Iterable juga dapat diterima | setiap iterable atau subtipe dari iterable dengan nilai integer | range(10) dan [1, 2, 3] | yang dapat diubah | ['a', 'b', 'v'] |
Secara default match()
ketat. Jika tidak ada pola yang cocok, maka akan muncul MatchError
.
Anda malah dapat memberikan nilai cadangan menggunakan default
untuk digunakan ketika tidak ada yang cocok.
>>> match([1, 2], [1, 2, 3], "whatever") MatchError: '_' not provided. This case is not handled: [1, 2] >>> match([1, 2], [1, 2, 3], "whatever", default=False) False
Pampy mendukung Regex Python. Anda dapat meneruskan regex yang dikompilasi sebagai pola, dan Pampy akan menjalankan pattern.search()
, lalu meneruskan ke fungsi tindakan hasil .groups()
.
def what_is(pet):return match(pet,re.compile('(w+)-(w+)-cat$'), nama lambda, my: 'cat '+name,re.compile('(w+)-( w+)-dog$'), nama lambda, my: 'dog '+name,_, "something else")what_is('fuffy-my-dog') # => 'dog fuffy'what_is('puffy-her-dog') # => 'dog puffy'what_is('carla-your-cat') # => 'cat carla'what_is('roger-my-hamster') # => ' sesuatu yang lain'
Pampy berfungsi dengan Python >= 3.6 Karena pencocokan dict hanya dapat berfungsi di Python terbaru.
Untuk menginstalnya:
$ pip install pampy
atau $ pip3 install pampy
Pampy adalah yang pertama di Python3, tetapi Anda dapat menggunakan sebagian besar fiturnya di Python2 melalui backport ini oleh Manuel Barkhau:
pip install backports.pampy
dari kecocokan impor backports.pampy, HEAD, TAIL, _