How to use rsplit with None vaules in Python? - python

At my Python application, I want to get a specific value from a list:
rating_unit_value = clean_result['format']['tags'].get('itunextc', None).rsplit('|', 3)[0]
The Problem here is that if 'itunextc' does not exist, it should return None instead, where rsplit can't work with a None value. So, how can I apply the rsplit only if 'itunextc' exists? Of course this can be done with an if else statement or try except, but is this really the only way to go ?
Something like this pseudocode would be cool:
rating_unit_value = clean_result['format']['tags'].get('itunextc'.rsplit('|', 3)[0], None)
Thanks in advance.

Using an assignment expression and a conditional expression:
rating_unit_value = val.rsplit('|', 3)[0] if (val := clean_result['format']['tags'].get('itunextc')) else None
Whether that is clearer (or generally "better") than an if-else or a try-except, is really in the eye of the beholder.
Simplified example:
>>> a = dict(b='1|1')
>>> e = val.split('|') if (val := a.get('c')) else None
>>> print(e)
None
>>> e = val.split('|') if (val := a.get('b')) else None
>>> e
['1', '1']

Related

Python 1 liners as arguments to functions

I'm trying to add another condition here:
fword.write(' '.join([chr(c-13+97) if c-13+97>96 else chr(c-3+48) for c in ground_valid])+'\n')
fword.write(' '.join([chr(c-13+97) if c-13+97>96 else chr(c-3+48) for c in output_valid]))
But I cannot quite understand the python 1 liners. From my understanding, if I expand it will be:
for c in ground_valid:
if c-13+97>96:
fword.write(' '.join(chr(c-13+97)))
else if: # my condition
# instructions
else:
fword.write(' '.join(chr(c-3+48)))
I tried just that but I don't get the expected output. What am I doing wrong?
Thank you!
fword.write(' '.join([chr(c-13+97) if c-13+97>96 else chr(c-3+48) for c in ground_valid])+'\n')
Is equivalent to:
tmp_list = []
for c in ground_valid:
if c-13+97>96:
tmp_list.append(chr(c-13+97))
else:
tmp_list.append(chr(c-3+48))
tmp_str = ' '.join(tmp_list)
fword.write(tmp_str + '\n')
That is, [<expression> for <variable> in <sequence>] is a list comprehension that evaluates to a list - it's a shorthand form of map (the syntax also lets you filter as well, but that's not used in your example)
The expression in this case is chr(c-13+97) if c-13+97>96 else chr(c-3+48) which is the python format of a terniary operator. <expression1> if <condition> else <expression2> is equivelent to <condition> ? <expression1> : <expression2> in C, for example.
Your mistake is that you are calling join inside the loop, rather than constructing a list with the loop and calling join on the result.
This would be the analogue of your two one-liners:
# fword.write(' '.join([chr(c-13+97) if c-13+97>96 else chr(c-3+48) for c in ground_valid])+'\n')
lst = []
for c in ground_valid:
if c-13+97>96:
lst.append(chr(c-13+97))
else:
lst.append(chr(c-3+48))
fword.write(' '.join(lst)+'\n')
and
# fword.write(' '.join([chr(c-13+97) if c-13+97>96 else chr(c-3+48) for c in output_valid]))
lst = []
for c in output_valid:
if c-13+97>96:
lst.append(chr(c-13+97))
else:
lst.append(chr(c-3+48))
fword.write(' '.join(lst))
Do you appreciate them more now?
An alternative, and more compact (and more readable imho) version of your one-liners would be the following:
choises = {True: -13+97, False: -3+48}
fword.write(' '.join([chr(c + choises[c-13+97>96]) for c in ground_valid])+'\n')
fword.write(' '.join([chr(c + choises[c-13+97>96]) for c in output_valid]))
Having an if-else block without elifs should make you wonder if a dictionary would be better.

How to test if a string has capital letters

In Scala I could test if a string has a capital letter like this:
val nameHasUpperCase = name.exists(_.isUpper)
The most comprehensive form in Python I can think of is:
a ='asdFggg'
functools.reduce(lambda x, y: x or y, [c.isupper() for c in a])
->True
Somewhat clumsy. Is there a better way to do this?
The closest to the Scala statement is probably an any(..) statement here:
any(x.isupper() for x in a)
This will work in using a generator: from the moment such element is found, any(..) will stop and return True.
This produces:
>>> a ='asdFggg'
>>> any(x.isupper() for x in a)
True
Or another one with map(..):
any(map(str.isupper,a))
Another way of doing this would be comparing the original string to it being completely lower case:
>>> a ='asdFggg'
>>> a == a.lower()
False
And if you want this to return true, then use != instead of ==
There is also
nameHasUpperCase = bool(re.search(r'[A-Z]', name))

Concat string if condition, else do nothing

I want to concat few strings together, and add the last one only if a boolean condition is True.
Like this (a, b and c are strings):
something = a + b + (c if <condition>)
But Python does not like it. Is there a nice way to do it without the else option?
Thanks! :)
Try something below without using else. It works by indexing empty string when condition False (0) and indexing string c when condition True (1)
something = a + b + ['', c][condition]
I am not sure why you want to avoid using else, otherwise, the code below seems more readable:
something = a + b + (c if condition else '')
This should work for simple scenarios -
something = ''.join([a, b, c if condition else ''])
It is possible, but it's not very Pythonic:
something = a + b + c * condition
This will work because condition * False will return '', while condition * True will return original condition. However, You must be careful here, condition could also be 0 or 1, but any higher number or any literal will break the code.
Is there a nice way to do it without the else option?
Well, yes:
something = ''.join([a, b])
if condition:
something = ''.join([something, c])
But I don't know whether you mean literally without else, or without the whole if statement.
a_list = ['apple', 'banana,orange', 'strawberry']
b_list = []
for i in a_list:
for j in i.split(','):
b_list.append(j)
print(b_list)

Python ternary_operator (do-somthing if flag else do-another)

Is there method by using python if/else (ternary_operator) to achieve this function:
flag = True # or False
if flag:
print 'abc'
else:
pass
I tried to using:
print 'abc' if flag else ''
But a blank line will be print if the flag == False. Because:
print 'abc' if flag else '' == print ('abc' if flag else '')
Is there any way can make print nothing if flag == False without using ;?
Thanks in advance.
By the way, I'v tried using lambda, but it wasn't successful, here my code:
a = lambda x: x if False else None
print a(1)
Result:
>> python a.py
None
In Python 2.X print is a statement while in 3.X print is a function.
You can do from __future__ import print_function and print will now be a function. You can then do print("abc") if condition else None if you want to print in an expression. Note that the value of the expression is always None, but it may or may not print "abc" depending on the value of condition.
You may want to reconsider your programming style. It can be confusing with side-effects, like printing, happening in expressions. Furthermore, Python isn't ideal for functional programming, in my opinion, for a number of reasons. For example:
There are no proper tail calls so you would easily get stack overflows (or max recursion depth errors).
You cannot have statements in lambda-expressions. This includes yield statements that otherwise could be used to mitigate the lack of tail calls.
Why not just:
if flag:
print "abc"
else:
# do something else
?
from __future__ import print_function
print('abc') if flag else None

Abbreviation for ternary operator in python

I seem to remember an abreviation for the ternary operator testing for existence. For example:
a = None
b = a if a else 'Not None!'
# b is now 'Not None!'
I thought it was something like this
a else 'Not None!'
but that doesn't work. Perhaps there is another way to abbreviate this using some other built-in type?
Nope, there is no abbreviation available.
Were you thinking about a or 'Not None!' instead?
And as a side note: ... if ... else ... is called an conditional expression; it is a ternary operator, but so is the SQL BETWEEN ... IN ... expression.
Yes, in your case there is an abbreviation.
b = a or 'Not None!'
is nearly equivalent to
b = a if a else 'Not None!'
The only difference is that a is evaluated once in the first case, and twice in the second. The value placed into b is the same in either case.
Also, realize that in either code, you may get unexpected results if a is not None, but still False-y. Consider what happens if a is 0.0, for example.
This doesn't really make sense to me
a = None
b = a if a else 'Not None!'
You're setting b to Not None! for any false value of a (including None)
Perhaps you were thinking
a = None
b = 'Not None!' if a is None else a
or something?
Anyway, except for the cases where you can get away with
b = a or 'Not None!'
or
b = a and 'Not None!'
There's no way to avoid mentioning a twice

Categories

Resources