Module with text files - python

I am very new to python, and am writing a code with multiple modules.
Each of my modules manipulates the same list that I have named "myList", however, I am having trouble understanding how to get the list into each module.
For example, one module called reverseList.py needs to take the list and reverse it, but when it is run in my main function, I get an error that the list does not exist.
Import reverseList
def main():
with open('list3.txt', 'r') as f:
data = f.read()
data = data.split("\n")
myList = [row.split(",") for row in data]
reverseList.reverse()
NameError: name 'myList' is not defined
The reverseList.py module is as follows:
def reverse()
myList1 = myList[::-1]
print(myList1)
return

It is unclear where exactly the error comes out since you didn't include your entire main function - there is no place myList is used before/after its definition. But I can think of a couple of reasons for the error.
The error shows up when a variable is used before it is defined. So, you might have the variable myList before you define it in line 4 of your current code.
In python, indentation is the matter of correctness of your code. Meaning, line 2~4 should be indented if you didn't do so.
I might be able to come up with a better answer if you present the rest part of the code.
Your update reveals where the problem is happening; that is from your reverseList, not your main.
You are loading myList in reverseList, but it has never been defined. myList defined in main is not accessible from reverseList. To fix this problem, you should pass myList as an argument to the function reverse when it is called and use that in your reverse function.
main:
reverseList.reverse(myList)
reverseList:
def reverse(myList):
myList1 = myList[::-1]
print(myList1)
return
Note that the argument name of the function reverse can be different from the one in main. In other words, it doesn't matter if you do follow;
def reverse(myList2):
myList1 = myList2[::-1]
print(myList1)
return
This might be better:
def reverse(myList2):
print(myList2[::-1])

Related

function calling by rigid python keyword

why list object is not callable inside a function ??
CODE:
def unique_list(list1):
sets=set(list1)
u_list=(list(sets))
print("old list",list1)
print('unique list',u_list)
list1=[1,1,2,3,4,4,5]
unique_list(list1)
when i did this.. I got the exact output [1,2,3,4,5]... BUT
if i use list in lieu of list1 or any other name like the following code:
def unique_list(list):
sets=set(list)
u_list=(list(sets))
print("old list",list)``
print('unique list',u_list)
list=[1,1,2,3,4,4,5]
unique_list(list)
python throws error:
TypeError: 'list' object is not callable
is it for this reason that rigid keywords must not be used as variable name ?? or for other reasons ??
Heres working code for what you want to do
def unique_list(list1):
print("old list",list1)
print('unique list',(list(set(list1))))
list1=[1,1,2,3,4,4,5]
unique_list(list1)
here's why your code wasn't working
lets take a look at the code that defines your function
def unique_list(list):
#code
list is a class name and list() is a function that is native to python; by making it a parameter and or variable, you are overriding it!
So, when you call list(set(list)) its basically saying: parameter(set(parameter))
Obviously the parameter cant be a function and a list at the same time; so there isn't any scenario where this could work.
I recommend using convention names like so if you arent sure what to call a list:
lst = []
x = []
l = []
The only time you should ever put any of these names alone into the definition of a function is through type-hinting
def foo(s: str, l: list) -> list:
#do code
return l + list(s)
In conclusion... it's a horrible practice to use any built-in function/class names in python as variable/functions unless you are actually trying to override them.

Can't use returned variable in another file - Python

I am trying to use a variable defined in one file (file1.py) in another file (file2.py).
File 1 contains "shoe" which is a queue, which has been tested and worked fine. So it does not look like the problem is with the implementation of the queue.
Context on what the variable of issue is:
result is merely a shuffled list made out of another list called cardList. result is shuffled within the shuffle function. It is a local variable within the scope of shuff. To get around this, I did try using: global result, and then import it again, but it did not work, so I am probably using global wrong?
Here are what I have tried so far that don't work for me:
In File1: where cardList is a list of 120 items.
def shuff(deck): # this function works fine within file1
for i in range(0, 9):
result = []
popped = cardList.pop(R.randint(0, len(cardList)-1))
result = result.append(popped)
return result
def main():
shuff(cardList)
In File2
from File1 import result
The above does not work, so I looked around and followed an answer which said my variable needs to be in main(), so I tried the following:, in File1
def main():
result = shuff(cardList)
I tried method 2 by removing the "return result" because I thought that it may override the existing result variable. But I also tried it without that, and both ways, it did not seem to work.
Lastly,
I made result a Global Var in File1 under the shuff function. And that did not seem to work either
Am I doing something wrong?
There are many issues at play here. For example, since result is not defined as a global variable, the variable only exists within your shuff function. Although method 2 is close to the answer, since your main is a function, again result only exists within that function and cannot be accessed from outside the function. If you want from File1 import result to work I suggest simply doing:
File 1:
def shuff(deck): # this function works fine within file1
for i in range(0, shoe.size()):
result = []
popped = cardList.pop(R.randint(0, len(cardList)-1))
result = result.append(popped)
return result
result = shuff(cardList)
File 2:
from File1 import result
print(result)
If you want to keep your main function, do:
File 1:
def main():
return shuff(cardList)
File 2:
from File1 import main
result = main()
print(result)
Ultimately, there are many ways of doing what you are trying to do, just pick one that applies to your needs

Python list variable scope issues

I have the following code:
def myFunction(param, param):
myList = ["",[],[],[]]
#code to fill up myList
for q,d in enumerate(detailCollection):
#all the fun stuff here
yield{
"var1":myList[0],
"var2":myList[1],
#and so on
}
The error I am getting is as follows:
NameError: name 'myList' is not defined
Coming from the lines in the yield statement
For privacy purposes I haven't included actual code, but this is identical situation of what is happening. Why is it saying that myList is not defined when it is clearly in the same function scope, and how can I fix this problem? I would rather not move the myList variable all the way out and call it a global variable, to keep the code clean and concise is there a way to do this without moving myList declaration/definition?
So I didn't realize I had an extra _ laying around in my yield statement. No biggy :) Problem solved.

Python string interpolation implementation

[EDIT 00]: I've edited several times the post and now even the title, please read below.
I just learned about the format string method, and its use with dictionaries, like the ones provided by vars(), locals() and globals(), example:
name = 'Ismael'
print 'My name is {name}.'.format(**vars())
But I want to do:
name = 'Ismael'
print 'My name is {name}.' # Similar to ruby
So I came up with this:
def mprint(string='', dictionary=globals()):
print string.format(**dictionary)
You can interact with the code here:
http://labs.codecademy.com/BA0B/3#:workspace
Finally, what I would love to do is to have the function in another file, named my_print.py, so I could do:
from my_print import mprint
name= 'Ismael'
mprint('Hello! My name is {name}.')
But as it is right now, there is a problem with the scopes, how could I get the the main module namespace as a dictionary from inside the imported mprint function. (not the one from my_print.py)
I hope I made myself uderstood, if not, try importing the function from another module. (the traceback is in the link)
It's accessing the globals() dict from my_print.py, but of course the variable name is not defined in that scope, any ideas of how to accomplish this?
The function works if it's defined in the same module, but notice how I must use globals() because if not I would only get a dictionary with the values within mprint() scope.
I have tried using nonlocal and dot notation to access the main module variables, but I still can't figure it out.
[EDIT 01]: I think I've figured out a solution:
In my_print.py:
def mprint(string='',dictionary=None):
if dictionary is None:
import sys
caller = sys._getframe(1)
dictionary = caller.f_locals
print string.format(**dictionary)
In test.py:
from my_print import mprint
name = 'Ismael'
country = 'Mexico'
languages = ['English', 'Spanish']
mprint("Hello! My name is {name}, I'm from {country}\n"
"and I can speak {languages[1]} and {languages[0]}.")
It prints:
Hello! My name is Ismael, I'm from Mexico
and I can speak Spanish and English.
What do you think guys? That was a difficult one for me!
I like it, much more readable for me.
[EDIT 02]: I've made a module with an interpolate function, an Interpolate class and an attempt for a interpolate class method analogous to the function.
It has a small test suite and its documented!
I'm stuck with the method implementation, I don't get it.
Here's the code: http://pastebin.com/N2WubRSB
What do you think guys?
[EDIT 03]: Ok I have settled with just the interpolate() function for now.
In string_interpolation.py:
import sys
def get_scope(scope):
scope = scope.lower()
caller = sys._getframe(2)
options = ['l', 'local', 'g', 'global']
if scope not in options[:2]:
if scope in options[2:]:
return caller.f_globals
else:
raise ValueError('invalid mode: {0}'.format(scope))
return caller.f_locals
def interpolate(format_string=str(),sequence=None,scope='local',returns=False):
if type(sequence) is str:
scope = sequence
sequence = get_scope(scope)
else:
if not sequence:
sequence = get_scope(scope)
format = 'format_string.format(**sequence)'
if returns is False:
print eval(format)
elif returns is True:
return eval(format)
Thanks again guys! Any opinions?
[EDIT 04]:
This is my last version, it has a test, docstrings and describes some limitations I've found:
http://pastebin.com/ssqbbs57
You can quickly test the code here:
http://labs.codecademy.com/BBMF#:workspace
And clone grom git repo here:
https://github.com/Ismael-VC/python_string_interpolation.git
Modules don't share namespaces in python, so globals() for my_print is always going to be the globals() of my_print.py file ; i.e the location where the function was actually defined.
def mprint(string='', dic = None):
dictionary = dic if dic is not None else globals()
print string.format(**dictionary)
You should pass the current module's globals() explicitly to make it work.
Ans don't use mutable objects as default values in python functions, it can result in unexpected results. Use None as default value instead.
A simple example for understanding scopes in modules:
file : my_print.py
x = 10
def func():
global x
x += 1
print x
file : main.py
from my_print import *
x = 50
func() #prints 11 because for func() global scope is still
#the global scope of my_print file
print x #prints 50
Part of your problem - well, the reason its not working - is highlighted in this question.
You can have your function work by passing in globals() as your second argument, mprint('Hello my name is {name}',globals()).
Although it may be convenient in Ruby, I would encourage you not to write Ruby in Python if you want to make the most out of the language.
Language Design Is Not Just Solving Puzzles: ;)
http://www.artima.com/forums/flat.jsp?forum=106&thread=147358
Edit: PEP-0498 solves this issue!
The Template class from the string module, also does what I need (but more similar to the string format method), in the end it also has the readability I seek, it also has the recommended explicitness, it's in the Standard Library and it can also be easily customized and extended.
http://docs.python.org/2/library/string.html?highlight=template#string.Template
from string import Template
name = 'Renata'
place = 'hospital'
job = 'Dr.'
how = 'glad'
header = '\nTo Ms. {name}:'
letter = Template("""
Hello Ms. $name.
I'm glad to inform, you've been
accepted in our $place, and $job Red
will ${how}ly recieve you tomorrow morning.
""")
print header.format(**vars())
print letter.substitute(vars())
The funny thing is that now I'm getting more fond of using {} instead of $ and I still like the string_interpolation module I came up with, because it's less typing than either one in the long run. LOL!
Run the code here:
http://labs.codecademy.com/BE3n/3#:workspace

Scope, using functions in current module

I know this must be a trivial question, but I've tried many different ways, and searched quie a bit for a solution, but how do I create and reference subfunctions in the current module?
For example, I am writing a program to parse through a text file, and for each of the 300 different names in it, I want to assign to a category.
There are 300 of these, and I have a list of these structured to create a dict, so of the form lookup[key]=value (bonus question; any more efficient or sensible way to do this than a massive dict?).
I would like to keep all of this in the same module, but with the functions (dict initialisation, etc) at the
end of the file, so I dont have to scroll down 300 lines to see the code, i.e. as laid out as in the example below.
When I run it as below, I get the error 'initlookups is not defined'. When I structure is so that it is initialisation, then function definition, then function use, no problem.
I'm sure there must be an obvious way to initialise the functions and associated dict without keeping the code inline, but have tried quite a few so far without success. I can put it in an external module and import this, but would prefer not to for simplicity.
What should I be doing in terms of module structure? Is there any better way than using a dict to store this lookup table (It is 300 unique text keys mapping on to approx 10 categories?
Thanks,
Brendan
import ..... (initialisation code,etc )
initLookups() # **Should create the dict - How should this be referenced?**
print getlookup(KEY) # **How should this be referenced?**
def initLookups():
global lookup
lookup={}
lookup["A"]="AA"
lookup["B"]="BB"
(etc etc etc....)
def getlookup(value)
if name in lookup.keys():
getlookup=lookup[name]
else:
getlookup=""
return getlookup
A function needs to be defined before it can be called. If you want to have the code that needs to be executed at the top of the file, just define a main function and call it from the bottom:
import sys
def main(args):
pass
# All your other function definitions here
if __name__ == '__main__':
exit(main(sys.argv[1:]))
This way, whatever you reference in main will have been parsed and is hence known already. The reason for testing __name__ is that in this way the main method will only be run when the script is executed directly, not when it is imported by another file.
Side note: a dict with 300 keys is by no means massive, but you may want to either move the code that fills the dict to a separate module, or (perhaps more fancy) store the key/value pairs in a format like JSON and load it when the program starts.
Here's a more pythonic ways to do this. There aren't a lot of choices, BTW.
A function must be defined before it can be used. Period.
However, you don't have to strictly order all functions for the compiler's benefit. You merely have to put your execution of the functions last.
import # (initialisation code,etc )
def initLookups(): # Definitions must come before actual use
lookup={}
lookup["A"]="AA"
lookup["B"]="BB"
(etc etc etc....)
return lookup
# Any functions initLookups uses, can be define here.
# As long as they're findable in the same module.
if __name__ == "__main__": # Use comes last
lookup= initLookups()
print lookup.get("Key","")
Note that you don't need the getlookup function, it's a built-in feature of a dict, named get.
Also, "initialisation code" is suspicious. An import should not "do" anything. It should define functions and classes, but not actually provide any executable code. In the long run, executable code that is processed by an import can become a maintenance nightmare.
The most notable exception is a module-level Singleton object that gets created by default. Even then, be sure that the mystery object which makes a module work is clearly identified in the documentation.
If your lookup dict is unchanging, the simplest way is to just make it a module scope variable. ie:
lookup = {
'A' : 'AA',
'B' : 'BB',
...
}
If you may need to make changes, and later re-initialise it, you can do this in an initialisation function:
def initLookups():
global lookup
lookup = {
'A' : 'AA',
'B' : 'BB',
...
}
(Alternatively, lookup.update({'A':'AA', ...}) to change the dict in-place, affecting all callers with access to the old binding.)
However, if you've got these lookups in some standard format, it may be simpler simply to load it from a file and create the dictionary from that.
You can arrange your functions as you wish. The only rule about ordering is that the accessed variables must exist at the time the function is called - it's fine if the function has references to variables in the body that don't exist yet, so long as nothing actually tries to use that function. ie:
def foo():
print greeting, "World" # Note that greeting is not yet defined when foo() is created
greeting = "Hello"
foo() # Prints "Hello World"
But:
def foo():
print greeting, "World"
foo() # Gives an error - greeting not yet defined.
greeting = "Hello"
One further thing to note: your getlookup function is very inefficient. Using "if name in lookup.keys()" is actually getting a list of the keys from the dict, and then iterating over this list to find the item. This loses all the performance benefit the dict gives. Instead, "if name in lookup" would avoid this, or even better, use the fact that .get can be given a default to return if the key is not in the dictionary:
def getlookup(name)
return lookup.get(name, "")
I think that keeping the names in a flat text file, and loading them at runtime would be a good alternative. I try to stick to the lowest level of complexity possible with my data, starting with plain text and working up to a RDMS (I lifted this idea from The Pragmatic Programmer).
Dictionaries are very efficient in python. It's essentially what the whole language is built on. 300 items is well within the bounds of sane dict usage.
names.txt:
A = AAA
B = BBB
C = CCC
getname.py:
import sys
FILENAME = "names.txt"
def main(key):
pairs = (line.split("=") for line in open(FILENAME))
names = dict((x.strip(), y.strip()) for x,y in pairs)
return names.get(key, "Not found")
if __name__ == "__main__":
print main(sys.argv[-1])
If you really want to keep it all in one module for some reason, you could just stick a string at the top of the module. I think that a big swath of text is less distracting than a huge mess of dict initialization code (and easier to edit later):
import sys
LINES = """
A = AAA
B = BBB
C = CCC
D = DDD
E = EEE""".strip().splitlines()
PAIRS = (line.split("=") for line in LINES)
NAMES = dict((x.strip(), y.strip()) for x,y in PAIRS)
def main(key):
return NAMES.get(key, "Not found")
if __name__ == "__main__":
print main(sys.argv[-1])

Categories

Resources