# if/elif calculations with lists [closed]

I'm struggling to remember any Python code, I use it so infrequently. I want to write a simple `if` / `elif` statement but using any value from a list like a Boolean `IN` statement. So instead of:

``````def Type(fld):
if fld == "Neighborhood":
value = 1
elif fld == "Apartment":
value = 2
elif fld == "Condo":
value = 3
return value‍‍‍‍‍‍‍‍
``````

I want something like:

``````def Type(fld):
if fld == ["Neighborhood", "Block", "Locality"]:
value = 1
elif fld == ["Apartment", "Unit"]:
value = 2
elif fld == ["Condo", "Penthouse"]:
value = 3
return value‍‍‍‍‍‍‍‍
``````

But I can't get it to run. How should I structure this?

Use in:

``````def btype(fld):
if fld in ["Neighborhood", "Block", "Locality"]:
value = 1
elif fld in ["Apartment", "Unit"]:
value = 2
elif fld in ["Condo", "Penthouse"]:
value = 3
else:
value = 999 # or whatever you want, for example None
return value‍‍‍‍‍‍‍‍
``````

call with:

``````btype(!your_actual_fieldname_here!)
``````
• This use pattern calls for a dictionary. May 20, 2021 at 11:13
• It is another possibility. But since the if's and lists are already written I didnt bother writing a dictionary
– BERA
May 20, 2021 at 11:16
• I should have mentioned this will be used in ArcMap Field Calculator, so this is the structure I'm more familiar with. May 21, 2021 at 10:11
• Ok! Both answers should work in field calculator
– BERA
May 21, 2021 at 11:58

The Pythonic solution is to use a dictionary.

``````def fldAsType(fld):
fldLookup = {
"Neighborhood" : 1,
"Block" : 1,
"Locality" : 1,
"Apartment" : 2,
"Unit" : 2,
"Condo" : 3,
"Penthouse" : 3,
}
try:
return fldLookup[fld]
except:
return -999
``````

Note that "Type" is a dangerous name, because of the built-in `type` operator.

Conforming to the PEP 8 style guide will make your code integrate more easily with code found on the web. The relevant piece is that classes start with upper-case and methods with lower-case.

So I just got a chance to benchmark this in Python 2.7, and found that the "Pythonic" "EAFP" principle ("It's easier to ask for forgiveness than permission") didn't actually apply -- structuring this function as

``````def fldAsType(fld):
fldLookup = {
"Neighborhood" : 1,
"Block" : 1,
"Locality" : 1,
"Apartment" : 2,
"Unit" : 2,
"Condo" : 3,
"Penthouse" : 3,
}
return fldLookup[fld] if fld in fldLookup else -999
``````

was three times faster than using the exception handling, but was still four times slower than the `if`/`elif`/`else` cascade. Which seemed wrong. So I moved the lookup initialization outside the function definition:

``````fldLookup = {
"Neighborhood" : 1,
"Block"        : 1,
"Locality"     : 1,
"Apartment"    : 2,
"Unit"         : 2,
"Condo"        : 3,
"Penthouse"    : 3,
}
def fldAsType(fld):
return fldLookup[fld] if fld in fldLookup else -999
``````

And then the dictionary was 10% faster than `if`/`elif`/`else`.

Then I applied EAFP:

``````fldLookup = {
"Neighborhood" : 1,
"Block"        : 1,
"Locality"     : 1,
"Apartment"    : 2,
"Unit"         : 2,
"Condo"        : 3,
"Penthouse"    : 3,
}
def fldAsType(fld):
try:
return fldLookup[fld]
except:
return -999
``````

and the dictionary was now 35% faster without any failed lookups, but 16% slower if there were 2% None values in the lookup population.

So, the lessons here are:

• Never place dictionary initialization inside a method
• Only use EAFP when you're reasonably certain you won't need forgiveness

Benchmark script:

``````import random
import datetime

def fldAsType0(fld):
if fld in ["Neighborhood", "Block", "Locality"]:
value = 1
elif fld in ["Apartment", "Unit"]:
value = 2
elif fld in ["Condo", "Penthouse"]:
value = 3
else:
value = 999 # or whatever you want, for example None
return value

def fldAsType1(fld):
fldLookup = {
"Neighborhood" : 1,
"Block"        : 1,
"Locality"     : 1,
"Apartment"    : 2,
"Unit"         : 2,
"Condo"        : 3,
"Penthouse"    : 3,
}
try:
return fldLookup1[fld]
except:
return -999

def fldAsType2(fld):
fldLookup2 = {
"Neighborhood" : 1,
"Block"        : 1,
"Locality"     : 1,
"Apartment"    : 2,
"Unit"         : 2,
"Condo"        : 3,
"Penthouse"    : 3,
}
return fldLookup2[fld] if fld in fldLookup2 else -999

fldLookup3 = {
"Neighborhood" : 1,
"Block"        : 1,
"Locality"     : 1,
"Apartment"    : 2,
"Unit"         : 2,
"Condo"        : 3,
"Penthouse"    : 3,
}
def fldAsType3(fld):
return fldLookup3[fld] if fld in fldLookup3 else -999

def fldAsType4(fld):
try:
return fldLookup3[fld]
except:
return -999

# choices not in Python 2.7
def choices(population, weights=None, cum_weights=None, k=1):
result = []
newpop = []
for p in population:
for w in weights:
newpop.append(p)
for i in range(k):
result.append(random.choice(newpop))

return result

# Generate 100000 values (even distribution)

random.seed(12345)
sampleSize      = 1000000
uniformDistro   = []
sortedDistro    = []

options1 = ["Neighborhood", "Block", "Locality", "Apartment", "Unit", "Condo", "Penthouse"]
options2 = sorted(options1)
options3 = random.sample(options1, k=len(options1))
options3.append(None)
options4 = random.sample(options1, k=len(options1))

for i in range(sampleSize):
uniformDistro.append(random.choice(options1))
sortedDistro.append(random.choice(options2))

missingDistro  = choices(options3,[7,7,7,7,7,7,7,1],k=sampleSize)
weightedDistro = choices(options4,[21,13,8,5,3,2,1],k=sampleSize)

start = datetime.datetime.utcnow()
for v in uniformDistro:
t = fldAsType0(v)
print("{:d} : {:12s} : {:7.3f}".format(0,"Uniform",(datetime.datetime.utcnow() - start).total_seconds()))

start = datetime.datetime.utcnow()
for v in sortedDistro:
t = fldAsType0(v)
print("{:d} : {:12s} : {:7.3f}".format(0,"Sorted",(datetime.datetime.utcnow() - start).total_seconds()))

start = datetime.datetime.utcnow()
for v in missingDistro:
t = fldAsType0(v)
print("{:d} : {:12s} : {:7.3f}".format(0,"Missing",(datetime.datetime.utcnow() - start).total_seconds()))

start = datetime.datetime.utcnow()
for v in weightedDistro:
t = fldAsType0(v)
print("{:d} : {:12s} : {:7.3f}".format(0,"Fibonacci",(datetime.datetime.utcnow() - start).total_seconds()))

start = datetime.datetime.utcnow()
for v in uniformDistro:
t = fldAsType1(v)
print("{:d} : {:12s} : {:7.3f}".format(1,"Uniform",(datetime.datetime.utcnow() - start).total_seconds()))

start = datetime.datetime.utcnow()
for v in sortedDistro:
t = fldAsType1(v)
print("{:d} : {:12s} : {:7.3f}".format(1,"Sorted",(datetime.datetime.utcnow() - start).total_seconds()))

start = datetime.datetime.utcnow()
for v in missingDistro:
t = fldAsType1(v)
print("{:d} : {:12s} : {:7.3f}".format(1,"Missing",(datetime.datetime.utcnow() - start).total_seconds()))

start = datetime.datetime.utcnow()
for v in weightedDistro:
t = fldAsType1(v)
print("{:d} : {:12s} : {:7.3f}".format(1,"Fibonacci",(datetime.datetime.utcnow() - start).total_seconds()))

start = datetime.datetime.utcnow()
for v in uniformDistro:
t = fldAsType2(v)
print("{:d} : {:12s} : {:7.3f}".format(2,"Uniform",(datetime.datetime.utcnow() - start).total_seconds()))

start = datetime.datetime.utcnow()
for v in sortedDistro:
t = fldAsType2(v)
print("{:d} : {:12s} : {:7.3f}".format(2,"Sorted",(datetime.datetime.utcnow() - start).total_seconds()))

start = datetime.datetime.utcnow()
for v in missingDistro:
t = fldAsType2(v)
print("{:d} : {:12s} : {:7.3f}".format(2,"Missing",(datetime.datetime.utcnow() - start).total_seconds()))

start = datetime.datetime.utcnow()
for v in weightedDistro:
t = fldAsType2(v)
print("{:d} : {:12s} : {:7.3f}".format(2,"Fibonacci",(datetime.datetime.utcnow() - start).total_seconds()))

start = datetime.datetime.utcnow()
for v in uniformDistro:
t = fldAsType3(v)
print("{:d} : {:12s} : {:7.3f}".format(3,"Uniform",(datetime.datetime.utcnow() - start).total_seconds()))

start = datetime.datetime.utcnow()
for v in sortedDistro:
t = fldAsType3(v)
print("{:d} : {:12s} : {:7.3f}".format(3,"Sorted",(datetime.datetime.utcnow() - start).total_seconds()))

start = datetime.datetime.utcnow()
for v in missingDistro:
t = fldAsType3(v)
print("{:d} : {:12s} : {:7.3f}".format(3,"Missing",(datetime.datetime.utcnow() - start).total_seconds()))

start = datetime.datetime.utcnow()
for v in weightedDistro:
t = fldAsType3(v)
print("{:d} : {:12s} : {:7.3f}".format(3,"Fibonacci",(datetime.datetime.utcnow() - start).total_seconds()))

start = datetime.datetime.utcnow()
for v in uniformDistro:
t = fldAsType4(v)
print("{:d} : {:12s} : {:7.3f}".format(4,"Uniform",(datetime.datetime.utcnow() - start).total_seconds()))

start = datetime.datetime.utcnow()
for v in sortedDistro:
t = fldAsType4(v)
print("{:d} : {:12s} : {:7.3f}".format(4,"Sorted",(datetime.datetime.utcnow() - start).total_seconds()))

start = datetime.datetime.utcnow()
for v in missingDistro:
t = fldAsType4(v)
print("{:d} : {:12s} : {:7.3f}".format(4,"Missing",(datetime.datetime.utcnow() - start).total_seconds()))

start = datetime.datetime.utcnow()
for v in weightedDistro:
t = fldAsType4(v)
print("{:d} : {:12s} : {:7.3f}".format(4,"Fibonacci",(datetime.datetime.utcnow() - start).total_seconds()))

#EOF
``````