I have a function which generates a large amount of output, like such
A: {B:1,C:0,D:3}
B: {A:1,C:0,D:3}
C: {B:1,A:0,D:3}
D: {B:1,C:0,A:3}
min = 0, x = A, y = C, new = AC
AC: {B:1,D:3}
B: {AC:1,D:3}
D: {B:1,AC:0}
min = 0, x = B, y = AC, new = ACB
Essentially, Im using a function (for arguments sake we'll call it 'fun1') which generates the type of output like shown above.
Im looking at doing something like data1 = fun1(input), and then using this variable as input to another function, along with some other input too.
So how do I utilize this information? I'm used to dealing with lists, dictionaries and what not, as output from a function. Im trying to access the information so that I can find out certain things about the relationship of a certain letter to others. Also it the amount of output above is just 2 lists of letters, but thats totally arbitrary.
Help please :)
Its not clear to me why you have a function that prints out tons of data as opposed to returning it as a useable python object. If you have control of this function (its yours and you wrote it), then it should be doing something like this (keep in mind that this is regardless of efficiency or whatever. Just trying to make it simple for you)...
def fun1():
allresults = []
# do you loop and generate objects like
results = {
"A": {"B":1,"C":0,"D":3},
"B": {"A":1,"C":0,"D":3},
"C": {"B":1,"A":0,"D":3},
"D": {"B":1,"C":0,"A":3},
"min": 0,
"x": "A",
"y": "C",
"new": "AC"
}
# and add them to your list
allresults.append(results)
return allresults
Then when you ran your function, you would have a return value:
data = fun1()
If you do not have control over the source of this function (its part of some other strangely written library), then the only clean way would be to run it in another process and read the stdout out. Then parse that into something useable. Otherwise you are talking about redirecting the stdout pipe temporarily while running this function, but I am not even gunna go there.
Update
In your comments you said that this is part of some other library. Your best bet is to make changes to this code and get it to properly return its data so that its reusable. Your biggest issue here is that what is being printed isnt even in a common format. At the very least it could have dumped out JSON or something like that to be parsed by another process.
Related
First I tried directly storing values from a list having the name 'data' in an array variable 'c' using loop but 'none' got printed
for i in data:
print(i['name'])
c=i['name']
Here print(i['name']) perfectly worked and output appeared
This is the working ouput
Then I printed c in order to print the values generated using loop. The ouput came as none.
print(c)
Then I tried another way by storing the values and making the array iterable at the same time using for loop. An error occurred which I was unable to resolve.
for i in data:
b[c]=i['name']
c=c+1
The error apeared is as follow-
I have tried two ways, if there is any other way please help me out as I am new to python.
It looks like the variable 'data' is a dictionary.
If you want to add each name from that dictionary to a list:
# create a new list variable
names = []
for i in data:
name = i['name']
print(name)
# add the name to the list
names.append(name)
# output the new list
print(names)
Assuming your data object here is a list like [{"name": "Mr. Green", ...}, {"name": "Mr. Blue", ...}].
If your goal is to end up with c == ["Mr. Green", "Mr. Blue"], then you're looking for something like:
c = []
for i in data:
c.append(i['name'])
print(c)
or you can accomplish tasks like these using list comprehensions like:
c = [i['name'] for i in data]
print(c)
The first code example you posted is iterating through the items in data and reassigning the value of c to each item's name key - not adding them to a list("array"). Without knowing more about the code you ran to produce the screenshot and/or the contents of data, it's hard to say why you're seeing print(c) produce None. I'd guess the last item in data is something like {"name": None, ...} which if it's coming from JSON is possible if the value is null. Small note: I'd generally use .get("name") here instead so that your program doesn't blow up if an item is missing a "name" key entirely.
For your second code example, the error is different but I think falls along a similar logical fallacy which is that lists in python function differently from primitives(things like numbers and strings). For the interpreter to know that b or c are supposed to be lists("arrays"), they need to be instantiated differently and they have their own set of syntax/methods for mutation. For example, like arrays in other languages, lists are indexed by position so doing b[c] = <something> will only work if c is an integer. So something similar to your second example that would also produce a list of names like my above would be:
b = [None] * len(data)
c = 0
for i in data:
b[c]=i['name']
c=c+1
Note that if you only initialize b = [], you get an IndexError: list assignment index out of range on the initial assignment of b[0] = "some name" because the list is of size 0.
Add
b = []
above your first line of code. As the error is saying that you have not (and correctly so) defined the list to append.
I personally would use list comprehension here
b = [obj['name'] for obj in data]
where obj is i as you have defined it.
I've followed a tutorial to write a Flask REST API and have a special request about a Python code.
The offered code is following:
# data list is where my objects are stored
def put_one(name):
list_by_id = [list for list in data_list if list['name'] == name]
list_by_id[0]['name'] = [new_name]
print({'list_by_id' : list_by_id[0]})
It works, which is nice, and even though I understand what line 2 is doing, I would like to rewrite it in a way that it's clear how the function iterates over the different lists. I already have an approach but it returns Key Error: 0
def put(name):
list_by_id = []
list = []
for list in data_list:
if(list['name'] == name):
list_by_id = list
list_by_id[0]['name'] = request.json['name']
return jsonify({'list_by_id' : list_by_id[0]})
My goal with this is also to be able to put other elements, that don't necessarily have the type 'name'. If I get to rewrite the function in an other way I'll be more likely to adapt it to my needs.
I've looked for tools to convert one way of coding into the other and answers in forums before coming here and couldn't find it.
It may not be beatiful code, but it gets the job done:
def put(value):
for i in range(len(data_list)):
key_list = list(data_list[i].keys())
if data_list[i][key_list[0]] == value:
print(f"old value: {key_list[0], data_list[i][key_list[0]]}")
data_list[i][key_list[0]] = request.json[test_key]
print(f"new value: {key_list[0], data_list[i][key_list[0]]}")
break
Now it doesn't matter what the key value is, with this iteration the method will only change the value when it finds in the data_list. Before the code breaked at every iteration cause the keys were different and they played a role.
I created multiply arrays and want to append something to them, but the user should choose which array he want append it to.
So to clarify what I mean: (The code down under is wrong, but I do not know how I could write it.)
x = []
y = []
def test(pName):
%s.append(1) %pName
test(y)
Edit:
#Jim Fasarakis-Hilliard
I am trying to program in PyGame.
Therefor I have to initalise all the images I want to use.
To not expand it, I wanted to create a function where you can easily append to any array you want to, so I do not have to create a new function every time I want to initalise new pictures.
My code looks like this atm.:
def loadImages(self,pName,pAnz,pScaleX,pScaleY):
for i in range(0,pAnz):
tux = pygame.transform.scale(pygame.image.load('./images/%s.png'),(pScaleX,pScaleY) % pName)
self.%s.append(tux) %pName
length_array = len(self.%s) %pName
return length_array
You could use globals, pass a string of the variable name to the function:
def test(pName):
globals()[pName].append(1)
test('y')
this, of course, relies on the name existing in the global scope.
You could put the array's in a dictionary. Assuming that there is a fixed number of arrays, the code would look something like this:
arrays = {}
arrays['x'] = []
arrays['y'] = []
def test(pName):
arrays[pName].append(1)
test('y')
You will want to check the user input, as a pName which is not a key in the dictionary will throw a key exception. If you want the arrays to be dynamic, you could do something like this:
arrays={}
def test(pName):
if pName not in arrays.keys():
arrays[pName]=[]
arrays[pName].append(1)
test('y')
If all you want is to be able to save your objects into different "namespaces", you can use dictionaries:
lists = {
"x": [],
"y": []
}
def test(pName):
lists[pName].append(1)
test("y")
Cleaner and easier to understand than using globals or similars IMHO.
So I made this method to set parameters from a text file:
def set_params(self, params, previous_response=None):
if len(params) > 0:
param_value_list = params.split('&')
self.params = {
param_value.split()[0]: json.loads(previous_response.decode())[param_value.split()[1]] if
param_value.split()[0] == 'o' and previous_response else param_value.split()[1]
for param_value in param_value_list
}
When i call this method for example like this:
apiRequest.set_params("lim 5 & status active")
//now self.params={"lim" : 5, "status" : "active"}
it works well. Now I want to be able to add the same parameter multiple times, and when that happens, set the param like a list:
apiRequest.set_params("lim 5 & status active & status = other")
//I want this: self.params={"lim" : 5, "status" : ["active", "other"]}
How can I modify this method beautifully? All I can think of is kinda ugly... I am new with python
Just write it as simple and straightforward as you can. That is usually the best approach. In my code, below, I made one change to your requirements: all values are a list, some may have just one element in the list.
In this method I apply the following choices and techniques:
decode and parse the previous response only once, not every time it is referenced
start with an empty dictionary
split each string only once: this is faster because it avoids redundant operations and memory allocations, and (even more importantly) it is easier to read because the code is not repetitive
adjust the value according to the special-case
use setdefault() to obtain the current list of values, if present, or set a new empty list object if it is not present
append the new value to the list of values
def set_params(self, params, previous_response=None):
if len(params) <= 0:
return
previous_data = json.loads(previous_response.decode())
self.params = {}
for param_value in params.split('&'):
key, value = param_value.split()
if key == 'o' and previous_response:
value = previous_data[value]
values = self.params.setdefault(key, [])
values.append(value)
# end set_params()
Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are, by
definition, not smart enough to debug it.
— Brian W. Kernighan and P. J. Plauger in The Elements of Programming Style.
Reference: http://quotes.cat-v.org/programming/
I'm making a very simple graphical program and am quite new.
nums = ["second", "third", "fourth"]
for colours in range(3):
numString = nums[colours]
inputWindow.getMouse()
colour1 = inputBox.getText()
inputBox.setText("")
instruction.setText("Please enter the {0} colour: ".format(numString))
Where I put 'colour1', I want it to cycle through colour1, colour2, colour3 and colour4 on each iteration (without using a long if statement). Dictionary cannot be used for this particular program.
At the end, the function returns all of these colours inputted from the user. I tried using a list but realised you can't use them for variable names.
Thanks for help.
Edit: Seeing as there's a lot of confusion (which I'm sorry for), I'll try and explain better:
My code up there is kind of strange and comes from nowhere. I'll simplify it:
def getInputs():
for colours in range(3):
colour1 = userInput()
return colour1, colour2, colour3, colour4
This is basically the gist. I wanna know if there's a way to cycle through the different variables where 'colour1 = userinput()' is (without using dictionary).
Editing to reflect the new information. The principal thing to keep in mind here is that you can use sequence types (list, dict, etc.) to collect your results.
def get_inputs():
# a list to collect the inputs
rval = []
for colours in range(4):
# range(4) will walk through [0,1,2,3]
# this will add to the end of the list
rval.append(userInput())
# after the for loop ran four times, there will be four items in the list
return rval
In case you really want to want return a tuple, the last line can be return tuple(rval)