This may be a very simple question, but how can I use a string for the name of a class/object declaration? I'm working with PySide, and I have code that will make a text input for every entry in an array.
i=0
d = {}
for name in mtlName:
i = i+1
curOldLabel = d["self.oldLabel" + str(i)]
So now I have to just decalre QtGui.QLineEdit() as what curOldLabel equals (self.oldLabel1 = QtGui.QLineEdit(), self.oldLabel2 = QtGui.QLineEdit(), etc). How do I tell it not to overwrite curOldLabel, but instead use the string as the name for this object?
Your best bet is to use another dictionary to store those objects. It's safe, it's easy to use and it has fast lookup. You don't want to be creating normal variables with dynamic names in most scenarios.
Related
I'm looking for a shorter but still clean and flexible way to write what I have below.
Variable to work with (length varying)
drpfile_exportname = '1911_CocaCola_XMasNow_TVC30sec_03_Roughcut_Tv10_PV01_Ov01_200319_prev_for_approval_H264'
Long way of doing it but clean
# Split string by "_"
drpfile_exportname_list = drpfile_exportname.split("_")
# Set variables
ul_date = drpfile_exportname_list[0]
up_client = drpfile_exportname_list[1]
up_cprojname = drpfile_exportname_list[2]
# Join variables to create desired name
upload_projname = "_".join((ul_date, up_client, up_cprojname))
Alternative oneliner not so flexible as no variables are assigned and in my opinion not a beautiful way to solve it
upload_projname = ("_".join(drpfile_exportname.split('_')[0:3]))
Thought something like this would work but always had problems with it
ul_date, up_client, up_cprojname = drpfile_exportname.split('_', 2)
Print:
print("\nProject name: {}".format(upload_projname))
Result that should be stored in a variable:
Project name: 1911_CocaCola_XMasNow
You can slice the result of split.
ul_date, up_client, up_cprojname = drpfile_exportname.split('_')[:3]
Or you can assign a dummy variable to the part you want to ignore
ul_date, up_client, up_cprojname, *_ = drpfile_exportname.split('_')
I have a list of file names, A1 & A2.
The load method creates a temporary list of the data held on the csv file.
Is it possible to create an instance of a class based off of the string (file name) passed?
patients_list = ["A1", "A2"]
def load_patient(patients_list):
patient_data = []
for i in range(len(patients_list)):
with open(patients_list[i]+".csv", "rt") as patient_file:
patient_file_reader = csv.reader(patient_file, delimiter=',')
for row in patient_file_reader:
patient_data.append(row)
patients_list[i] = patientClass(patient_data) #can the string value be converted to an obj?
My goal is to have two objects named A1 and A2 (each containing the csv data).
Is this possible? I have searched the internet for a solution but have come up short.
Yes it is possible by some hacks like adding entries into globals(), and no you do not want that.
The fact is that you could not even propose a possible syntax, because nothing is easy on that way. The common and robust way to name dynamic objects is to use a dictionary:
patient_obj = {}
...
for i in range(...):
...
patient_obj[patient_list[i]] = patientClass(patient_data)
This question already has answers here:
How do I create variable variables?
(17 answers)
Closed 5 years ago.
I have a list of commands that I want to iterate over so I've put those commands into a list. However, I want to also use that list as strings to name some files. How do I convert variable names to strings?
itemIDScore = """SELECT * from anytime;"""
queryList = [itemIDScore, accountScore, itemWithIssue, itemsPerService]
for x in queryList:
fileName = x+".txt"
cur.execute(x) #This should execute the SQL command
print fileName #This should return "itemIDScore.txt"
I want fileName to be "itemIDScore.txt" but itemIDScore in queryList is a SQL query that I'll use elsewhere. I need to name files after the name of the query.
Thanks!
I don't think you may get name of the variable as string from the variable object. But instead, you may create the list of string of your variables as:
queryList = ['itemIDScore', 'accountScore', 'itemWithIssue', 'itemsPerService']
Then you may access the value of variable from the variable name string using the globals() function as:
for x in queryList:
fileName = "{}.txt".format(x)
data = globals()[x]
cur.execute(data)
As the globals() document say:
Return a dictionary representing the current global symbol table. This is always the dictionary of the current module (inside a function or method, this is the module where it is defined, not the module from which it is called).
As far as I know, there is no easy way to do that, but you could simply use a dict with what currently are variable names as keys, e.g.:
queries = {
'itemIDScore': 'sql 1',
'accountScore': 'sql 2',
...
}
for x in queries:
fileName = x + ".txt"
cur.execute(queries[x])
print fileName
This would also preserve your desired semantics without making the code less readable.
I think you would have an easier time storing the names explicitly, then evaluating them to get their values. For example, consider something like:
itemIDScore = "some-long-query-here"
# etc.
queryDict = dict( (name,eval(name)) for name in ['itemIDScore', 'accountScore', 'itemWithIssue', 'itemsPerService'] )
for k in queryDict:
fileName = k+".txt"
cur.execute(queryDict[k])
You can use the in-built str() function.
for x in queryList:
fileName = str(x) + ".txt"
cur.execute(x)
I'm creating this type of object:
class start_url_mod ():
link = ""
id = 0
data = ""
I'm creating a list of this object and I want to know if there is some way in order to delete one of then if I find same link attribute.
I know the function set() for the deleting of duplicates in a "sample" list, but there is something very fast and computational acceptable?
Use a dict key-ed on the attribute. You can preserve order with collections.OrderedDict:
from collections import OrderedDict
# Keep the last copy with a given link
kept_last = OrderedDict((x.link, x) for x in nonuniquelist).values()
# Keep the first copy with a given link (still preserving input order)
kept_first = list(reversed(OrderedDict((x.link, x) for x in reversed(nonuniquelist)).viewvalues()))
If order is not important, plain dict via dict comprehensions is significantly faster in Python 2.7 (because OrderedDict is implemented in Python, not C, and because dict comprehensions are optimized more than constructor calls; in Python 3.5 it's implemented in C):
# Keep the last copy with a given link but order not preserved in result
kept_last = {x.link: x for x in nonuniquelist}.values()
# Keep the first copy with a given link but order not preserved in result
kept_first = {x.link: x for x in reversed(nonuniquelist)}.values()
You can use a dictionary with the attribute that you're interested in being the key ...
Very beginner question but it is driving me mad. sample1, sample2 etc. are Pygame.mixer.sound objects.
sample_list = []
sample_list.append(sample1)
sample_list.append(sample2)
sample_list.append(sample3)
Is fine, but I want to do that using a for style loop, e.g.
for j in range(1, 3, 1):
sample_list.append(sample + j)
But that is trying to add a number to a sound object so isn't right. I can add the equivalent string by;
for j in range(1, 3, 1):
sample_list.append("sample" + str(j))
But that doesn't refer to the objects I want, just adds those strings.
I've tried must permutations of syntax I can think of but it is still alluding me!
Thanks.
Don't store the objects in variables in the first place; store them directly into a list, and then you will be able to index them by integer.
If the integer identifiers are sparse, use a dict indexed by integer.
I would recommend storing these in a dict to begin with. It is almost the same effect for you to reference by a name, but without the explicit object symbol for each:
samples = {
"sample1": Sample(),
"sample2": Sample()
}
samples['sample3'] = Sample()
This is the preferred approach when you have a dynamic number of objects you are creating and want to be able to grab them by a name later. You can store 100's of these in your dict without cluttering up your namespace.
And later if you are trying to apply this to your loop, you can reference the string names:
for i in xrange(1,4):
sample_list.append(samples["sample" + str(i)])
As a side note another way to get attributes by name when they live on some object is to use getattr. Assume you have this:
class Sampler(object):
pass
sampler = Sampler()
sampler.sample1 = Sample()
sampler.sample2 = Sample()
sampler.sample3 = Sample()
You can then reference by name via: getattr(sampler, "sample1")
Note: As mentioned in comments by #Marcin, if you don't care about having a string identifier to be able to look up your items, and they are just purely sequential by number, you can use this same approach but with a list. It depends on your needs.
It is possible you might want to end up doing something like:
samples = {
"bang1": Sample(),
"bang2": Sample(),
"bang3": Sample(),
"shot1": Sample(),
"shot2": Sample(),
...
}
... Which would then allow you to look up sequential subsets of those sounds.
You can dynamically load variables from the locals() mapping:
for j in range(1, 4):
sample_list.append(locals()["sample" + str(j)])
Generally, you want to avoid such tricks; find other ways to store your sample variables, in a mapping or a list for example.
Looks like the wrong approach, but nevertheless.
sample_list = [eval('sample' + str(i)) for i in range(1, 4)]