I'm working on a choose-your-own-adventure project whose main function accepts 3 paramters.
First parameter is printed by the function. This is always a variable containing text describing the scenario
The second parameter is always a variable containing choices pertaining to the current scenario, which is printed by the function
The third parameter is a dictionary whose keys correspond to the scenario choices, and are compared against user's input. The value of the keys contain the next 3 arguments.
Example.
text1 = 'This is the scenario'
text2 = 'These are the choices'
dict2 = {'1':[text2, text1, dict1]}
dict1 = {'1':[text1, text2, dict2]}
def mainloop(scenario, choice, consequence):
print scenario
print choice
answer = raw_input('Please input 1, 2 or 3>>> ')
if answer in consequence.keys():
mainloop(*consequence[answer])
mainloop(text3, text2, dict1)
I thought this would be a good way to design my project, however I am running into a problem with the dictionary parameter. Because the dictionary values contain a list of arguments, which include other dictionaries I keep getting the error:
NameError: name 'dict1' is not defined
Flipflopping the order I define the dictionaries in expectedly results in the same error, only with 'dict2' not being defined. Any advice on how I can get this concept to work? Or is it time to take a completely different approach?
I'm not quite sure why you need two dicts, but assuming you do, it is possible to define dicts with circular references:
text1 = 'This is the scenario'
text2 = 'These are the choices'
dict1, dict2 = {}, {}
dict2['1'] = [text2, text1, dict1]
dict1['1'] = [text1, text2, dict2]
There are a couple of things that I would suggest rethinking about the approach as a whole.
As others pointed out, mainloop() isn't actually a loop; it's a recursive function. Ideally, if this is a game loop, you'd want it to be more like…
def myGameLoop():
gameRunning = True
while gameRunning:
# code that displays your rooms, gets user input,
#and checks to make sure that gameRunning is not False.
#for an example, something like:
if somethingAwfulHappened
gameRunning = False
In this way you don't have to call the mainloop more than once, and there's no reason for it to call itself.
Additionally, the reason your room dicts/lists keep telling you they don't exist is because, well, they don't :) This is actually a fairly good example of why it's a good idea to separate your concerns!
Think of it this way: why does a 'room' object - whether it is a dict, a list, an object, etc - need to contain any data about other rooms? Your kitchen might lead to your bathroom, sure - but does your kitchen KNOW that it leads to the bathroom? Does it serve a new purpose by leading to the bathroom instead of your bedroom? In the same way that your kitchen does not "care" that it is connected to your bathroom, neither do your dicts need to "know" that they are connected by explicitly naming each other in their own data.
An ideal approach might be instead to go and define all your rooms, and then create a 'map' which describes the relationship between your rooms. So for example:
kitchen = {
"name":"Kitchen",
"description": "This is the kitchen! It's nice and clean.",
"exits": "S", "E"
}
bathroom = {
"name":"Bathroom",
"description":"This is the bathroom. Someone left a towel on the floor.",
"exits":"W", "S"
}
#and so on, creating rooms
Now create a map dict that just holds all this info and describes how those exits work.
mapOfHouse = {
"kitchen": kitchen,
"leadsTo": {
"S": bathroom,
"E": someOtherRoom ##some other place you've defined
},
"bathroom": bathroom,
"leadsTo": {
"S": otherAwesomePlaces,
"E": kitchen
},
#and so on for other rooms in the house/on the map/etc
}
Once you sketch all this out, you then set your gameloop to get your player's input, check it against the room's exits, and if there's a match, as long as the loop is still True it heads back up to the top, displaying the updated information.
It seems like a lot more work, but really this gives you an immense amount of freedom. It lets you focus strictly on rooms as you design them, then focus strictly on the map as you update it, and then lets you design a game loop which doesn't really care a lot about the contents of what it's looping over, as long as it stays True the whole time and gets good instructions from the player.
You referencing the dict1 within dict2, but dict1 doesn't exist yet.
Your problem is the following:
dict2 = {'1':[text2, text1, dict1]} # NameError: Here dict1 does not exist yet
dict1 = {'1':[text1, text2, dict2]}
You can only solve this by defining the objects before referencing them.
In order to achieve that, you can do as follows:
dict1, dict2 = {}, {} # Define both objects
dict1[1] = [text2, text1, dict2] # Here dict2 is already defined, no NameError
dict1[2] = None # ...
dict2[1] = [text1, text2, dict1] # And here is dict1 already defined too
dict2[2] = None # ...
The question we could ask is: does referencing an object and later changing it alter the reference?
The answer is yes, it does; provided you're using references and not copies (asigning dictonaries always references them).
What if you wanted to make a copy and not a reference?
Well, you can do that via the deepcopy and copy functions from the copy module.
The problem with NameErrors is that there is no such name defined; Python does not use names to track variables: the same name can correspond to different variables (in different scopes, or at different times) and the same variable can be accessed via different names (by assigning one name's value to the other).
When you do del x, you unlink a variable from its name, but you don't always eliminate the object.
For example, the following code works and prints stash correctly, altough via the del operator we unlinked the str object 'hello' from the object x that contained it.
x = {1: 'hello'}
stash = x[1]
del x[1]
print stash
By deleting the stash object too the 'hello' object may be now prone to be garbage-collected at some point.
Reminder
If you want to refer to other objects via their names, they have to be named before that reference happens.
Related
The below block of code works as intended
patient = Patient()
patient.log = []
patient.id = "xyz"
patient.example_attribute = []
ALL_PATIENT_LOG = []
def update(patient, attribute, argument, replace = False):
now = datetime.now()
entry = {"argument": argument, "attribute": attribute, "time": now.strftime("%H:%M on %d/%m/%y")}
patient.log.append(entry)
But when I add the following to the end of update
entry["patient_id"] = patient.id # we also need to include the patient's ID for the global log
ALL_PATIENT_LOG.append(entry)
if replace:
patient.__dict__[attribute] = [argument]
else:
patient.__dict__[attribute].append(argument)
the patient.log entry is changed such that it also contains the patient id
This violates my understanding of how python works, as I thought that later lines cannot affect how earlier lines are executed. What have I misunderstood which prevents me from understanding why this executes the way it does? How could I change this code to get the desired behaviour? (two different log entries depending on whether its being appended to the patient log or the ALL_PATIENT_LOG)
The line
patient.log.append(entry)
Appends the entry dictionary to the patient.log, it does not "add" the elements of the entry dictionary to the list. So when you in the next line call
entry["patient_id"] = patient.id
You are changing the entry dictionary, and since the patient.log is referencing to that dictionary, it will have the updated information when you look up that list.
A way to solve this, is to create a copy of the dictionary, instead of a reference, also see this post :
patient.log.append(entry.copy())
As that post also mentions, make sure you understand how copy works, as it might not always work as intended. Especially if there are references within the object you copy.
I'm trying to store a function in a list, retrieve the function from the list later, and then call on that function. This is basically what I want to do, without any specifics. It doesn't show my purpose, but it's the same issue.
elements: list = [] # List meant to contain a tuple with the name of the item and the function of the item.
def quit_code():
exit()
element.append(("quit", quit_code))
Now, somewhere else in the code, I want to be able to use an if statement to check the name of the item and, if it's the right one at that time, run the function.
user_input = "quit" # For brevity, I'm just writing this. Let's just imagine the user actually typed this.
if elements[0][0] == user_input:
#This is the part I don't understand so I'm just going to make up some syntax.
run_method(elements[0][1])
The method run_method that I arbitrarily made is the issue. I need a way to run the method returned by elements[0][1], which is the quit_code method. I don't need an alternative solution to this example because I just made it up to display what I want to do. If I have a function or object that contains a function, how can I run that function.
(In the most simplified way I can word it) If I have object_a (for me it's a tuple) that contains str_1 and fun_b, how can I run fun_b from the object.
To expand on this a little more, the reason I can't just directly call the function is because in my program, the function gets put into the tuple via user input and is created locally and then stored in the tuple.
__list_of_stuff: list = []
def add_to_list(name, function):
__list_of_stuff.append((name, function))
And then somewhere else
def example_init_method():
def stop_code():
exit()
add_to_list("QUIT", stop_code())
Now notice that I can't access the stop_code method anywhere else in the code unless I use it through the __list_of_stuff object.
Finally, It would be nice to not have to make a function for the input. By this, I mean directly inserting code into the parameter without creating a local function like stop_code. I don't know how to do this though.
Python treats functions as first-class citizens. As such, you can do things like:
def some_function():
# do something
pass
x = some_function
x()
Since you are storing functions and binding each function with a word (key), the best approach would be a dictionary. Your example could be like this:
def quit_code():
exit()
operations = dict(quit=quit_code)
operations['quit']()
A dictionary relates a value with a key. The only rule is the key must be immutable. That means numbers, strings, tuples and other immutable objects.
To create a dictionary, you can use { and }. And to get a value by its key, use [ and ]:
my_dictionary = { 'a' : 1, 'b' : 10 }
print(my_dictionary['a']) # It will print 1
You can also create a dictionary with dict, like so:
my_dictionary = dict(a=1, b=10)
However this only works for string keys.
But considering you are using quit_code to encapsulate the exit call, why not using exit directly?
operations = dict(quit=exit)
operations['quit']()
If dictionaries aren't an option, you could still use lists and tuples:
operations = [('quit',exit)]
for key, fun in operations:
if key == 'quit':
fun()
For my examine command, because I don't want to do this:
def examine(Decision):
if Decision == "examine sword":
print sword.text
elif Decision == "examine gold":
print gold.text
elif Decision == "examine cake":
print cake.text
...
for every item in my game.
So I wanted to convert the second word of the Decision string into a variable so that I could use something like secondwordvar.text.
I tried to use eval(), but I always get an errors when I make a spelling mistake in a single word command.
The error
IndexError: list index out of range
It's be working otherwise though.
Right now my code is this:
def exam(Decision):
try:
examlist = shlex.split(Decision)
useditem = eval(examlist[1])
print useditem.text
except NameError:
print "This doesn't exist"
Does anyone have an idea, for an other option, how I could write that function in a easy way?
I should probably also include the full game. You can find it here:
http://pastebin.com/VVDSxQ0g
Somewhere in your program, create a dictionary mapping the name of the object to a variable that it represents. For example:
objects = {'sword': sword, 'gold': gold, 'cake': cake}
Then you can change your examine() function to something like the following:
def examine(Decision):
tokens = shlex.split(Decision)
if len(tokens) != 2 or tokens[0] != 'examine' or tokens[1] not in objects:
print "This doesn't exist"
else:
print objects[tokens[1]].text
What you could do (because with my knowledge in programming, somewhat limited, this is the most advanced way I could see it) is to utilize dictionaries. I'll try to explain in english, because my knowledge of code in this field is suspect and I don't want to mislead you.
Dictionaries are very array-like, allowing you to associate a decision with a value.
You would be able to associate Examine sword with an action code 4
This would (in a hack-y way) allow you to convert your string to a variable, more by direct and consistent referencing of key/value pairs.
Good luck with this approach; Read up some on Dictionaries and you may very well find them easier to handle than it sounds!
Finally, as a form of good coding practice, never use eval() unless you are sure of what you are doing. eval() executes the code inside the (), so if, god forbid, some malicious process manages to run that code with a malicious line injected inside it:
eval(###DELETE EVERYTHING RAWR###)
You'll have a bad time. Sincerely.
Also, for the sake of evaluating code, I've heard that it is a very slow command, and that there are better alternatives, performance-wise.
Happy coding!
These two print the same text:
Using a dictionary:
texts = dict(sword = "wathever",
gold = "eachever",
cake = "whomever")
def examine_dict(decision):
decision = decision.split()[1]
print texts[decision]
examine_dict("examine sword")
Using object attributes (a class):
class Texts():
sword = "wathever"
gold = "eachever"
cake = "whomever"
def examine_attribute(decision):
decision = decision.split()[1]
text = getattr(Texts, decision)
print text
examine_attribute("examine sword")
Depending on what you want, one method can be more appropriate than the other. The dictionary-based method, however, is in general, the easier and the faster one.
Your variables are stored in a dictionary somewhere. If they are global variables, globals() returns this dictionary. You can use this to look up the variable by name:
globals()['sword'].text
If the variables are stored in a class as attributes, you can use getattr:
getattr(object, 'sword').text
You'll want to catch possible exceptions for bad names.
Ok, I have a dictionary called food. food has two elements, both of which are dictionaries themselves, veg and dairy. veg has two elements root : Turnip, and stem : Asparagus. dairy has cheese : Cheddar and yogurt : Strawberry. I also have a new dictionary fruit which has red : Cherry and yellow : Banana.
food['veg']['root'] == 'Turnip'
food['dairy']['cheese'] == 'Cheddar'
etc and
fruit['red'] == 'Cherry'
Now I would like to add the "fruit" dictionary to the "food" dictionary in its entirety, so that I will have:
food['fruit']['red'] == 'Cherry'
I know that I could do something like this:
food['fruit'] = fruit
But that seems clumsy. I would like to do something like
food.Append(fruit)
But that doesn't do what I need.
(Edited to removed the initial capitals from variable names, since that seemed to be causing a distraction.)
Food['Fruit'] = Fruit is the right and proper way (apart from the capitalized names).
As #kindall wisely notes in the comment, there can be several names referencing the same dictionary, which is why one can't build a function that maps the object to its name and uses that as the new key in your food dict.
I know what you are trying to do. You are trying to avoid DRY in python. Sadly python, and many other languages, are very bad at this.
The main issue though is that You are mixing the names of your variables with the values in your program. It is a common faux pas in many programming languages.
If you really wanted to do this, the thing you have bound to the fruit=... variable would need to know its name.
You are trying to say, in python "graft this dict onto this other dict".
Python demands that you say it like "graft this dict onto this other dict, attaching it at "Fruit""
The only way around this is that the name "Fruit" already exist somewhere. But it doesn't: it only exists in a variable name, which is not in your program.
There are two solutions:
You could avoid ever creating a fruit=... variable, and instead directly graft it only the "Fruit" name. So you would only have to type "Fruit" once, but instead of not typing the somedict["Fruit"] like you want, we're avoiding typing the variable name. This is accomplished by programming in anonymous style:
somedict["Fruit"] = {'red':'apple', 'yellow':'banana'}
Sadly, python will not let you do this if your construction requires statements; you can only get away with this if you just have a literal. The other solution is:
You could create a function which does this for you:
graft(somedict, "Fruit", {'red':'apple', 'yellow':'banana'})
Sadly this too would not work if your construction required any kind of statement. You could create a variable x={'red':...} or something, but that defeats the whole purpose. The third way, which you shouldn't use, is locals(), but that still requires you to refer to the name.
In conclusion, IF you require significant for loops and functions and if statements, what you are trying to do is impossible in python, unless you change the entire way you construct your fruit=... dictionary. It would be possible with combinations of multiline lambdas, dictionary comprehensions (dict((k,v) for k,v in ...)), inline IFTRUE if EXPR else IFFALSE, etc. The danger of this style is that it very quickly becomes hard to read.
It is possible if you are able to express your dictionary as a literal dictionary, or a dictionary comprehension, or the output of a function which you have already written. In fact it's fairly easy (see other answers). Unfortunately the original question does not say how you are building these dictionaries.
Assuming those answers don't answer your question (that is, you are building these in a really complicated manner), you can write "meta" code: code that will make your dictionary for you, and abuse reflection. However the best solution in python is to just try to make your dictionary with iteration. For example:
foods = {
"Fruit": {...},
"Meats": makeMeats(),
}
for name,data in ...:
foods[name] = someProcessing(data)
foods.update(dataFromSomeFile) #almost same as last two lines
Is there any reason you're using the square brackets? Because you can represent this data structure with nested literal dictionaries:
food = {
'veg': {
'red': 'tomato',
'green': 'lettuce',
},
'fruit': {
'red': 'cherry',
'green': 'grape',
},
}
You can't do append because a dictionary is not a list: it has no order. What you want to do is update the dictionary with a new key/value pair. You need to use:
Food['Fruit'] = Fruit
or, alternatively:
Food.update({'Fruit': Fruit})
An unrelated note: it's not Python coding style to write variables with capitals. Fruit would be written as fruit instead.
The basic problem you have is that your dictionary does not know its own name. Which is normal; generally, any number of names can be bound to a Python object, and no single name is in any way privileged over any others. In other words, in a = {}; b = a, both a and b are names for the same dictionary, and a is not the "real" name of the dictionary just because it was assigned first. And in fact, a dictionary has no way to even know what name is on the left side of the variable.
So one alternative is to have the dictionary contain its own name as a key. For example:
fruit = {"_name": "fruit"}
fruit["red"] = "cherry"
food[fruit["_name"]] = fruit
Well, that didn't help much, did it? It did in a way, because fruit is now not a string any longer in the attachment to the food dictionary, so at least Python will give you an error message if you mistype it. But you're actually typing "fruit" even more than before: you now have to type it when you create the dictionary in addition to when you attach it to another dictionary. And there is a fair bit more typing in general.
Also, having the name as an item in the dictionary is kind of inconvenient; when you are iterating over the dictionary, you have to write code to skip it.
You could write a function to do the attachment for you:
def attach(main, other):
main[other["_name"]] = other
Then you don't have to repeat yourself when you attach the sub-dictionary to the main one:
fruit = {"_name": "fruit"}
fruit["red"] = "cherry"
attach(food, fruit)
And of course, now you can actually create a dictionary subclass that knows its own name and can attach a named subdictionary. As a bonus, we can make the name an attribute of the dictionary rather than storing it in the dictionary, which will keep the actual dictionary cleaner.
class NamedDict(dict):
def __init__(self, name="", seq=(), **kwargs):
dict.__init__(self, seq, **kwargs)
self.__name__ = name
def attach(self, other):
self[other.__name__] = other
food = NamedDict("food")
fruit = NamedDict("fruit")
fruit["red"] = "cherry"
food.attach(fruit)
But we still have one repeat, when the NamedDict is initially defined: food = NamedDict("food") for example. How do we dispense with that?
It is possible, though unwieldy and probably not worth the trouble. Python has two kinds of objects that have an "intrinsic" name: classes and functions. In other words:
class Foo:
pass
The above not only creates a variable named Foo in the current namespace, the class's name is also conveniently stored in the class's __name__ attribute. (Functions do something similar.) By abusing classes and metaclasses, we can exploit the underlying machinery to completely avoid repeating ourselves—with the minor drawback of having to write our dictionaries as though they were classes!
class NamedDict(dict):
class __metaclass__(type):
def __new__(meta, name, bases, attrs):
if "NamedDict" not in globals(): # we're defining the base class
return type.__new__(meta, name, bases, attrs)
else:
attrs.pop("__module__", None) # Python adds this; do not want!
return meta.NamedDict(name, **attrs)
class NamedDict(dict):
def __init__(self, name, seq=(), **kwargs):
dict.__init__(self, seq, **kwargs)
self.__name__ = name
def attach(self, other):
self[other.__name__] = other
__call__ = NamedDict
Now, instead of defining our dictionaries the usual way, we declare them as subclasses of NamedDict. Thanks to the metaclass, subclassing the outer NamedDict class actually creates instances of the inner NamedDict class (which is the same as before). The attributes of the subclass we define, if any, become items in the dictionary, like keyword arguments of dict().
class food(NamedDict): pass
class fruit(NamedDict): red = "cherry"
# or, defining each item separately:
class fruit(NamedDict): pass
fruit["red"] = "cherry"
food.attach(fruit)
As a bonus, you can still define a NamedDict the "regular" way, by instantiating it as a class:
fruit = NamedDict("fruit", red="cherry")
Be warned, though: the "class that's really a dictionary" is a pretty non-standard idiom for Python and I would suggest that you not ever actually do this, as other programmers will not find it at all clear. Still, this is how it can be done in Python.
You are probably looking for defaultdict. It works by adding a new empty dictionary whenever you ask for a new first level type.
Example shown below:
from collections import defaultdict
basic_foods = {'Veg' : {'Root' : 'Turnip'}, 'Dairy' : {'Cheese' : 'Cheddar'}}
foods = defaultdict(dict, basic_foods)
foods['Fruit']['Red'] = "Cherry"
print foods['Fruit']
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])