Python arbritary keys in TypedDict - python

Is it possible to make a TypedDict with a set of known keys and then a type for an arbitrary key? For example, in TypeScript, I could do this:
interface Sample {
x: boolean;
y: number;
[name: string]: string;
}
What is the equivalent in Python?

Related

Graphene: What are the Difference between serializer, parse_literal and parse_value staticmethods on Custom Scalar? [duplicate]

Looking through the GraphQL documentation for custom scalar types (I'm trying to create my own date type) I'm not sure what the difference between parseValue and parseLiteral are.
http://graphql.org/graphql-js/type/#graphqlscalartype
The documentation doesn't seem to include any descriptions of what the functions are supposed to do.
Can someone let me know what the requirements are? I'm assuming that serialize must serialize the scalar to a string. Is that correct? I'm assuming that parseLiteral is a deserialization of that string to the type? In my case a Date type. However, in the examples - serialize and parseValue are the same function - which suggests it's not a simple deserialization method.
The serialize method would be called when the value of the type is going to be sent to the client as a response. Since the values on the output is in the form of JSON, the return value of serialize could be anything. Could be string, number, array, object ...
The other two methods (parseValue and parseLiteral) are to read input.
In GraphQL there are two ways of reading input from client, one is inline in the query, like:
query {
allUsers(first:10) {
id
}
}
where 10 is the inline value for first argument. Since the input language for GraphQL is not exactly JSON, the value (here 10) is being parsed and converted to AST (Abstract Syntax Tree). In this case, parseLiteral comes to play. It inputs the AST and returns the parsed value of the type. Types could be as complex as JSON and parseLiteral could traverse the AST and return JSON.
The other way of reading input from clients is through variables:
query ($howMany: YourCustomType) {
users(first: $howMany) {
id
}
}
variables:
{
"howMany": {
"thisMany": 10
}
}
Since the variables are pure JSON, you don't need AST here, you already have JSON. That's where parseValue comes to play. It gets the input as JSON and returns whatever the query resolver should use.
function parseValue(value) {
let first = value.thisMany;
return first;
}
So, you could have different presentation when you read from variables than when you read values inline, but conceptually, they should be the same in terms of presentation. However since the "type" of input is different (inline is GraphQL and variable is JSON), the parsing algorithm could be different. That's why if you define it as input type, you need to provide two separate methods to read them.

I want to create something like a python dictionary in C++

I'm using a struct. Is there some way to iterate through all the items of type "number"?
struct number { int value; string name; };
In c++ map works like python dictionary, But there is a basic difference in two languages. C++ is typed and python having duck typing. C++ Map is typed and it can't accept any type of (key, value) like python dictionary.
A sample code to make it more clear -
map<int, char> mymap;
mymap[1] = 'a';
mymap[4] = 'b';
cout<<"my map is -"<<mymap[1]<<" "<<mymap[4]<<endl;
You can use tricks to have a map which will accept any type of key, Refer - http://www.cplusplus.com/forum/general/14982/
As per my understanding you want to access a value and name using number. You can go for array of structure like
number n[5]; where n[0],n[1],...n[4]
but we have some additional features in c++ to achieve this with the predefined map, set
You can find lots of examples for map
You can use std::map (or unordered_map)
// Key Value Types.
std::map<int, std::string> data {{1, "Test"}, {2, "Plop"}, {3, "Kill"}, {4, "Beep"}};
for(auto item: data) {
// Key Value
std::cout << item.first << " : " << item.second << "\n";
}
Compile and run:
> g++ -std=c++14 test.cpp
> ./a.out
1 : Test
2 : Plop
3 : Kill
4 : Beep
The difference between std::map and std::unordered_map is for std::map the items are ordered by the Key while in std::unordered_map the values are not ordered (thus they will be printed in a seemingly random order).
Internally they use very different structures but I am sure you are not interested in that level of detail.

Marshmallow: How to handle undeclared fields?

I am trying to validate a dict which contains stringified integers as keys. These ints are arbitrary numerical IDs, and out of my control.
How could I declare this in a schema?
Maybe there's a way to declare a default schema which I could use as a catch-all?
Thanks.
http://marshmallow.readthedocs.org/en/latest/index.html
The way I prefer, use a map instead of if statement:
for key, value in dictionary.items():
dictionary[
{
"True": str(key),
"False": <build a random key>
}.get(str(isinstance(key, int)))
] = value
Note: works only on Python3+

Python dict converted to VB.net

I would like to find out if there is a way to easily convert a dictionary in Python to VB.net.
for example if I had a function that took a list and I want to make it when passing it in Python it would be:
function(['Hello', 'World!'])
If I wanted to do that in VB.net I would:
function({"Hello", "World"})
But I want to know if that is possible with dict's. Such as this in Python:
function({'key': 'value', 'key2': 'value2'})
If converting that to VB.net is not possible then is there a way I could pass a list of strings and convert it from a list to a dictionary?
Dictionary and SortedDictionary are inbuilt types in the .NET Framework, so you should be fine.
This is C# - don't know VB:
Dictionary dct = new Dictionary() { { "a", 1 }, { "b", 2 } };
That creates the dictionary and adds two members to it.
Cheers -

Python's json module, converts int dictionary keys to strings

I have found that when the following is run, python's json module (included since 2.6) converts int dictionary keys to strings.
>>> import json
>>> releases = {1: "foo-v0.1"}
>>> json.dumps(releases)
'{"1": "foo-v0.1"}'
Is there any easy way to preserve the key as an int, without needing to parse the string on dump and load.
I believe it would be possible using the hooks provided by the json module, but again this still requires parsing.
Is there possibly an argument I have overlooked?
Sub-question:
Thanks for the answers. Seeing as json works as I feared, is there an easy way to convey key type by maybe parsing the output of dumps?
Also I should note the code doing the dumping and the code downloading the json object from a server and loading it, are both written by me.
This is one of those subtle differences among various mapping collections that can bite you. JSON treats keys as strings; Python supports distinct keys differing only in type.
In Python (and apparently in Lua) the keys to a mapping (dictionary or table, respectively) are object references. In Python they must be immutable types, or they must be objects which implement a __hash__ method. (The Lua docs suggest that it automatically uses the object's ID as a hash/key even for mutable objects and relies on string interning to ensure that equivalent strings map to the same objects).
In Perl, Javascript, awk and many other languages the keys for hashes, associative arrays or whatever they're called for the given language, are strings (or "scalars" in Perl). In perl $foo{1}, $foo{1.0}, and $foo{"1"} are all references to the same mapping in %foo --- the key is evaluated as a scalar!
JSON started as a Javascript serialization technology. (JSON stands for JavaScript Object Notation.) Naturally it implements semantics for its mapping notation which are consistent with its mapping semantics.
If both ends of your serialization are going to be Python then you'd be better off using pickles. If you really need to convert these back from JSON into native Python objects I guess you have a couple of choices. First you could try (try: ... except: ...) to convert any key to a number in the event of a dictionary look-up failure. Alternatively, if you add code to the other end (the serializer or generator of this JSON data) then you could have it perform a JSON serialization on each of the key values --- providing those as a list of keys. (Then your Python code would first iterate over the list of keys, instantiating/deserializing them into native Python objects ... and then use those for access the values out of the mapping).
No, there is no such thing as a Number key in JavaScript. All object properties are converted to String.
var a= {1: 'a'};
for (k in a)
alert(typeof k); // 'string'
This can lead to some curious-seeming behaviours:
a[999999999999999999999]= 'a'; // this even works on Array
alert(a[1000000000000000000000]); // 'a'
alert(a['999999999999999999999']); // fail
alert(a['1e+21']); // 'a'
JavaScript Objects aren't really proper mappings as you'd understand it in languages like Python, and using keys that aren't String results in weirdness. This is why JSON always explicitly writes keys as strings, even where it doesn't look necessary.
Answering your subquestion:
It can be accomplished by using json.loads(jsonDict, object_hook=jsonKeys2int)
def jsonKeys2int(x):
if isinstance(x, dict):
return {int(k):v for k,v in x.items()}
return x
This function will also work for nested dicts and uses a dict comprehension.
If you want to to cast the values too, use:
def jsonKV2int(x):
if isinstance(x, dict):
return {int(k):(int(v) if isinstance(v, unicode) else v) for k,v in x.items()}
return x
Which tests the instance of the values and casts them only if they are strings objects (unicode to be exact).
Both functions assumes keys (and values) to be integers.
Thanks to:
How to use if/else in a dictionary comprehension?
Convert a string key to int in a Dictionary
Alternatively you can also try converting dictionary to a list of [(k1,v1),(k2,v2)] format while encoding it using json, and converting it back to dictionary after decoding it back.
>>>> import json
>>>> json.dumps(releases.items())
'[[1, "foo-v0.1"]]'
>>>> releases = {1: "foo-v0.1"}
>>>> releases == dict(json.loads(json.dumps(releases.items())))
True
I believe this will need some more work like having some sort of flag to identify what all parameters to be converted to dictionary after decoding it back from json.
I've gotten bitten by the same problem. As others have pointed out, in JSON, the mapping keys must be strings. You can do one of two things. You can use a less strict JSON library, like demjson, which allows integer strings. If no other programs (or no other in other languages) are going to read it, then you should be okay. Or you can use a different serialization language. I wouldn't suggest pickle. It's hard to read, and is not designed to be secure. Instead, I'd suggest YAML, which is (nearly) a superset of JSON, and does allow integer keys. (At least PyYAML does.)
Here is my solution! I used object_hook, it is useful when you have nested json
>>> import json
>>> json_data = '{"1": "one", "2": {"-3": "minus three", "4": "four"}}'
>>> py_dict = json.loads(json_data, object_hook=lambda d: {int(k) if k.lstrip('-').isdigit() else k: v for k, v in d.items()})
>>> py_dict
{1: 'one', 2: {-3: 'minus three', 4: 'four'}}
There is filter only for parsing json key to int. You can use int(v) if v.lstrip('-').isdigit() else v filter for json value too.
Convert the dictionary to be string by using str(dict) and then convert it back to dict by doing this:
import ast
ast.literal_eval(string)
I made a very simple extension of Murmel's answer which I think will work on a pretty arbitrary dictionary (including nested) assuming it can be dumped by JSON in the first place. Any keys which can be interpreted as integers will be cast to int. No doubt this is not very efficient, but it works for my purposes of storing to and loading from json strings.
def convert_keys_to_int(d: dict):
new_dict = {}
for k, v in d.items():
try:
new_key = int(k)
except ValueError:
new_key = k
if type(v) == dict:
v = _convert_keys_to_int(v)
new_dict[new_key] = v
return new_dict
Assuming that all keys in the original dict are integers if they can be cast to int, then this will return the original dictionary after storing as a json.
e.g.
>>>d = {1: 3, 2: 'a', 3: {1: 'a', 2: 10}, 4: {'a': 2, 'b': 10}}
>>>convert_keys_to_int(json.loads(json.dumps(d))) == d
True
[NSFW] You can write your json.dumps by yourself, here is a example from djson: encoder.py. You can use it like this:
assert dumps({1: "abc"}) == '{1: "abc"}'

Categories

Resources