How to use if else on a non-existant value - python

The contents of the ScheduledStartDate list is either None or a string.
How can I change my codes below to detect and skip the ScheduledStartDate[j] that contains None? And only run the statements when it is not None.
j = 0
while j< len1:
if (ScheduledStartDate[j] == None):
else:
ScheduledStartDate[j] = datetime.datetime.strptime(ScheduledStartDate[j], format)
j=j+1

To my understanding this looks like it should work, however you may want to remove the else statement and just change the logic of your if statement.
j = 0
while j< len1:
if ScheduledStartDate[j] is not None:
ScheduledStartDate[j] = datetime.datetime.strptime(ScheduledStartDate[j], format)
j=j+1
If your objective is to actually remove the None values then you can see how it's done here. Otherwise there is no way to know which values are None and which are strings without going through the entire list.
Also on another note, if you'd like your code to have that nice color scheme you see in all other questions, add the python tag to the question. Makes your code easier to read.

Related

How to prevent variable from being changed to "None" if the field is blank in python

I am trying to read a cell in an excel file and assign it to a variable. The problem comes when the cell is blank. Then the variable is assigned the string "None". I want it to be blank (""). Is there an easy way of doing this in one line in Python? Something like this?
a = str(sheet.cell(row=3, column=2).value) if (a != "None") else: a = ""
My goal is to achieve this without writing (sheet.cell(row=3, column=2).value), multiple times. Since i have a lot of other variables to check and that makes it harder to maintain.
Your approach is dangerous if you ever have a cell with the value "None". The most pythonic way to do this is in two lines:
v = sheet.cell(row=3, column=2).value
a = str(v) if v is not None else ''
Writing sheet.cell(row=3, column=2).value multiple times causes unnecessary accesses to the sheet object, so your goal of avoiding it is good. However, your goal of writing it in one line should be secondary to the goal of writing it well.
A couple of one-liners, that aren't going to replace a good old "assign then test" 2-line method:
Create a generator and iterate on a one-element list, which allows to assign to a variable, then use a ternary on this variable, use next to iterate once and get the value:
v = next("" if x is None else str(x) for x in [sheet.cell(row=3, column=2).value])
Maybe more interesting: if the values cannot be 0, you could use or:
v = str(sheet.cell(row=3, column=2).value or "")
now is it worth saving one line? I'll let you figure it out.
You can split it in a couple of lines, it will feel better, and you have several options:
res = str(sheet.cell(row=3, column=2).value)
a = "" if res == "None" else res
or another option for example:
a = {"None" : ""}.get(res, res)

Python3: for-loop break and else (if statement)

Background information:
hey,
I want to do the following: I have a dictionary with IDs as keys and lists with various things as value. One of the items of the value is a string. I want to check, if a list contains this string. And I want to do it for all keys in my dictionary.
If the list contains the string, I want to print "String is valid"
If the list does not contain the string, I want to print "String is NOT valid"
So far, so good.
Furthermore, the lists I want to check depend on one console input of the user, which specifies, which list should be checked. The console input is "number".
My idea was to iterate over my dictionary and my list with a nested for-loop and compare, if the string(the item of the value) is equal to any list item. If it is, I want to break out of the loop. If the String is not found in the list, I want to execute the else-statement to print my "String is not valid" message.
Code snippet:
def validationHelper(myDict, myList):
for key in myDict:
for value in myDict[key][0]:
for item in myList:
if value==item:
validationHelper.true="String is valid"
break
else:
validationHelper.true="Warning: String is NOT valid"
def validation(anyList,helperfunc):
if anyList=="one":
return helperfunc(finalDict,myList1)
if anyList=="two":
return helperfunc(finalDict,myList2)
if anyList=="three":
return helperfunc(finalDict,myList3)
validation(number, validationHelper)
print(validationHelper.true)
Problem:
I am running this, but no matter if the string is in the list or not, I always get my printout for the else-statement. So, I guess I have an error in reasoning in my for-loop? Or maybe, I did not understand for-loops at all?! I have tried out different indentions with the else-statement, but couldnt solve my problem.
I would suggest you to change your function the following way (without changing the logic):
def validationHelper(myDict, myList):
for key in myDict:
for value in myDict[key][0]:
for item in myList:
if value==item:
return "String is valid" # Add here to exit
return "Warning: String is NOT valid" # will be returned inf nothing will be found in your 3 loops
def validation(anyList,helperfunc):
if anyList=="one":
return helperfunc(finalDict,myList1)
if anyList=="two":
return helperfunc(finalDict,myList2)
if anyList=="three":
return helperfunc(finalDict,myList3)
validation(number, validationHelper)
print(validationHelper)
This will help you to exit your 3 nested loops as it was mentioned in comments.
Because in the negative case on first wrong occurrence you don't need to check anything else.
Use return to break all of your loop. Having an else statement is not necessary if you don't have any if statement to begin with.
def validationHelper(myDict, myList):
for item in myList:
if item in myDict.values():
return ("String is valid")
return ("String is NOT valid")
def validation(anyList,helperfunc):
if anyList=="one":
return helperfunc(finalDict,myList1)
elif anyList=="two":
return helperfunc(finalDict,myList2)
elif anyList=="three":
return helperfunc(finalDict,myList3)
validation(number, validationHelper)
print(validationHelper.true)
Using elif instead of multiple if is a better practice. Be careful with indentions next time.
Also you might want to check .keys() and .values()
You can replace:
for key in myDict:
for value in myDict[key][0]:
with:
for value in myDict.values():
The other answers give a good explanation of how to break out of multiple loops. But you could also simplify your code by using Python's built-in functions and list comprehensions, like this:
def validationHelper(myDict, myList):
if any(v in myList for val in myDict.values() for v in val[0]):
validationHelper.true="String is valid"
else:
validationHelper.true="Warning: String is NOT valid"
def validation(anyList,helperfunc):
if anyList=="one":
return helperfunc(finalDict,myList1)
if anyList=="two":
return helperfunc(finalDict,myList2)
if anyList=="three":
return helperfunc(finalDict,myList3)
validation(number, validationHelper)
print(validationHelper.true)
This should be as efficient as your code, since any short circuits at the first match. And it may be a little more readable. (Note that multi-level list comprehensions go in the same order as regular for loops.)

Compare Two Lists and Create a List

I'm still trying to learn programming so please help me simplify this. I'm trying to run something that looks through the indices in my list and if it finds a 1 returns "yay" (just for debugging purposes). Here's what I have so far:
def replaceValues(distList, indexList):
for i in range (1,len(indexList)):
if indexList[i] = 1
return "yay!"
However, I get a syntax error whenever I run this, which underlines the 1. Please help!
Thanks!
Apart from incorrect indentation(fixed below), you are using = when you should be using ==, and you left out a colon from your if statement.
= is used to assign values
== evaluates equality(returning a boolean i.e True or False)
You left out a : in your if statement.
Corrected code:
def replaceValues(distList, indexList):
for i in range (1,len(indexList)):
if indexList[i] == 1:
return "yay!"
If you don't understand exactly how Python uses whitespace/indentation as an integral part of it's syntax/structure and other syntax basics, then you need to get on that i.e tutorials.. A quick google should turn up many. I recommend Udacity or Codeacademy
There are three syntax errors that I see.
First, you're using the = sign (assignment) when you need == (comparison).
Second, you're missing a colon at the end of your if statement.
Finally, you must* have an indented block after your if statement.
All together, it should read like this:
if indexList[i] == 1: # double-equals and colon
return "yay!" # This must be indented to the proper level
You should really go have a look at the tutorials; this is all stuff that's laid out very well there, and it's all critical to doing pretty much anything in Python.
*Technically, you can also follow an if statement with an expression on the same line (e.g. if 1: pass). However, I personally think this is hideous in almost every case.
= is an assignment statement. Example:
name = "tyler"
You should use == to check for equality of primitives (you're comparing integers, which are primitives).
Switch :
if indexList[i] = 1
to:
if indexList[i] == 1
Try it like this:
def replaceValues(distList, indexList):
for k in range(1, len(indexList)):
if indexList[k] == 1:
return "yay!"

Should I return an empty dict instead of None?

I have a method that currently returns None or a dict.
result,error = o.apply('grammar')
The caller currently has to check for the existence of two keys to decide what kind of object was returned.
if 'imperial' in result:
# yay
elif 'west' in result:
# yahoo
else:
# something wrong?
Because result can be None, I'm thinking of returning an empty dict instead, so the caller does not need to check for that. What do you think ?
For comparison, in the re module, the result of calling match can result in None.
p = re.compile('\w+')
m = p.match( 'whatever' )
But in this case, m is an object instance. In my case, I am returning a dict which should either be empty or have some entries.
Yes I think returning an empty dict (or where applicable an empty list) is preferable to returning None as this avoids an additional check in the client code.
EDIT:
Adding some code sample to elaborate:
def result_none(choice):
mydict = {}
if choice == 'a':
mydict['x'] = 100
mydict['y'] = 1000
return mydict
else:
return None
def result_dict(choice):
mydict = {}
if choice == 'a':
mydict['x'] = 100
mydict['y'] = 1000
return mydict
test_dict = result_dict('b')
if test_dict.get('x'):
print 'Got x'
else:
print 'No x'
test_none = result_none('b')
if test_none.get('x'):
print 'Got x'
else:
print 'No x'
In the above code the check test_none.get(x) throws an AttributeError as
result_none method can possibly return a None. To avoid that I have to add an
additional check and might rewrite that line as:
if test_none is not None and test_none.get('x') which is not at all needed
if the method were returning an empty dict. As the example shows the check test_dict.get('x') works fine as the method result_dict returns an empty dict.
I'm not entirely sure of the context of this code, but I'd say returning None suggests that there was somehow an error and the operation could not be completed. Returning an empty dictionary suggests success, but nothing matched the criteria for being added to the dictionary.
I come from a completely different background (C++ Game Development) so take this for what it's worth:
For performance reasons though, might be nice to return None and save whatever overhead, though minimal, may be involved in creating an empty dictionary. I find that, generally, if you're using a scripting language, you're not concerned about the performance of that code. If you were, you probably wouldn't be writing that feature in said language unless required for some unavoidable reason.
As others have said, an empty dict is falsy, so there's no problem there. But the idea of returning an empty dict leaves a bad taste in my mouth. I can't help but feel that returning an empty dict could hide errors that returning None would reveal. Still, it's just a gut feeling.
After more thought, I think returning an empty dict might be more Pythonic. A good rule of thumb might be to always return an empty container if you write a function/method which returns a container. Several examples of this behavior:
"".split() == []
filter(lambda a:False, [1,2]) == []
range(1, -1) == []
re.findall('x', '') = []
In contrast if you are trying to get a single object, you have no choice but to return None I suppose. So I guess None is like the empty container for single objects! Thanks to KennyTM for arguing some sense into me :D
Python supports returning multiple values. Hence, you can return a status of success along with an empty dictionary. The caller first verifies the return code and then uses the dictionary.
def result_none(choice):
mydict = {}
retcode = -1
if choice == 'a':
mydict['x'] = 100
mydict['y'] = 1000
retcode = 0
return mydict, retcode
retcode, mydict = result_none('a')
if retcode == 0:
<<use dictionary>>

Do I have to cause an ValueError in Python

I have this code:
chars = #some list
try:
indx = chars.index(chars)
except ValueError:
#doSomething
else:
#doSomethingElse
I want to be able to do this because I don't like knowfully causing Exceptions:
chars = #some list
indx = chars.index(chars)
if indx == -1:
#doSomething
else:
#doSomethingElse
Is there a way I can do this?
Note that the latter approach is going against the generally accepted "pythonic" philosophy of EAFP, or "It is Easier to Ask for Forgiveness than Permission.", while the former follows it.
if element in mylist:
index = mylist.index(element)
# ... do something
else:
# ... do something else
For the specific case where your list is a sequence of single-character strings you can get what you want by changing the list to be searched to a string in advance (eg. ''.join(chars)).
You can then use the .find() method, which does work as you want. However, there's no corresponding method for lists or tuples.
Another possible option is to use a dictionary instead. eg.
d = dict((x, loc) for (loc,x) in enumerate(chars))
...
index = d.get(chars_to_find, -1) # Second argument is default if not found.
This may also perform better if you're doing a lot of searches on the list. If it's just a single search on a throwaway list though, its not worth doing.

Categories