(CHECK UPDATE BELOW)
I'm having trouble with importing a list from another file.
I'm still learning how to call/pass variables in functions.
I have something very similar to this example,
#file1
list_one = [] #global
list_two = [] #global
def function_list_one():
# code
return list_one
def function_list_two(list_one, list_two):
# code
return list_two
def both_lists(list_one, list_two):
# code
return new_list
# return new_list outputs a JSON list
both_lists(list_one, list_two) # this is used to call it from main
So far, if I print this new list it works from within this file. It prints what I want. However, if I try to do the next few things then it just prints an empty list. The last time from file1 is for the main file where I call that function using those parameters.
#file2
from file1 import both_lists, list_one, list_two
new_list = both_lists(list_one, list_two)
new_list2 = list_two
print(new_list)
# outputs = []
prin(new_list2)
#outputs = []
# Expected output should be the results from new_list from file1, which
# would be a JSON type list.
This is where nothing happens. If I try both methods, they return an empty list. I understand I have a global variable for both list_one and list_two. What I don't understand is why it returns an empty list when I have used this same method in another program I made. Basically, I want to use the "return new_list" in fil2 in order to proceed with the rest of the program.
Update:
I found the solution. Somehow file2 when I import the new_lists it didn't like it. So, instead I just import both_lists(function_list_one(), function_list_two())
Thank you all for your time!
It looks as though you're importing the lists as defined, not as they are built by your function_list_* functions.
When you import list_one and list_two, you are importing them as empty lists, as file 1 has them:
list_one = [] #global
list_two = [] #global
If both_lists() is just appending them, then what you're getting for new_list in file 2 is just both of those empty lists appended together, or just another empty list.
I think what you're after is the result of appending function_list_one(list_one) and function_list_two(list_two). There's a number of ways you could accomplish that, but perhaps the simplest is to redefine both_lists() to do something like this:
def both_lists(list_one, list_two):
# Code
return function_list_one(list_one) + function_list_two(list_two)
Then, when you import both_lists, you also import the functionality defined for your list-building functions.
To sum up:
As written, your imports are importing these items:
list_one = []
list_two = []
both_lists, which I'm assuming just appends list_one and list_two
The code in function_list_one() and function_list_two() won't execute unless you import and call those functions or include their functionality in something that you do import - and then call that.
My suggestion above is just one way around this, and that's assuming I read your code correctly! Hope this helps, though. :^)
Related
I want to share lists between different functions like:
def function1():
testlist = ['1','2','3']
testlist.append = ('4')
print(testlist)
return testlist
def function2():
testlist = function1()
print(testlist)
testlist.append('6')
The Problem is, that as soon as I want to edit the list with for example list.append, the Error-Message 'tuple' object has no attribute 'append'. Even though testlist has still the correct input in function2. Thats why I don't know why the list is correctly passed between the two functions but as a tuple and not a list. Is there a way to change the variable back to a list or to pass it as a list?
I already know that I could pass lists easier in classes. But the class would be to big for the application I want to program. I already saw this Question, where the problem is discussed similar. But with these solutions I still can't edit the list in the other function.
Thanks for your help.
To clarify the problem: The code is:
The code is:
`
def function1():
cfg = yaml.load(yamlfile)
testlist = []
list2 = []
for x in cfg['y']
list2.append([x, str(cfg['y'][x]['z']), cfg['g']['d'] + '\\'])
for c in cfg['y'][x]['z']:
if cfg['x'][y]['z'][c]['abc']:
list2.append([str(cfg['y'][x]['z'][c]['abs'])])
return testlist, list2
def function2():
testlist = function1()
list2 = function1()
for i in range(len(list2)):
testlist.append(list2[i][0])`
I hope know its a bit more clear what I want to do. Btw I just used random names in the config file.
You have a semantic error:
testlist.append = (['4'])
Is not correct:
If you want to append only '4' you should use:
testlist.append('4')
Gabriel is right.
Be careful in your second function too.
I think you want to append '6' and not ['6'].
testlist.append('6')
I have a list with files (the path to them).
I wrote a function like this to remove certain files matching a pattern but it just removes 2 files at most and I don't understand why.
remove_list = ('*.txt',) # Example for removing all .txt files in the list
def removal(list):
for f in list:
if any(fnmatch(basename(f.lower()), pattern) for pattern in remove_list:
list.remove(f)
return list
//Edit; Ok naming my list "list" in the code was a bad idea. in my code here its called differently. Just wanted to give an abstract idea what I'm dealing with. Should have mentioned that
Modifying a list while you're iterating over it is a bad idea, as you can very easily get in edge cases when behaviour is not determined.
The best way to do what you want is to build a new list without the items you don't want:
remove_list = (r'*.txt',) # Example for removing all .txt files in the list
def removal(l, rm_list):
for f in l:
for pattern in rm_list:
if not fnmatch(basename(f.lower()), pattern):
yield f
print(list(removal(list_with_files, remove_list))
Here, I'm unrolling your any one-liner that might make your code look smart, but is hard to read, and might give you headaches in six months. It's better (because more readable) to do a simple for and an if instead!
The yield keyword will make the function return what's called a generator in python, so that when you're iterating over the result of the function, it will return the value, to make it available to the calling context, and then get back to the function to return the next item.
This is why in the print statement, I use list() around the function call, whereas if you iterate over it, you don't need to put it in a list:
for elt in removal(list_with_files, remove_list):
print(elt)
If you don't like using a generator (and the yield statement), then you have to build the list manually, before returning it:
remove_list = (r'*.txt',) # Example for removing all .txt files in the list
def removal(l, rm_list):
ret_list = []
for f in l:
for pattern in rm_list:
if not fnmatch(basename(f.lower()), pattern):
ret_list.append(f)
return ret_list
HTH
You can use str.endswith if you are removing based on extension, you just need to pass a tuple of extensions:
remove_tup = (".txt",".py") # Example for removing all .txt files in the list
def removal(lst):
return [f for f in lst if not f.endswith(remove_tup)]
The code you provided is vague.
1.don't use list it is shadow the build-in list
2.don't modify the list when you iterate it, you can make a copy of it
My suggestion is:
You can iterate your original list and the remove_list as below:
test.py
list1=["file1.txt", "file2.txt", "other.csv"]
list2=["file1.txt", "file2.txt"] # simulates your remove_list
listX = [x for x in list1 if x not in list2] # creates a new list
print listX
$python test.py
['other.csv']
As was said in the comments, don't modify a list as you iterate over it. Can also use a list comprehension like so:
patterns = ('*.txt', '*.csv')
good = [f for f in all_files if not any(fnmatch(basename(f.lower()), pattern) for pattern in patterns)]
I have the following code:
import maya.cmds as cmds
list = cmds.ls(sl=True)
my_list = [object.upper() for object in list]
print(my_list)
However, it doesn't change the name of the objects even though it prints out upper case names in the print statement at the end.
What you want is
import maya.cmds as cmds
list = cmds.ls(sl=True)
for n in list:
cmds.rename(n, n.upper())
new_list = cmds.ls(sl=True)
print(new_list)
This is documented here with an example.
This code will rename all objects in list you can also work with whichever you have selected with cmds.select() if you want to.
The proper way to “mutate” a string is to use slicing and concatenation
to build a new string by copying from parts of the old string.
It's quite hackish, and I honestly wouldn't recommend it, but if you REALLY want to do that, you could do:
def global_var_to_upper(var):
for _ in globals():
if var is globals()[_]:
globals()[str(_).upper()] = globals()[_]
del globals()[_]
break
abc = 123
global_var_to_upper(abc)
print(ABC) # prints 123
In web2py I have been trying to break down this list comprehension so I can do what I like with the categories it creates. Any ideas as to what this breaks down to?
def menu_rec(items):
return [(x.title,None,URL('shop', 'category',args=pretty_url(x.id, x.slug)),menu_rec(x.children)) for x in items or []]
In addition the following is what uses it:
response.menu = [(SPAN('Catalog', _class='highlighted'), False, '',
menu_rec(db(db.category).select().as_trees()) )]
So far I've come up with:
def menu_rec(items):
for x in items:
return x.title,None,URL('shop', 'category',args=pretty_url(x.id, x.slug)),menu_rec(x.children))
I've got other variations of this but, every variation only gives me back 1(one) category, when compared to the original that gives me all the categories.
Can anyone see where I'm messing this up at? Any and all help is appreciated, thank you.
A list comprehension builds a list by appending:
def menu_rec(items):
result = []
for x in items or []:
url = URL('shop', 'category', args=pretty_url(x.id, x.slug))
menu = menu_rec(x.children) # recursive call
result.append((x.title, None, url, menu))
return result
I've added two local variables to break up the long line somewhat, and to show how it recursively calls itself.
Your version returned directly out of the for loop, during the first iteration, and never built up a list.
You don't want to do return. Instead append to a list and then return the list:
def menu_rec(items):
result = []
for x in items:
result.append(x.title,None,URL('shop', 'category',args=pretty_url(x.id, x.slug)),menu_rec(x.children)))
return result
If you do return, it will return the value after only the first iteration. Instead, keep adding it to a list and then return that list at the end. This will ensure that your result list only gets returned when all the values have been added instead of just return one value.
Here's an example of the code im trying to implement:
def notes():
print "\nPlease enter any notes:"
global texts
texts = []
if not texts:
print "no notes exist."
write_note()
else:
print "this note already exists"
def write_note():
while True:
global txt
txt = raw_input(">>> ")
if not txt:
break
else:
texts.append(txt)
print "\nNote(s) added to report."
notes_menu()
def print_note():
new_report.write("\nNotes:")
for txt in texts:
new_report.write("\n-%r" % txt)
print "Note Printed to %r. Goodbye!" % file_name
exit(0)
My goal here is to make it so if/when "notes()" is called a second(or ad infinitum) time the new inputs are added to "texts" list and dont overwrite the list. I tried attempting to at least determine if the list was empty whenever "notes()" is called. But every time I do, regardless of how many items ive created in "texts" during the previous calling, it always prints "no notes exist."
I'm kind of at a loss at this point. I've looked into the dictionary function but im not sure how to incorporate it into this code. Anyone have any advice/suggestions?
I agree with the comments that suggest a better design would be to create a class that contains the texts. However, with respect to the code as it stands, it appears to me that texts = [] should be in the main code, outside notes(), so that the line is only ever run once.
without changing too much of what you have above, can I suggest a function that simply requests a new note, and appends the note to the existing list:
>>> notes = []
>>> def write_note(notes):
... while True:
... new_note = raw_input('>>> ')
... if not new_note:
... break
... else:
... notes.append(new_note)
Does this do what you are after?
When you call texts = [] you set text to an empty list, blanking out any items set earlier. Removing that line should help.
Also, I think may you want to use the .extend() function. Append adds an item on to the end of a list, i.e.:
>>li = [1,2,3]
>>li2 = [4,5,6]
>>li.append(li2)
li = [1,2,3,[4,5,6]]
Where as extend() concatenates two lists:
>>li = [1,2,3]
>>li2 = [4,5,6]
>>li.extend(li2)
li = [1,2,3,4,5,6]
This can be found on dive into python