Comments (5)
Okay, but maybe then the example should validate everything and raise in the default case? That would actually simplify things a bit because we can get rid of the Optional (| None
).
We should also add case _: raise ...
to get_pets()
then.
from patma.
The example certainly works, but it looks a wee bit artificial too me, to be perfectly honest.
Yes, the str(name)
part is a bit of an ugly spot. The reason why it bothers me a bit is that it is used to validate the data without really handling it. To my mind, patterns should be used to let the interpreter select the 'correct' case clause and extract data. Somehow, having a pattern like { "name": str(name) }
suggests to me that there will be another pattern { "name": ... }
handling anything that is not a string. But I would not use the str()
here just as a kind of type annotation.
So, may I propose to slightly change the example like this:
def get_pet(raw_pet: object) -> Cat | Dog | None:
match raw_pet:
case {"type": "cat", "name": str(name), "breed": str(breed), "favorite_toy": str(toy)}:
return Cat(name, breed, toy)
case {"type": "dog", "name": str(name), "breed": str(breed), "leash_color": str(leash)}:
return Dog(name, breed, leash)
case {"type": "cat" | "dog"}:
raise malformed_data(repr(raw_pet))
case _:
return None # Not a known type of pet
Perhaps it might also be a nice touch to add a very brief description or title saying something like "transforming data from JSON to Python data classes."
from patma.
Yes, that sounds good to me. I would still have the additional case then, though, and use perhaps two different exception types. One could be malformed_data
and the other not_a_pet
, for instance.
from patma.
Okay, then my next version is:
# Cats and Dogs
import sys
import json
from dataclasses import dataclass
@dataclass
class Animal:
pass
@dataclass
class Pet(Animal):
name: str
breed: str
@dataclass
class Dog(Pet):
leash_color: str
@dataclass
class Cat(Pet):
favorite_toy: str
def get_pets(raw: object) -> list[Cat | Dog]:
match raw:
case [*raw_pets]: # List of pets
return [get_pet(raw_pet) for raw_pet in raw_pets]
case {**raw_pet}: # Maybe a single pet
return [get_pet(raw_pet)]
case _:
raise TypeError(f"Neither a pet nor a list of pets: {raw}")
def get_pet(raw_pet: object) -> Cat | Dog:
match raw_pet:
case {"type": "cat", "name": str(name), "breed": str(breed), "favorite_toy": str(toy)}:
return Cat(name, breed, toy)
case {"type": "dog", "name": str(name), "breed": str(breed), "leash_color": str(leash)}:
return Dog(name, breed, leash)
case {"type": "cat" | "dog"}:
raise TypeError(f"Malformed pet: {raw_pet}")
case _:
raise TypeError(f"Not a pet: {raw_pet}")
def main() -> None:
raw = json.load(sys.stdin)
for pet in get_pets(raw):
print(pet)
if __name__ == "__main__":
main()
However, I still find this too long for inclusion in PEP 635 (where I have a TODO suggesting a JSON example), and even if we link to it I'm less than thrilled about using str(name)
six times -- this is too similar to the expression of that form. If we could instead use
case {"type": "cat", "name": name, "breed": breed, "favorite_toy": toy}:
it would be more accessible as an example, but of course it fails to validate properly.
from patma.
Cleaned up as https://github.com/gvanrossum/patma/blob/master/examples/jsonpets.py
I changed the structure somewhat, moving "breed" into Dog and changing it to "pattern" for Cat (tuxedo cats aren't a breed, the Internet tells me).
Note that there's no way to validate the type annotations, as no type checker for Python currently supports match statements (nor the PEP 604 |
notation for Unions :-).
from patma.
Related Issues (20)
- Phrasing update in abstract and overview HOT 2
- Disallow guards when using an "open pattern"? HOT 11
- Can the compiler move guards around? HOT 7
- Add link to DLS paper to PEP 635 HOT 1
- Reach out to Pablo for code review HOT 1
- Use "as" for named patterns HOT 2
- Raise SyntaxErrors for anything following irrefutable patterns
- Finish AST validation for patterns
- Catch remaining errors in the compiler HOT 1
- Unify the PEP 634 and implementation grammars HOT 2
- Review progress for the reference implementation HOT 5
- Thomas Wouters' objections HOT 13
- Nick Coghlan's (revised) PEP 642 HOT 1
- Dedicated AST nodes for patterns? HOT 5
- PyCon 2021 HOT 10
- work error with zip param "strict=False" on py386 HOT 1
- Please document the design decisions behind PEP 634. HOT 7
- Case goto's? HOT 1
- PyCon JP 2021 HOT 5
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from patma.