1 line function to get middle letters, syntax error - python

Trying to write a one-line function that will take the input string and get the middle letter/letters depending on if the string is even or uneven. I get an error code saying there's a syntax error at the first len(s) after the else if. The third line of code should continue on the second line.
The code:
def get_middle(s):
return m = s[int(len(s/2))] if type(len(s)/2) is float else if
s[int(len(s)/2)-1:int(len(s)/2)]
The ERROR:
Traceback (most recent call last):
File "main.py", line 1, in <module>
from solution import *
File "/home/codewarrior/solution.py", line 2
return m = s[len(s/2)] if type(len(s)/2) is float else if
s[int(len(s)/2)-1:int(len(s)/2)]
^
SyntaxError: invalid syntax

type(len(s)/2) is float is not a check for even-odd length, as you can see below, both even and odd string lengths evaluate to True for the check you had, because both divisions are float values
4/2 = 2.0 and 5/2=2.5
In [16]: s = 'abcd'
In [17]: type(len(s)/2) is float
Out[17]: True
In [18]: s = 'abcde'
In [19]: type(len(s)/2) is float
Out[19]: True
Why not keep things simple by checking divisibility by 2 for even/odd length.
Check if the number is length is odd or even, and select middle characters accordingly.
def get_middle(s):
#If even length, select 2 characters
if len(s)%2 == 0:
return s[int(len(s)/2)-1:int(len(s)/2)+1]
#If odd length, select 1 character
else:
return s[int(len(s)/2)]
print(get_middle('a'))
print(get_middle('ab'))
print(get_middle('abc'))
print(get_middle('abcd'))
print(get_middle('abcde'))
The output will be
a
ab
b
bc
c
From here, we can easily write the one liner
def get_middle(s):
return s[int(len(s)/2)-1:int(len(s)/2)+1] if len(s)%2 == 0 else s[int(len(s)/2)]

The guys in the comments and other answers already answered your question but I want to extend them a bit with some life-style advice. Yes, the issue at hand is that you shouldn't have else if at the end, the correct syntax is foo if condition else bar. And also type(len(s)) is Float is an absurd way to check for oddness. Hopefully, you already got that from the comments.
However, I want to argue that writing things on 1 line just so you can brag about how smart you are is a very detrimental practice. Programs must be written for people to read, and only incidentally for machines to execute. Unless, you can truly make that one liner understandable, it makes no sense to write it like you did - rather prefer to write it on multiple lines to make any errors obvious. Prefer to think about the other people that will be reading this code more than 'oh, see how cool is that'.
Now if you really insist on writing short and concise code, that's ok and here's how you can actually rewrite the thing to be a meaningful one liner:
from math import ceil
def get_middle(s):
return s[ceil(len(s)/2 - 1): ceil(len(s)/2)]
I'll let you figure out why that works on your own.

Your code has syntax error because if cannot be on the second line unless you escape the new line and only expr if cond else expr is valid inline if-statement:
foo() if condition \
else bar()
And there's something you'll probably like: onelinerizer
Original post has another problem with even/odd check. To solve it in one line:
def get_middle(s):
return m = s[int(len(s/2))] if len(s)%2 != 0 else s[int(len(s)/2)-1:int(len(s)/2)]
Here uses %2 to get remainder.
Though comments saying int(len(s)/2) would fail, also it's not guaranteed to be floor of division, as far as I see it's equivalent as len(s)//2:
def get_middle(s):
return m = s[len(s)//2] if len(s)%2 != 0 else s[len(s)//2-1:len(s)//2]

Related

Does python operator not need condition statement?

I saw the code snippet that I think it is illegal, but not sure yet.
This is not exactly the same code, but I try to keep the original as much as I can.
def validate_check(string):
try:
len(string) > 0
# do something
except Error:
# do something
Doesn't len(string) > 0 have to be in condition statement? Or is it something python syntax?
Doesn't len(string) > 0 have to be in condition statement?
No, but the example you've provided doesn't make a ton of sense.
Here's a different, similar construction that might help:
x = input()
try:
10 / int(x)
except ZeroDivisionError:
print("Can't divide by zero")
except ValueError:
print("Can't convert to int")
The result of 10 / int(x) is calculated (to see whether it will raise an error), but the result of that calculation is thrown away.
The reason I say your example is a bit weird is because the comparison with zero will have no effect whatsoever. So while the code will serve as a way of testing whether len can be called on string, that's about all it'll do.
This is valid syntax. But if you write:
len(string) > 0
print("hi")
then "hi" will be printed regardless of the length of the string. The only relevance this statement has is that it will throw an exception when either string has no length, or the result of len(string) is not comparable to 0.
What the author of the code is doing is avoiding the more complicated check if isinstance(string, str) and string: (or, I guess, if isinstance(string, collections.abc.Sized) and len(string) > 0).
If string is None, the len function will raise an error.
Perhaps it's the reason why your function is named validate_check.

SyntaxError: can't assign to function call Python 3.3

I would like to know what SyntaxError: can't assign to function call (<string>, line 6) means in relation to my specific line of code. I've looked around just about everywhere and I'm not getting anything I understand, simply because I just started learning code yesterday and much of what everyone else has mixed in with their strings of code is confusing.
Here is what I have entered:
name = 'Hayley'
print(len(name))
while len(name) < 10:
print('k')
len(name) = len(name) + 1
print('Done.')
I want the program to add 1 to the length of the name until it isn't less than ten anymore. It starts off at 6 and then increases by 1 until it hits 10 and the program doesn't run anymore.
I'm just trying to practice with loops and using a lot of meaningless things just to practice and make sure it sticks in my head. I'm trying to learn to code for an internship I will work at this summer.
Better to remember while a beginner,
if there is parantheses(round bracket) in the left side of an assignment, you should check it again and be extra careful.
len("arg")
is a function called with the argument "arg" and it already returns a value. Therefore cannot be assigned to something, something can be assigned to it.
I cannot truly help you because of not knowing exactly what you are trying to do. But what you expected to happen while you tried to increase the length of the string, by using the function to measure the length alone. Study on what you exactly want and you will get closer to the answer, like in all other subjects.
len(name) returns you the length of "Hayley" in your code above. You cannot assign another value to it. Perhaps you meant to do this:
>>> name = "Hayley"
>>> x = len(name)
>>> print(x)
6
In [2]:
>>> while x < 10:
>>> print('k')
>>> x += 1
>>> print('Done.')
k
k
k
k
Done.

def that takes a string and returns first half lower case and second part upper

I'm new to python and want help cleaning up my code.
I had to make a definition that takes a string and returns the first half lowercase and second part uppercase.
This is my code - but I can't help think there's a cleaner way to write this.
def sillycase(string):
x = len(string)/2
y = round(x)
print (string[:y].lower() + string[y:].upper())
It looks pretty good already, but as mentioned, it was not returning anything. How about this?
def sillycase(string):
y = round(len(string)/2)
return string[:y].lower() + string[y:].upper()
As I mentioned in comments, your current method is returning None. If you're just printing values out, you're not actually returning anything back to the caller.
Ultimately though, this can be cleaned up a great deal. You don't have to bother with the concatenation if you use format instead. Also, if you're dealing with integer division, it will always round down to the nearest integral - so there's no benefit in calling round. The double-slash // operator enforces that behavior, so it'll work the same between Python versions.
def sillycase(s):
half = len(s)//2
return "{}{}".format(s[:half].lower(), s[half:].upper())
Take it in steps. First of all, how do you return values from a function?
def return_True():
return True
def return_half(x):
return x/2
Second, how do you pull pieces out of a string?
In [1]: "abc"[:2]
Out[1]: "ab"
In [2]: "abc"[2:]
Out[2]: "c"
Third, how do you get a whole number from division?
In [1]: 5/2
Out[1]: 2.5 # 2 in Python2, but don't rely on that
In [2]: 5//2
Out[2]: 2 # in both Python2 and Python3
Fourth, how do you manipulate cases of a string?
In [1]: "TeSt".upper()
Out[1]: "TEST"
In [2]: "TeSt".lower()
Out[2]: "test"
Finally let's put it all together:
def sillycase(s):
mid_point = len(s) // 2
first_half = s[:midpoint]
second_half = s[midpoint:]
return first_half.lower() + second_half.upper()

How to add numbers and letters in a string in Python3.3.5 (The final result should be an int)?

My assignment is:
"Write a function sumOfDigits that has one parameter of type string. The function should return the
sum of the digits in the string. Do not treat multiple digit string as one number – “2014” should be
treated as 4 different digits of 2, 0, 1, 4. The function should return 17 for the string “Today’s date
is 09/01/2014”. You can assume the parameter is a string. No need to do any type validation."
Here's what I've got so far (with appropriate indentation):
def sumOfDigits (string1: str):
summation=0
for i in string1:
summation=summation + int (i)
return (summation)
print (sumOfDigits ('543tf'))
I get the following error:
"Traceback (most recent call last):
File "C:\Users\Andrew\Desktop\lab3.py", line 45, in <module>
print (sumOfDigits ('543tf'))
File "C:\Users\Andrew\Desktop\lab3.py", line 42, in sumOfDigits
summation=summation + int (i)
ValueError: invalid literal for int() with base 10: 't'"
How do I solve this? Is it doing this because of the difficulties associated with adding an int and string/char?
The problem is that int(x) fails unless x is a digit. The solution is to sum only the digits. For this purpose, python has the string method isdigit. For example:
>>> s = '543tf'
>>> sum(int(x) for x in s if x.isdigit())
12
And:
>>> s = "Today’s date is 09/01/2014"
>>> sum(int(x) for x in s if x.isdigit())
17
Python3
Unicode has added a large number of characters and python classifies some of them as digits even if int does not accept them. One such example is superscript 3: ³. To deal with this, python3 has introduced isdecimal and made it more discriminating than isdigit. Thus, in python3, one can use:
>>> s = "Today’s date is 09/01/2014 See footnote³"
>>> sum(int(x) for x in s if x.isdecimal())
17
You can do type-checking like what the other people have mentioned, or just pass the exception in the following manner (with minimal modification to your code so it is easy to see how it works):
def sumOfDigits (string1):
summation=0
for i in string1:
try:
summation = summation + int(i)
except:
pass
return (summation)
This is one of the philosophies of Python that says that you assume that the input is correct and only catch the exceptions and handle them separately. You might even want to explicitely check for the ValueError rather than catching all exceptions. Bit the details depend upon you.
You can't cast a char to an int and expect it to return 0 if it's not an int and its numerical value otherwise. You need to split up the string, check if the characters represent integers, and add those up. Like this:
def sumdigits(mystring):
summation = 0
for letter in list(mystring):
if letter.isdigit():
summation += int(letter)
return summation
This will do the trick:
sum(int(d) for d in '09/01/2014' if d.isdigit())
but I don't recommend handing it in without being able to explain how it works :-)
You could also try figuring out how
sum(map(int,filter(str.isdigit,'09/01/2014')))
works.
Your attempt is not failing 'because of difficulties of adding ints to char' (at least not directly), it's actually failing before that: when you try to convert something that doesn't look remotely like a number ('t') into an int. Which is what the error message is trying to tell you (right at the very bottom: 'ValueError etc.'). How do you solve it? You remove the stuff that can't be converted to int before attempting the conversion. The two code samples I gave you contain hints suggesting two different ways you might do it.
There are many ways to skin this cat.
One is to use a regex to find the single digits:
>>> import re
>>> re.findall(r'(\d)', '543tf')
['5', '4', '3']
Put that inside of map and convert to ints:
>>> map(int, re.findall(r'(\d)', '543tf'))
[5, 4, 3]
Put that into sum to sum the list:
>>> sum(map(int, re.findall(r'(\d)', '543tf')))
12

Parsing string to see if it can be cast to a float

Part of my homework assignment is to write a function that will parse a string such as '-.4e-4' and identify any problems that would prevent it from being cast to a float. For example, in '10e4.5' I would need to detect the decimal in the exponent and provide a relevant error message.
I have attempted many things. The first and, of course, most basic is the try: except:. Attempt to cast it to a float and let Python do the heavy lifting. However, as far as I can see, the errors it can return are not descriptive enough for this assignment.
The second thing I tried was to normalize the string, replacing all digits with n, signs with s, decimals with d, exponents with e (the maketrans function from C made this very fast). Then, I cut down any repeated n's to a single n. I made a list of all valid float formats and checked if the normalized string was in that list. AKA, I white-listed it. It worked perfectly and rather time-efficiently, but again, no error checking. That code is posted below.
import string,time
check_float_trans = string.maketrans("nsd0123456789-+.","???nnnnnnnnnnssd")
check_float_valids = 'n sn sndn ndn ndnen dn sdn sdnen sdnesn dnesn dnen nen nesn snesn sn snen sndnen sndnesn ndnesn'.split()
def check_float( test ):
"""Check if string <test> could be cast as a float, returns boolean."""
test = test.translate(check_float_trans)
test = ''.join([a for a,b in zip(test, ' '+test) if a != b])
return test in check_float_valids
I was hoping someone here could give me some pointers. I don't want this handed to me, but I am relatively stuck. I tried guardian-coding it, trying to identify reasons why the string might not be castable as a float, but I could never put up enough walls to ensure that no bad strings got a false positive.
Thanks.
Here's what I would do... (also this is untested)
def isValid(expression):
if 'e' in expression:
number, exponent = expression.split('e')
else:
print "not a valid format, no 'e' in expression"
return False
# a bunch of other if statments here to check for
#certain conditions like '.' in the exponent component
return float(number) ** float(exponent)
if __name__ == '__main__':
print isValid('-.4e-4')
print isValid('10e4.5')

Categories