I'm coding this program but running it and typing "2" when I type a subject it doesn't print the result once but nine times. Where is the problem? 9 is the number of subjects in the list named mat so it's strictly connected. Now to check some files .txt as placeholder but I'd like also using the module json.
import os
def spat():
a=len(list(os.listdir('C:/Users/SUINO/Desktop/python/prob/cache/'+y)))
print(a)
b=100/(25-a)
print(b)
mat=["latino","greco","storia","latino","scienze","matematica","grammatica",
"promessi sposi,","eneide"] #mat means subject
c=input("Do you want to add a placeholder or calculate probabilties? 1|2: ")
if c == "1":
c=input("Insert a subject: ")
c=c.lower
if c in mat:
name=input("Insert the name of the student: ")
open('C:/Users/SUINO/Desktop/python/prob/cache/'+c+'/'+name+".txt")
else:
print("Materia non esistente!")
if c == "2":
y=input("Materia: ")
y=y.lower()
x={"latino":spat(),"greco":spat(),"eneide":spat(),"promessi sposi":spat(),
"mate":spat(),"grammatica":spat(),"storia":spat(),"scienze":spat(),
"inglese":spat(),}
The objective of the program is to calculate the probabilities of being interrogated using the files .txt that have as name the name of the student interrogated yet.
If I understand your question correctly, you're basically trying to create a CLI for accessing homework or other school work that students can interact with and access their files.
I just noticed you are also trying to access var y within function spat(). You need to pass this value into the function call. If you want to map each key to the function.
If you want the key to be a reference, you need to structure your dict like this:
x = {
'latino': spat,
'greco': spat,
...
}
Then when the user enters in a value, you simply declare a new variable to be the value of the key, which in turn, creates a variable which is a reference to that function.
So if you receive input y with
y = input("Materia: ")
Then you should create a new variable like such
func = x[y]
This will find the key value entered in from the above input function and assign that reference to the variable func. Essentially, func now is equal to the function and you can execute func like any other normal function as well as pass in variables.
func(y)
This will execute the function referenced (spat) and pass in variable y. You also need to rewrite spat() as such:
def spat(y):
a = len(list(os.listdir('C:/Users/SUINO/Desktop/python/prob/cache/'+y)))
print(a)
b = 100/(25-a)
print(b)
Essentially the same except you're now passing in y from the input below.
You also need to move the declaration of the dictionary to the top so that your reference to this dictionary will be recognized when you declare func.
So whole code:
import os
def spat(y):
a = len(list(os.listdir('C:/Users/SUINO/Desktop/python/prob/cache/'+y)))
print(a)
b=100/(25-a)
print(b)
x = {"latino":spat,"greco":spat,"eneide":spat,"promessi sposi":spat,
"mate":spat,"grammatica":spat,"storia":spat,"scienze":spat,
"inglese":spat,} # x moved up from bottom
mat = ["latino","greco","storia","latino","scienze","matematica","grammatica",
"promessi sposi,","eneide"] #mat means subject
c = input("Do you want to add a placeholder or calculate probabilties? 1|2: ")
if c == "1":
c = input("Insert a subject: ")
c = c.lower
if c in mat:
name = input("Insert the name of the student: ")
open('C:/Users/SUINO/Desktop/python/prob/cache/'+c+'/'+name+".txt")
else:
print("Materia non esistente!")
if c == "2":
y=input("Materia: ")
y=y.lower()
func = x[y] # creates reference to the key which is a ref to a function
func(y)
However, since every key value is executing the same function, you might be better served not writing new dictionary entries for each new key and just simply making a list of recognized subjects that the student may enter:
subjects = ['latino', 'greco', 'grammatica', ...]
Then you can simply check whether the input exists within this list and, if it does, run spat() and pass in y.
if y in subjects:
spat(y)
else:
print("Unrecognized command...")
Mapping functions within a dictionary is useful for creating an 'interface' that can route the various inputs to a function that will be executed for that given option. You can check whether or not their command works by simply checking for their input within a list/dict and if it doesn't exist, then you can skip running the function and output an error message--if the command exists, then you can reference it to a key value (which in turn, references it to the value of that key) and then it will run the proper function.
The short answer is it's printing nine times because of all the calls to spat() you put in the statement:
x={"latino":spat(),"greco":spat(),"eneide":spat(),"promessi sposi":spat(),
"mate":spat(),"grammatica":spat(),"storia":spat(),"scienze":spat(),
"inglese":spat(),}
There are a number of other issues with your code, but since I don't completely understand everything it's trying to accomplish, I'm not going to attempt to tell you what to do other than not to call it some many times like that.
Related
I have a bit of python code that's set to run on a schedule. (I think my problem is the same as if it were within a loop.)
Let's say that in its most basic form, the code snippet looks something like this:
A = 1
B = 2
renameMe = A + B
Let's say the scheduler runs the same snippet of code every 5 minutes. The values of variables A & B are different each time the code is run, but the operation renameMe = A + B is always the same.
The values for A & B are grabbed out of a dataframe that's updated every 5 minutes, so I don't know what they are in advance, but if I need to do something with them beforehand instead of assigning them to A & B right away, I can.
I recently found out that for other things to work, I need to be able to rename the variable renameMe every time that snippet of code runs. In other words, I want the variable's name to be renameMe1 the first time the code snippet runs, then renameMe2 when it runs 5 minutes later, and so on.
It doesn't really matter in which way the variable's name changes (ints, strs, whatever) as long as I'm able to find out what the new variable name is, and use it elsewhere.
Do NOT use a variable variable name, you will have problems, use a container:
a list:
# first time
container = []
# each loop/run
container.append(A+B)
## last value
container[-1]
a dictionary:
# first time
container = {}
# each loop/run
container['new_id'] = A+B
# access arbitrary value
container['my_previous_id']
If you need persistence, use a flat file or a database.
I think it is suitable to use a class so that setattr can be used:
class newVal:
def __init__(self):
self.n = 1
def addVal(self, a, b):
setattr(self, f”val{self.n}”, a+b)
self.n += 1
Values = newVal()
Values.addVal(a, b)
Values.val1 would now be assigned
I aggree with Mozway when saying variables names are likely to cause problems, but this is also something you could strictly manage.
globals() stores all variables names and values in the form of a collection of 2-tuples, like this one :
dict_items([('__name__', '__main__'), ..., ('thisName', 'renaMe1'), ('renaMe18', 10)])
So you should register your new variable name but not forget to delete the previous one in order to avoid overloading.
If you follow a natural law of equal births and deaths, you will avoid overpopulation.
I propose you this bunch of code (with comments inside) :
basename = 'renaMe'
def varUpdate():
# Get previous variable name
thisName = [i for i, j in globals().items() if i[:len(basename)] == basename][0]
# Define the new variable name
newName = basename + '%d'%sum([int(thisName[len(basename):]), 1])
# Register the new variable name
globals()[newName] = globals()[thisName]
# Delete previous variable name from global
del globals()[thisName]
def process(i):
# Isolate from process content for readibility
varUpdate()
# PROCESS BELOW
# ....
newVar = [i for i, j in globals().items() if i[:len(basename)] == basename][0]
print(newVar, " : ", globals()[newVar])
# With this for` loop we simulate 4 entries in process
for i in range(4):
### we enter in the process
process(i)
Test in the shell
First restart your shell and let's suppose we have at the beginning renaMe12 = 12 :
>>> renaMe12 = 12
>>> Proposed Script ...
Result
Variable increments it's proper name at each iteration.
renaMe13 : 12
renaMe14 : 12
renaMe15 : 12
renaMe16 : 12
If you check in the shell now, you could see at the end of iteration, renaMe12 to renaMe15 no longer exist.
Only the variable renaMe16 exists with value 12.
>>> renaMe16
12
>>>> renaMe15
Retraçage (dernier appel le plus récent) :
Shell Python, prompt 4, line 1
builtins.NameError: name 'renaMe15' is not defined
Conclusion
This discussion is just for the sake of experimentation, but if I were you I would do my possible to avoid such code complexification unless it's necessary.
I agree Mozway when thinking you should avoid pain headaches...
Say that I want to take an input for variable a but then use the input in a function that will repeat but the function will change and save the input as a different value but as the same variable so I don't need the user input multiple times.
a = input("")
b = input("")
c = a + b
c = a
I save a equal to c so all the input I want is b but how would I go about repeating the function without repeatedly getting prompted for an input for a when all I want is to keep the value of a+b.
I hope I understood your question correctly.
you can do it this way:
a = "hello"
a = a + "world"
a = "helloworld"
It will work the same for you also with input():
a = a + input()
I have three similar functions in tld_list.py. I am working out of mainBase.py file.
I am trying to create a variable string which will call the appropriate function by looping through the list of all functions. My code reads from a list of function names, iterates through the list and running the function on each iteration. Each function returns 10 pieces of information from separate websites
I have tried 2 variations annotated as Option A and Option B below
# This is mainBase.py
import tld_list # I use this in conjunction with Option A
from tld_list import * # I use this with Option B
functionList = ["functionA", "functionB", "functionC"]
tldIterator = 0
while tldIterator < len(functionList):
# This will determine which function is called first
# In the first case, the function is functionA
currentFunction = str(functionList[tldIterator])
Option A
currentFunction = "tld_list." + currentFunction
websiteName = currentFunction(x, y)
print(websiteName[1]
print(websiteName[2]
...
print(websiteName[10]
Option B
websiteName = currentFunction(x, y)
print(websiteName[1]
print(websiteName[2]
...
print(websiteName[10]
Even though it is not seen, I continue to loop through the iteration by ending each loop with tldIterator += 1
Both options fail for the same reason stating TypeError: 'str' object is not callable
I am wondering what I am doing wrong, or if it is even possible to call a function in a loop with a variable
You have the function names but what you really want are the function objects bound to those names in tld_list. Since function names are attributes of the module, getattr does the job. Also, it seems like list iteration rather than keeping track of your own tldIterator index would suffice.
import tld_list
function_names = ["functionA", "functionB", "functionC"]
functions = [getattr(tld_list, name) for name in function_names]
for fctn in functions:
website_name = fctn(x,y)
You can create a dictionary to provide a name to function conversion:
def funcA(...): pass
def funcB(...): pass
def funcC(...): pass
func_find = {"Huey": funcA, "Dewey": funcB, "Louie": FuncC}
Then you can call them, e.g.
result = func_find["Huey"](...)
You should avoid this type of code. Try using if's, or references instead. But you can try:
websiteName = exec('{}(x, y)'.format(currentFunction))
I have a function in my code:
X = []
Y = [1,2,3,4]
class DATA():
def __init__(self):
X.append(Y)
DATA()
print (X)
When I run my code, I want this class (named DATA) to be implemented only when I press the Enter key. Any idea how I can do it? (A simple example is appreciated!).
This was hard to answer for a couple reasons:
You keep using the word "implement", but I'm pretty sure you mean "call" instead. I'm going to assume that here, since conditionally implementing something is rarely needed.
Your use of the class here is confusing. It isn't actually needed in this case, so it's just complicating things. I'm going to reduce it down to just:
def DATA():
X.append(Y)
Since that does the same thing as your existing code.
To ask for user input, use input. input waits until the user presses Enter, then returns the typed text. You can use it here to wait for Enter to be pressed:
x = []
y = [1,2,3,4]
def data():
x.append(y)
print("x before Enter is pressed:")
print(x)
input("Type Enter to continue...")
data() #Call DATA similar to your original code
print("x after Enter is pressed:")
print(x)
A couple extra notes:
Function and variables names should be in lower case. Uppercase is reserved for class names, and even in those cases, only the first letter is uppercase.
Ideally, you shouldn't be mutating global variables like x and y. They should be passed into the function, then the result should be returned.
So I wrote this function from a book I am reading, and this is how it starts:
def cheese_and_crackers(cheese_count, boxes_of_crackers):
print "You have %d cheeses!" % cheese_count
print "You have %d boxes of crackers!" % boxes_of_crackers
print "Man that's enough for a party!"
print "Get a blanket.\n"
ok, makes sense. and then, this is when this function is run where I got a little confused and wanted to confirm something:
print "OR, we can use variables from our script:"
amount_of_cheese = 10
amount_of_crackers = 50
cheese_and_crackers(amount_of_cheese, amount_of_crackers)
the thing that confused me here is that the amount_of_cheese and amount_of_crackers is changing the variables (verbage? not sure if i am saying the right lingo) from cheese_count and boxes_of_crackers repectively from the first inital variable labels in the function.
so my question is, when you are using a different variable from the one that is used in the initial function you wrote, why would you change the name of the AFTER you wrote out the new variable names? how would the program know what the new variables are if it is shown after it?
i thought python reads programs top to bottom, or does it do it bottom to top?
does that make sense? i'm not sure how to explain it. thank you for any help. :)
(python 2.7)
I think you are just a bit confused on the naming rules for parameter passing.
Consider:
def foo(a, b):
print a
print b
and you can call foo as follows:
x = 1
y = 2
foo(x, y)
and you'll see:
1
2
The variable names of the arguments (a, b) in the function signature (1st line of function definition) do not have to agree with the actual variable names used when you invoke the function.
Think of it as this, when you call:
foo(x, y)
It's saying: "invoke the function foo; pass x in as a, pass y in as b". Furthermore, the arguments here are passed in as copies, so if you were to modify them inside the function, it won't change the values outside of the function, from where it was invoked. Consider the following:
def bar(a, b):
a = a + 1
b = b + 2
print a
x = 0
y = 0
bar(x, y)
print x
print y
and you'll see:
1
2
0
0
The script runs from top to bottom. The function executes when you call it, not when you define it.
I'd suggest trying to understand concepts like variables and function argument passing first.
def change(variable):
print variable
var1 = 1
change(var1)
In the above example, var1 is a variable in the main thread of execution.
When you call a function like change(), the scope changes. Variables you declared outside that function cease to exist so long as you're still in the function's scope. However, if you pass it an argument, such as var1, then you can use that value inside your function, by the name you give it in the function declaration: in this case, variable. But it is entirely separate from var! The value is the same, but it is a different variable!
Your question relates to function parameter transfer.
There are two types of parameter transfer into a function:
By value ------- value changed in function domain but not global domain
By reference ------- value changed in global domain
In python, non-atomic types are transferred by reference; atomic types (like string, integer) is transferred by value.
For example,
Case 1:
x = 20
def foo(x):
x+=10
foo()
print x // 20, rather than 30
Case 2:
d = {}
def foo(x): x['key']=20
foo(d)
print d // {'key': 20}