I'm trying to solve the following sets of coding challenges, but generate one error after another.
def checkingIfIn(a, direction=True,
d={'apple': 2, 'pear': 1, 'fruit': 19, 'orange': 5,
'banana': 3, 'grapes': 2, 'watermelon': 7}):
if direction == True:
if a in d is True:
return d[a]
else:
return False
else:
if a not in d:
return True
else:
return d[a]
Call the function so that it returns False and assign that function
call to the variable c_false
Call the fucntion so that it returns True and assign it to the
variable c_true
Call the function so that the value of fruit is assigned to the
variable fruit_ans
Call the function using the first and third parameter so that the
value 8 is assigned to the variable param_check
c_false = checkingIfIn('wwww',direction=True)
c_true = checkingIfIn('bbbbb',direction=False)
fruit_ans = checkingIfIn('fruit',True)
param_check = checkingIfIn('apple',True,(d(['pear']['watermelon'])))
print(c_false)
print(c_true)
print(fruit_ans)
print(param_check)
You're mixing stuff up.
1)
First off, the method is not d.keys[a], it's d.keys()
if a in d.keys()
2)
In your else case you're also being incoherent because you're writing
if a not in d
when it should be
if a not in d.keys()
3)
for fruit_ans you're assigning d='apple'. Now d is a string, not a dictionary, so of course it won't work (string don't have keys)
You're actually doing something useless by even passing something to d. You should be passing just
checkingIfIn('apple',True)
And this will check if key apple is contained in your dictionary d.
Otherwise you need to pass a proper dictionary to d
checkingIfIn('apple',True, d={'this':1,'is':2,'aProper':3,'dictionary':4})
4)
You're assigning an integer to d for the param_check. Which is the same error you made in point 3, passing something that is not a dictionary to d
5) Your comments for each function call are quite hard to figure out. It's not clear what you even want to achieve with this method but it's clearly in dire need to be reworked
EDIT:
This is what you get by using your method properly
if __name__ == "__main__":
#Call the function so that it returns False and
#assign that function call to the variable c_false
c_false = checkingIfIn('apple',direction=False)
#Call the fucntion so that it returns True and assign it to the
#variable c_true
c_true = checkingIfIn('apple',direction=True)
#Call the function so that the value of fruit is assigned to the
#variable fruit_ans
fruit_ans = checkingIfIn('apple',True,d={'apple':1})
#Call the function using the first and third parameter so that the
#value 8 is assigned to the variable param_check
param_check = checkingIfIn('apple',direction=True)
print(c_false)
print(c_true)
print(fruit_ans)
print(param_check)
And the output is as follows
2
apple
apple
apple
Which clearly isn't what you're trying to get, but again, your code and your comments aren't exactly easy to understand
def checkingIfIn(a, direction = True, d= {'apple': 2, 'pear': 1, 'fruit': 19, 'orange': 5, 'banana': 3, 'grapes': 2, 'watermelon': 7}):
if direction == True:
if a in d:
return d[a]
else:
return False
else:
if a not in d:
return True
else:
return d[a]
Call the function so that it returns False and assign that function call to the variable c_false
Call the fucntion so that it returns True and assign it to the variable c_true
Call the function so that the value of fruit is assigned to the variable fruit_ans
Call the function using the first and third parameter so that the value 8 is assigned to the variable param_check
c_false = checkingIfIn('wwww',direction=True)
c_true = checkingIfIn('bbbbb',direction=False)
fruit_ans = checkingIfIn('fruit',True)
param_check = checkingIfIn('apple',True,('pear')+('watermelon'))
print(c_false)
print(c_true)
print(fruit_ans)
print(param_check)
Related
I have a problem in python(python 3.9 on VS Code). I'm trying to change a value in a dictionary by some conditions:
def getset(age):
age['age']+=0 if age['age']>=0 else age['age'] == 0
mammad = {'name': 'mammad', 'age': -3}
mammad = getset(mammad)
print(mammad)
as you can see in age['age']+=0 if age['age']>=0 else age['age'] == 0 age key has to have a value of 0 if it's lower than 0. But anyway, it changes it to none. What's the problem?
You need to return the dict after you make changes to it (you are assigning None from the function call when it returns nothing) or just call the function without assigning it to your variable since it will modify the dict in-place anyway. You can change the dictionary like this:
def getset(age):
age['age'] = 0 if age['age'] < 0 else age['age']
mammad = {'name': 'mammad', 'age': -3}
# no need to 'assign' to 'mammad' again, you changed it already!
getset(mammad)
>>> print(mammad)
{'name': 'mammad', 'age': 0}
A function which returns nothing prints nothing (None).
>>> def f():
... pass
...
>>> print(f())
None
You should return the age. if you don't return anything it will be None.
I have a data structure that looks something like this:
someData = {"apple":{"taste":"not bad","colors":["red","yellow"]},
"banana":{"taste":"perfection","shape":"banana shaped"},
"some list":[6,5,3,2,4,6,7]}
and a list of keys which describes a path to some item in this structure
someList = ["apple","colors",2]
I already have a function getPath(path) (see below) that is supposed to return a pointer to the selected object. It works fine for reading, but I get into trouble when trying to write
print(getPath(someList))
>> yellow
getPath(someList) = "green"
>> SyntaxError: can't assign to function call
a = getPath(someList)
a = "green"
print(getPath(someList))
>> "yellow"
Is there a way to make this work? Maybe like this:
someFunc(someList, "green")
print(getPath(someList))
>> green
This question looks like this question, except that I want to write something to that item, and not just read it.
My actual data can be seen here (I used json.loads() to parse the data). Note that I plan on adding stuff to this structure. I want a general approach to future proof the project.
My code:
def getPath(path):
nowSelection = jsonData
for i in path:
nowSelection = nowSelection[i]
return nowSelection
The result you're getting from getPath() is the immutable value from a dict or list. This value does not even know it's stored in a dict or list, and there's nothing you can do to change it. You have to change the dict/list itself.
Example:
a = {'hello': [0, 1, 2], 'world': 2}
b = a['hello'][1]
b = 99 # a is completely unaffected by this
Compare with:
a = {'hello': [0, 1, 2], 'world': 2}
b = a['hello'] # b is a list, which you can change
b[1] = 99 # now a is {'hello': [0, 99, 2], 'world': 2}
In your case, instead of following the path all the way to the value you want, go all the way except the last step, and then modify the dict/list you get from the penultimate step:
getPath(["apple","colors",2]) = "green" # doesn't work
getPath(["apple","colors"])[2] = "green" # should work
You could cache your getPath using custom caching function that allows you to manually populate saved cache.
from functools import wraps
def cached(func):
func.cache = {}
#wraps(func)
def wrapper(*args):
try:
return func.cache[args]
except KeyError:
func.cache[args] = result = func(*args)
return result
return wrapper
#cached
def getPath(l):
...
getPath.cache[(someList, )] = 'green'
getPath(someList) # -> 'green'
You can't literally do what you're trying to do. I think the closest you could get is to pass the new value in, then manually reassign it within the function:
someData = {"apple":{"taste":"not bad","colors":["red","yellow"]}, "banana":{"taste":"perfection","shape":"banana shaped"}, "some list":[6,5,3,2,4,6,7]}
def setPath(path, newElement):
nowSelection = someData
for i in path[:-1]: # Remove the last element of the path
nowSelection = nowSelection[i]
nowSelection[path[-1]] = newElement # Then use the last element here to do a reassignment
someList = ["apple","colors",1]
setPath(someList, "green")
print(someData)
{'apple': {'taste': 'not bad', 'colors': ['red', 'green']}, 'banana': {'taste': 'perfection', 'shape': 'banana shaped'}, 'some list': [6, 5, 3, 2, 4, 6, 7]}
I renamed it to setPath to reflect its purpose better.
I'm learning about python class. In a toy python script,
class test():
def __init__(self, a, b):
self.new = a
self.old = b
def another_one(self):
temp = self.new
for key in temp.keys():
temp[key] += 1
def old_one(self):
old = self.old
old += 1
a = {'1': 1, '2': 2, '3': 3, '4': 4, '5': 5}
b = 5
test_pass = test(a, b)
test_pass.another_one(), test_pass.old_one()
a, b
I found that by running the method another_one of instance test_pass, dictionary a will be changed. However, integer b will not be altered by running the method old_one.
Why a dictionary will be changed while an integer will not?
Python integers are immutable, you can't change them in-place.
Take a look at the following snippet:
x = 2
print(id(x))
x += 1
print(id(x))
x = [2]
print(id(x))
x += [1]
print(id(x))
You can see that the first part, where the integer is being modified, the unique id() of the object changes. Afterwards x is a completely different object.
When modifying the list, its 'id()' does not change, the list is changes in-place.
The integer is immutable, they can't be magically turn into something different. Lists can.
Basically I'm looking for an implementation of itertools.product that allows me to change the order in which the combinations are generated.
Example: If I use itertools.product('AB', 'xy') it generates the combinations in this exact order:
[('A', 'x'), ('A', 'y'), ('B', 'x'), ('B', 'y')]
I need an implementation that responds to requests like "Please change A to B next", for example like this:
>>> generator = DynamicOrderProduct({'var1': 'AB', 'var2': 'xy'})
>>> generator.first()
{'var1': 'A', 'var2': 'x'}
>>> generator.change('var1')
{'var1': 'B', 'var2': 'x'}
>>> generator.change('var2')
{'var1': 'B', 'var2':, 'y'}
>>> generator.change('var2') # here it can't generate a new combination by
# changing var2, so it changes var1 instead
{'var1': 'A', 'var2': 'y'}
>>> generator.change('var2')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
Ideally, the generator would accept a list of variables like this:
generator.change(['var1', 'var2'])
It should then attempt to change the value of var1, and if that isn't possible, change the value of var2 instead, and so on.
How would I go about implementing this? Is there something in the standard lib that can help me?
Alright, I've managed to write an iterator that does what I want. It's the ugliest piece of code I've ever written, but it gets the job done.
I'm still hoping for a better solution though - this implementation keeps a set of all returned combinations, which can grow to use quite a bit of memory.
class DynamicOrderProduct:
"""
Given a dict of {variable: [value1,value2,value3,...]}, allows iterating
over the cartesian product of all variable values.
Each step in the iteration returns a mapping of {variable: value}.
To start the iteration, retrieve the first mapping by calling .first().
To retrieve subsequent mappings, call
.next(order_in_which_to_change_variable_values). This function's
parameter should be a list of variables sorted by which variable's value
should change next. If possible, the first variable in the list will
change value. If not, the 2nd variable in the list will change value
instead, and so on. Raises StopIteration if all combinations are
exhausted.
Example:
possible_values = {'B': [0,1], # B can take the value 0 or the value 1
'L': [1,2,3]}
iterator = DynamicOrderProduct(possible_values)
print(iterator.first())
import random
variables = list(possible_values.keys())
while True:
order = random.sample(variables, len(variables))
print('advancing variables in this order:', order)
try:
print(iterator.next(order))
except StopIteration:
break
You may also pass an incomplete list of variables to the .next function.
If no new combination of the given variables is possible, StopIteration is
raised. For example:
iterator = DynamicOrderProduct({var1: [1],
var2: [1,2]})
iterator.first() # this returns {var1: 1, var2: 1}
iterator.next([var1]) # raises StopIteration
Also, you may pass multiple lists to .next in order to change the value of
multiple variables. StopIteration will be raised only if no variable can
change value.
iterator = DynamicOrderProduct({var1: [1,2],
var2: [1,2]})
iterator.first() # this returns {var1: 1, var2: 1}
iterator.next([var1], [var2]) # returns {var1: 2, var2: 2}
"""
def __init__(self, possible_variable_values):
self.possible_variable_values = {k:tuple(v) for k,v in \
possible_variable_values.items()}
self.variable_order = list(possible_variable_values)
self.exhausted_combinations = set()
def first(self):
self.mapping = {var:vals[0] for var,vals in \
self.possible_variable_values.items()}
t = tuple(self.mapping[var] for var in self.variable_order)
self.exhausted_combinations.add(t)
return self.mapping
def next(self, *orders):
def advance(order, index, maxindex=2147483648):
while True: # loop to reduce recursion
try:
variable = order[index]
except IndexError:
raise StopIteration
value = self.mapping[variable]
valindex = self.possible_variable_values[variable].index(value)
start_index = valindex
while True: # change the value until we find a new combination
valindex += 1
try:
possible_values = self.possible_variable_values
value = possible_values[variable][valindex]
except IndexError:
valindex = 0
value = self.possible_variable_values[variable][0]
self.mapping[variable] = value
# if we've tried all values but none of them
# worked, try to change the next variable's
# value instead
if valindex == start_index:
if index+1 >= maxindex:
raise StopIteration
# instead of recursing, update our own parameters and
# start a new iteration
index += 1
break
t = tuple(self.mapping[var] for var in self.variable_order)
# if this combination isn't new, try
# changing the previous variables' values
if t in self.exhausted_combinations:
if index == 0:
continue
try:
return advance(order, 0, index)
except StopIteration:
continue
return t
total_order = []
fail = True
for order in orders:
# each iteration may also change the previous
# iterations' variables
total_order = order + total_order
try:
t = advance(total_order, 0)
except StopIteration:
fail = True
else:
fail = False
if fail:
raise StopIteration
self.exhausted_combinations.add(t)
return self.mapping
I have a list of dictionaries. Each dictionary has certain boolean flags. So, the list looks like -
listA = [{key1: somevalue1, key2:somevalue2, flag1:True, flag2:False, score:0},
{key1: somevalue3, key2:somevalue4, flag1:False, flag2:True, score:0},
...
{key1: somevalue(N-1), key2:somevalueN, flag1:True, flag2:False, score:0}]
Let's say I have a table, that assigns scores based on the combination of values of the flags. It's like a binary truth table:
flag1 True True False False
flag2 True False True False
score 1 2 3 4
I now want to iterate through the list, and assign these scores to each dictionary in the list, based upon the combination they specify. Is there an elegant way to do it, instead of if else loops? I have a lot of flags, and the combinations would increase with every new flag that's added - result - the code is just ugly.
You can use a dictionary for this:
scores = {(True, True): 1, (True, False): 2,
(False, True): 3, (False, False): 4}
Now you can find the score by simply looking up scores[flag1, flag2].
To do this on the whole list, use
for d in listA:
d["score"] = scores[d["flag1"], d["flag2"]]
Suppose that you have a function f that assigns these scores (it's not obvious how you do it in the above example) given a list of flags, then you can do:
for myDict in myList:
score = f(myDict['flag1], myDict['flag2'])
if you want to generalize this to an arbitrary number of flags:
def score(L):
""" This function takes a list of bools and returns a score.
In this case, the score is simply the number of bools that are True """
return sum(L)
listA = [{key1: somevalue1, key2:somevalue2, flag1:True, flag2:False, score:0},
{key1: somevalue3, key2:somevalue4, flag1:False, flag2:True, score:0},
...
{key1: somevalue(N-1), key2:somevalueN, flag1:True, flag2:False, score:0}]
for d in listA:
print "The score of", d, "is:", \
score([f for f,b in d.iteritems() if type(b) == bool])