Use Python reserved words in an XML File - python

I'm currently trying to use python's (3.6) xml.etree.ElementTree commands to write an xml file. Some of the Elements and Subelements I need to write must have "id" and "map" fields, which are reserved python words.
My problem is contained in the following line of code:
ET.SubElement(messages,'trigger',thing='1',bob='a', max='5')
But "max" is a function and I can't use it. Is there a character I can place there to allow me to write this field as I desire? Or some sort of known workaround?
EDIT: I am aware that an '_' stops the python from processing the word, but unfortunately this underscore will show up in my file...so I am trying to see if there is an 'invisible' option for the file I will later be writing.
Thanks much!

Python functions are no problem in the left side of a keyword expression:
>>> def abc(**kwargs):
print kwargs
>>> abc(id=2)
{'id': 2}
>>>
id, map, int, float, str, repr, etc. are built in symbols, not reserved words. You may use them like any other bunch of letters, but assigning it another value replaces the built in symbol:
>>> int(2.5)
2
>>> int = "5"
>>> int(2.5)
Traceback (most recent call last):
File "<pyshell#10>", line 1, in <module>
int(2.5)
TypeError: 'str' object is not callable
Notice how the first line is entirely legal, but will trigger a warning if you have a good IDE like pycharm.
If you want to send a actual reserved word to a function, like print, None, yield, or try, you can use the double star ** to convert a dictionary into keyword arguments, for example:
>>> abc(**{"print":2, "None":3})
{'print': 2, 'None': 3}
I hope this answers your question!

Related

Store formatted strings, pass in values later?

I have a dictionary with a lot of strings.
Is it possible to store a formatted string with placeholders and pass in a actual values later?
I'm thinking of something like this:
d = {
"message": f"Hi There, {0}"
}
print(d["message"].format("Dave"))
The above code obviously doesn't work but I'm looking for something similar.
You use f-string; it already interpolated 0 in there. You might want to remove f there
d = {
# no f here
"message": "Hi There, {0}"
}
print(d["message"].format("Dave"))
Hi There, Dave
Issue: mixing f-String with str.format
Technique
Python version
f-String
since 3.6
str.format
since 2.6
Your dict-value contains an f-String which is immediately evaluated.
So the expression inside the curly-braces (was {0}) is directly interpolated (became 0), hence the value assigned became "Hi There, 0".
When applying the .format argument "Dave", this was neglected because string already lost the templating {} inside. Finally string was printed as is:
Hi There, 0
Attempt to use f-String
What happens if we use a variable name like name instead of the constant integer 0 ?
Let's try on Python's console (REPL):
>>> d = {"message": f"Hi There, {name}"}
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'name' is not defined
OK, we must define the variable before. Let's assume we did:
>>> name = "Dave"; d = {"message": f"Hi There, {name}"}
>>> print(d["message"])
Hi There, Dave
This works. But it requires the variable or expression inside the curly-braces to be valid at runtime, at location of definition: name is required to be defined before.
Breaking a lance for str.format
There are reasons
when you need to read templates from external sources (e.g. file or database)
when not variables but placeholders are configured independently from your source
Then indexed-placeholders should be preferred to named-variables.
Consider a given database column message with value "Hello, {1}. You are {0}.". It can be read and used independently from the implementation (programming-language, surrounding code).
For example
in Java: MessageFormat.format(message, 74, "Eric")
in Python: message.format(74, 'Eric').
See also:
Format a message using MessageFormat.format() in Java

Python-string formatting with variable length

I'm trying to pad dynamic elements within a table, but it seems as though the native padding function doesn't work with variables. Just wondering if I'm doing something wrong or if there are simple alternatives to center padding. I know of ljust and rjust but there is no m(iddle)just for some reason.
Simple example:
a=10
b='hi'
print(f'{b:^a}')
or
a=10
b='hi'
print('{:^a}'.format(b))
produces
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: Unknown format code 'a' for object of type 'str'
Typing 10 in place of a in the print statement makes it work as intended, so I'm guessing 'a' is being interpreted as a string by the string formatted. Is a helper function the only way out here?
In [114]: print(f'{b:^{a}}')
hi
In [115]: print(f'"{b:^{a}}"')
" hi "
Probably want to add another set of brackets
a=10
b='hi'
print(f'{b:^{a}}')

Slicing a string from inside a formatted string gives 'TypeError: string indices must be integers'

Shouldn't both these commands do the same thing?
>>> "{0[0:5]}".format("lorem ipsum")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: string indices must be integers
>>> "{0}".format("lorem ipsum"[0:5])
'lorem'
The commands
>>> "{0[0]}".format("lorem ipsum")
'l'
and
>>> "{0}".format("lorem ipsum"[0])
'l'
evaluate the same. (I know that I can use other methods to do this, I am mainly just curious as to why it dosen't work)
The str.format syntax is handled by the library and supports only a few “expression” syntaxes that are not the same as regular Python syntax. For example,
"{0[foo]}".format(dict(foo=2)) # "2"
works without quotes around the dictionary key. Of course, there are limitations from this simplicity, like not being able to refer to a key with a ] in it, or interpreting a slice, as in your example.
Note that the f-strings mentioned by kendall are handled by the compiler and (fittingly) use (almost) unrestricted expression syntax. They need that power since they lack the obvious alternative of placing those expressions in the argument list to format.

Print words using string module and ascii in python?

I was curious about how ASCII worked in python, so I decided to find out more. I learnt quite a bit, before I began to try to print letters using ASCII numbers. I'm not sure if I am doing it correctly, as I am using the string module, but I keep picking up an error
print(string.ascii_lowercase(104))
This should print out "h", as far as I know, but all that happens is that I receive an error.
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
string.ascii_lowercase(104)
TypeError: 'str' object is not callable
If someone could help me solve this, or tell me a better way, I would be ever grateful. Thanks in advance! :)
ascii_lowercase is a string, not a function. Use chr(104).
I guess what you want is chr
>>> chr(104)
'h'
The chr() function returns the corresponding character to the ASCII value you put in.
The ord() function returns the ASCII value of the character you put in.
Example:
chr(104) = 'h'
ord('h') = 104

Python string formatting of multi-level dict

A common technique for rendering values from template strings looks like this:
>>> num = 7
>>> template = 'there were {num} dwarves'
>>> print template.format(**locals())
there were 7 dwarves
This approach works for any data type that has a __str__ method, e.g. dicts:
>>> data = dict(name='Bob', age=43)
>>> template = 'goofy example 1 {data}'
>>> print template.format(**locals())
goofy example 1 {'age': 43, 'name': 'Bob'}
However it doesn't work when a dict item is referenced by key:
>>> template = 'goofy example 2 {data["name"]}'
>>> print template.format(**locals())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: '"name"'
It's inconvenient, and seems odd, that an identifier that's valid in code outside the format string is invalid when used within the format string. Am I missing something? Is there a way to do this?
I'd like to be able to reference an element several layers down in a nested dictionary structure, like somedict['level1key']['level2key']['level3key']. So far my only workable approach has been to copy these values to a scalar variable just for string formatting, which is icky.
You can do it by using {data[name]} instead of {data["name"]} in the string.
The types of things you can specify in a format string are restricted. Arbitrary expressions aren't allowed, and keys are interpreted in a simplified way, as described in the documentation:
it is not possible to specify arbitrary dictionary keys (e.g., the strings '10' or ':-]') within a format string.
In this case, you can get your key out because it's a simple alphanumeric string, but, as the docs suggest, you can't always necessarily do it. If you have weird dict keys, you may have to change them to use them in a format string, or resort to other methods (like concatening string values explicitly with +).

Categories

Resources