Python - Append to an array whose name is given by a string - python

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.

Related

Iterate over Python list with clear code - rewriting functions

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.

Python: calling strings from a list to feed into a function

I'm struggling with how to correctly feed a list of strings one-by-one into a pre-defined function. The list looks like this:
riclist = ["XAU=", "XAG=", "XPT=", "XPD="]
And the function looks like this (note that ek.get_timeseries is a pre-defined function from the Eikon library, but this problem could be generalized to any similar one):
def get_variable(input):
chosenric = riclist[ ##each item one-by-one## ]
var = ek.get_timeseries(rics=chosenric,
start_date=2018-01-01,
fields="CLOSE")
return(var)
And the end result I'm after is a DataFrame with the time-series for all n variables in riclist.
How about:
for item in riclist:
var = ek.get_timeseries(rics=chosenric,
start_date=2018-01-01,
fields="CLOSE")
....do the rest here for each item
I may be missing something in the question, but if the question is:
How to run a function on a list of arguments then
there are a few simple ways:
results = [get_variable(input) for input in riclist]
results = map(get_variable, riclist)
Not sure if I completely understand your question, but are you looking for a for loop?
for ric in riclist:
var = ek.get_timeseries(rics=ric,
start_date=2018-01-01,
fields="CLOSE")
then, if you want to return one at a time, you could use a generator
yield var
Returns a dict-like {chosenric : timeseries}
def get_variable(riclist):
return {chosenric : ek.get_timeseries(rics=chosenric, start_date=2018-01-01, fields="CLOSE") for chosenric in riclist}
It is probably better to ask these kind of questions on the Thomson Reuters Developer Portal, because you are asking something (licensed) product specific, which is not useful for the StackOverflow community.
That being said, the get_timeseries function can be fed a list of instruments directly. It always returns a pandas dataframe. So you probably want to do this:
df = ek.get_timeseries(riclist, fields="CLOSE", start_date='2018-01-01')
If you really need it to be part of a function, you could do this:
def get_variable():
var = ek.get_timeseries(rics=riclist,
start_date="2018-01-01",
fields="CLOSE")
return(var)
Please check out the documentation
**Disclaimer: I am currently employed by Thomson Reuters

Concise way to convert multiple Date Time to seconds?

I am looking for a way to write the code below in a more concise manner. I thought about trying df[timemonths] = pd.to_timedelta(df[timemonths])...
but it did not work (arg must be a string, timedelta, list, tuple, 1-d array, or Series).
Appreciate any help. Thanks
timemonths = ['TimeFromPriorRTtoSRS', 'TimetoAcuteG3','TimetoLateG3',
'TimeSRStoLastFUDeath','TimeDiagnosistoLastFUDeath',
'TimetoRecurrence']
monthsec = 2.628e6 # to convert to months
df.TimetoLocalRecurrence = pd.to_timedelta(df.TimetoLocalRecurrence).dt.total_seconds()/monthsec
df.TimeFromPriorRTtoSRS = pd.to_timedelta(df.TimeFromPriorRTtoSRS).dt.total_seconds()/monthsec
df.TimetoAcuteG3 = pd.to_timedelta(df.TimetoAcuteG3).dt.total_seconds()/monthsec
df.TimetoLateG3 = pd.to_timedelta(df.TimetoLateG3).dt.total_seconds()/monthsec
df.TimeSRStoLastFUDeath = pd.to_timedelta(df.TimeSRStoLastFUDeath).dt.total_seconds()/monthsec
df.TimeDiagnosistoLastFUDeath = pd.to_timedelta(df.TimeDiagnosistoLastFUDeath).dt.total_seconds()/monthsec
df.TimetoRecurrence = pd.to_timedelta(df.TimetoRecurrence).dt.total_seconds()/monthsec
You could write your operation as a lambda function and then apply it to the relevant columns:
timemonths = ['TimeFromPriorRTtoSRS', 'TimetoAcuteG3','TimetoLateG3',
'TimeSRStoLastFUDeath','TimeDiagnosistoLastFUDeath',
'TimetoRecurrence']
monthsec = 2.628e6
convert_to_months = lambda x: pd.to_timedelta(x).dt.total_seconds()/monthsec
df[timemonths] = df[timemonths].apply(convert_to_months)
Granted I am kind of guessing here since you haven't provided any example data to work with.
Iterate over vars() of df
Disclaimer: this solution will most likely only work if the df class doesn't have any other variables.
The way this works is by simply moving the repetitive code after the = to a function.
def convert(times):
monthsec = 2.628e6
return {
key: pd.to_timedelta(value).dt.total_seconds()/monthsec
for key, value in times.items()
}
Now we have to apply this function to each variable.
The problem here is that it can be tedious to apply it to each variable individually, so we could use your list timemonths to apply it based on the keys, however, this requires us to create an array of keys manually like so:
timemonths = ['TimeFromPriorRTtoSRS', 'TimetoAcuteG3','TimetoLateG3', 'TimeSRStoLastFUDeath','TimeDiagnosistoLastFUDeath', 'TimetoRecurrence']
And this can be annoying, especially if you add more, or take away some because you have to keep updating this array.
So instead, let's dynamically iterate over every variable in df
for key, value in convert(vars(df)).items():
setattr(df, key, value)
Full Code:
def convert(times):
monthsec = 2.628e6
return {
key: pd.to_timedelta(value).dt.total_seconds()/monthsec
for key, value in times.items()
}
for key, value in convert(vars(df)).items():
setattr(df, key, value)
Sidenote
The reason I am using setattr is because when examining your code, I came to the conclusion that df was most likely a class instance, and as such, properties (by this I mean variables like self.variable = ...) of a class instance must by modified via setattr and not df['variable'] = ....

How to assign a function to a String and use some of the string as parameter for the function

I'm having some trouble figuring out something.
Let's say that I have a list of strings (a csv,txt,or something like that) that looks something like this:
1)Set Car color = red
2)Set Radio-Volume = 50%
3)Car AC temp = 20°C
And I want each of those lines to execute some functions that I have created. Let's say that I have created some functions that use the values from the string above.
Ex:
def set_color(colorvalue):
car_color= colorvalue
print("The car has been set to: ",colorvalue)
def radio_vol(vol):
#do something here
def set_car_ac_to(deg):
#do something else here
etc,you get the idea.
What is the best approach, so that when parsed, the csv,txt file containing the lines of text, to call their specific function with the given parameter.
How can I assign a function to a string and use it's specific param.
Thank you
Use a dict:
actions = {"Set Car color": set_color,
"Set Radio-Volume": radio_vol, ...}
command = "Set Car color"
argument = "red"
actions[command](argument)

How to add Objects to Class with a loop in Python?

I have a class which looks like this.
class CharInStageList(object):
def __init__(self, charid, charname) :
self.charid = charid
self.charname = charname
into this class I would like to add lists that I have.
I know how to do it the normal way
charOne = CharInStageList(1,'Tim')
charTwo = CharInStageList(2,'Struppi')
that's not a problem what I actually want to do is to add them by using a loop.
I get my data in this form
((1,'Tim'),(4,'Struppi'))
or
((1,'Tim'),(4,'Struppi'),(5,'Nami'),(6,'Luffy'))
the amount of characters I have in the scene is always different.
what I imagined would be a loop like this
charlist = ((1,'Tim'),(4,'Struppi'))
for char in charlist
objname = CharInStageList(char[0],char[1])
something like this
I want the objname to change by itself for every object I add to the class.
How can I get this effect?
I can only use python 2.6.6 for this since it's the maya 2013 python
Edit:
Thx #silas-ray #chepner #theodox I looked into Dicts a bit more and that's pretty much what I need
I use a modified version of #chepner method on it.
object_dict = dict( (y, CharInStageList(x,y)) for x,y in data )
Works like a charm
My testcode looks like this
import maya.cmds as cmds
dicttest = {}
def getdata ():
global dicttest
data = ((1,'Tim'),(4,'Struppi'),(5,'Nami'),(6,'Luffy'))
dicttest = dict( (y,(x,y)) for x,y in data )
getdata()
def printtest() :
for char in dicttest:
print dicttest[char]
printtest()
dicttest.clear()
I would have liked to comment in your answers with code examples but I can't get that to work there.
Objects are not added to a class. Instead, you can create a list of objects which are all instances of the same class, using a list comprehension and taking advantage of the *args syntax:
data = ((1,'Tim'),(4,'Struppi'),(5,'Nami'),(6,'Luffy'))
object_list = [ CharInStageList(*x) for x in data ]
Perhaps you want a dictionary instead:
object_dict = dict( (y, CharInStageList(x,y)) for x,y in data )
(Note that CharInStageList is a poor name for the class, because it's not a list; it encapsulates a single character.)
If you really want CharInStateList to be a collection of characters, try something like this, which is just a thin wrapper around a dictionary:
# Your former CharInStageList
class Character(object):
def __init__(self, charid, charname) :
self.charid = charid
self.charname = char name
class OnStageCharacters(object):
def __init__(self):
self.characters = dict()
# Index on-stage characters using their charid
def add(self, character):
self.characters[character.charid] = character
on_stage = OnStageCharacters()
for id, name in data:
on_stage.add( Character(id, name) )
You can't (at least not without hacking at locals/globals, which is generally not a good idea) change the name you are assigning to dynamically like that. You can, however, insert them in to a dictionary where the keys are your dynamically generated names.
characters = {}
for char_data in char_list:
characters[char_data[1]] = CharInStageList(*char_data)
Though if all your character objects are storing is name and id, it might make more sense to simplify the whole thing and just create mapping dictionaries rather than objects.
character_names_by_id = dict(char_data)
character_ids_by_name = dict((name, id) for id, name in char_data)
#chepner's answer is a great one if you can use the *args form to fill out your class instances.
If you're just asking the most efficient way to do this from a loop, remember you can have iterate over the parts of a tuple together:
data = ((1,'Tim'),(4,'Struppi'),(5,'Nami'),(6,'Luffy'))
class_data = (CharInStageList(id, name) for id, name in data) # "for id, name" will yield two vals
You can also use map, which is very common for doing bulk data translations. A common way to do it is with a lambda so you can write it clearly:
to_char = lambda k: CharInStageList(k[0], k[1])
class_data = map(to_char, data)
If you're doing something as simple as your example, you might not want to bother with your own class. the namedtuple is a great data structure for creating tuples that are easy to work with. It also means you can use positional or named args interchangeably, just as in #chepner's *args version:
StageListChar = namedtuple('CharInStageList', ['id', 'name'])
class_data = map(StageListChar , data)

Categories

Resources