how to access a variable that's inside a function [duplicate] - python

This question already has answers here:
How do I get a result (output) from a function? How can I use the result later?
(4 answers)
Closed 8 months ago.
I'm trying to do 4 steps where I ask the user for a "key character" and a string, then capitalize the string, then remove all instances of the key character from the string. Each of these steps is supposed to be its own function. However, steps 3 and 4 rely on accessing variables located in the functions from steps 1 and 2.
I've read a few threads on this such as the following...
How to access the variables declared inside functions in python
...which suggests you must "return" the variables after defining them, but I've done that (I think) and it hasn't changed anything.
def main():
get_key_character()
get_string()
sentence_capitalizer()
remove_key_character()
def get_key_character():
key_character=str(input("Please enter a SINGLE character to act as key? "))
if len(key_character)!=1:
get_key_character()
else:
return key_character
def get_string():
phrase_input=str(input("Please enter a phrase or sentence >=4 and <=500 characters: "))
if len(phrase_input) <4 or len(phrase_input)>500:
get_string()
else:
return phrase_input
def sentence_capitalizer():
import re
sentence_capitalized=(re.sub(r"(^|\?|\.|\!)\s*(\w)", lambda q: q[0].upper(), phrase_input))
return sentence_capitalized
def remove_key_character():
sentence_capitalized.replace(key_character, "")
main()
error: undefined name phrase_input in def sentence_capitalizer and undefined name key_character in def remove_key_character

What you are missing is that the returned value must be stored in another variable.
For example,
def test():
x = 1
return x
def main():
z = test()
print(z)
main()
This program will output:
1
You must pass the output of your functions as parameters to the subsequent calls of different functions. I have reworked your code to work like this.
def main():
key_character = get_key_character()
phrase_input = get_string()
sentence_capitalized = sentence_capitalizer(phrase_input)
removed = remove_key_character(key_character, sentence_capitalized)
print(removed)
def get_key_character():
key_character=""
while len(key_character) < 1:
key_character=str(input("Please enter a SINGLE character to act as key? "))
return key_character
def get_string():
phrase_input=str(input("Please enter a phrase or sentence >=4 and <=500 characters: "))
if len(phrase_input) <4 or len(phrase_input)>500:
get_string()
else:
return phrase_input
def sentence_capitalizer(phrase_input):
import re
sentence_capitalized=(re.sub(r"(^|\?|\.|\!)\s*(\w)", lambda q: q[0].upper(), phrase_input))
return sentence_capitalized
def remove_key_character(key_character, sentence_capitalized):
return sentence_capitalized.replace(key_character, "")
main()

if len(key_character)!=1:
get_key_character()
Your function does not return anything (so implicitly returns None) in this case. You want to return get_key_character() (or perhaps more usefully refactor to avoid recursion, i.e. add a while loop and exit it when you receive a valid character, rather than have the function call itself until it receives a valid character).
More generally, you should avoid global variables. Every time a function returns something useful, the calling code should assign that value to a local variable. If you need to pass that value to another function, make that function accept a parameter into another local variable of its own.

Related

How to write a code that automatically executes a function based on the user input?

I am trying to write a code that automatically executes a function based on the user input. I have my real functions in my code blocks but just to make things simple the example is simplified. The code that I wrote until now looks like this:
#Function lists
def a1():
return 'a'
def b2():
return 'b'
def c3():
return 'c'
def d4():
return 'd'
def e5():
return 'e'
def f6():
return 'f'
def g7():
return 'g'
while (cond):
try:
command=input('Enter a integer that matches the function\'s\ name')
funcname=
print(funcname)
except ValueError:
print('Wrong value. please enter an integer')
After this point, the while loop must print out a prompt asking the user to input an integer again that matches up with the functions created.
The parts that I am working on are these:
the command that matches function's name is entered based on user input.
command=input('Enter a integer that matches the function\'s\ name')
the user input integer is matched up with the function name that contains it. ex) user input=1, the function matched=a1()
funcname=
print the function results
print(funcname)
if a character is entered in to the user input instead of integers send error.
except ValueError:
print('Wrong value. please enter an integer')
The while loop condition that would create a proper loop that prints a prompt to users in order to get user inputs after former input is executed.
while (cond):
.
.
end
This is so far as I planned and wrote the code but obviously, it has a long way to go to get executed correctly.
How to make this code work?
One option is to gather the functions to be considered into a list. This list can then be searched for the matching function.
A decorator can be used to do this:
def make_func_list():
"""Return a decorator which tracks which functions it's applied to.
The decorator will have an `all` attribute to list these.
"""
functions = []
def wrapper(fn):
functions.append((fn.__name__, fn))
return fn
wrapper.all = functions
return wrapper
# Create the decorator
fl = make_func_list()
# Apply the decorator to each function to be included in the executor
#fl
def fn3(): return 3
#fl
def fn1(): return 1
#fl
def fn2(): return 2
# Can enumerate the list and solicit input based on index:
# (adjusted to be indexed from 1)
for n, (name, fn) in enumerate(fl.all):
print(f'{n + 1}: {name}')
response = int(input('Enter number: '))
name, func = fl.all[response - 1]
print(name, func())
# Or search the names instead (this one would search for any input):
response = input('Enter number: ')
for name, func in fl.all:
if response in name:
print(name, func())

How do I get around functions being called when they are used as arguments for other functions

I want to use a function as a default argument for another function that can be overridden without calling the function.
Let's use this snippet:
def split():
word = input('Whats the word?')
return [letter for letter in word]
def do_something_with_letters(letters=split())
for letter in letters:
print(letter)
If I call do_something_with_letters like this:
do_somthing_with_letters()
The program works how I would expect it to but not in the order that I expect. The end result is that split is called and user input is used to define the word which is split then passed into do_something_with_letters. Now, this is happening during the declaration of do_somthing_with_letters rather than during the function call(where split() is used as a default value).
for instance if I override the default value i.e:
do_somthing_with_letters(['a', 'b', 'c'])
The following chain of events occurs: Split Declared > do_somthing_with_letters Declared > Split Called and assigned to letters(or stored in memory) > do_somthing_with_letters called with overridden value.
The user has been needlessly prompted for input when it should have been over-written.
Again I need a function to be the default value for letters any answer should have a way of keeping that.
Now, this is happening during the declaration of
do_somthing_with_letters rather than during the function call(where
split() is used as a default value).
Because the function split() is being called when the function is declared. You can initialise letters with the function name (actually the function object) without calling it by omitting the parentheses. Then you can test if the argument can be called, e.g because it is a function, callable class etc.
def do_something_with_letters(letters=split):
if callable(letters):
letters = letters()
for letter in letters:
print(letter)
Now if you call do_something_with_letters() without arguments, letters will default to the split() function and call it to get the letters to work on. If you were to pass a string or list then it would print the elements of those objects. You could even pass in a different function to have it obtain the input.
>>> do_something_with_letters()
Whats the word?hello
h
e
l
l
o
>>> do_something_with_letters('abcd')
a
b
c
d
>>> do_something_with_letters(lambda : 'a string')
a
s
t
r
i
n
g
>>> do_something_with_letters(range(5)) # not letters at all
0
1
2
3
4
You have a counter-intuitive design, combining program steps that aren't functionally related. As a result, you're trying to warp the module design to compensate. user input and pre-processing the input are not fully linked in your program design -- so why do you insist on putting them into a module where they are linked? Decouple those steps.
Your do_something function should not have to adapt to wherever the string originates. let it simply handle its string argument.
If you somehow do have a design that requires this contortion, you have a problem: the default value must be realized at the definition of do_something.
You can leave the function itself as an argument:
def do_something(source=split):
if not isstring(source):
letters = source(argument) # You still need to supply argument
However, this is still tortuous design.
Also, I strongly recommend that you not use split as a function name, since that is already a built-in string function.
I believe this sort of problem may call for a decorator. You can define a function, such as verbose (shown below), that when used to decorate a function that returns an iterable, modifies it according to the behavior as specified in do_something_with_letters from your post.
Then by simply decorating the split function, you can achieve the desired result.
def verbose(f):
def func(s):
for ch in f(s):
print(ch)
return func
#verbose
def split(s):
return (ch for ch in s)
if __name__ == '__main__':
s = input("Enter word: ")
split(s)
Now any other function may be modified in a similar way. For example, the upper_and_split function will print all characters in s in uppercase.
#verbose
def upper_and_split(s):
return (ch for ch in s.upper())

python change global string in function

First off i am very new to coding and python. I am trying to call a global string inside of a function. Then I want to change it into an integer. Next, I want to apply some Math to the integer. Finally I want to convert that integer back to a string and send it back to the global to use in other functions.
I have accomplished most of what I needed to do, but I am having trouble sending the string back to the global. I have tried using return() but it just quits the program. Instead I want it to go to another function, while retaining the new value
Relevant code
current_gold = '10'
def town():
global current_gold
print(current_gold)
def pockets():
global current_gold
new_gold = int(current_gold) + 5
new_gold = str(new_gold)
print(new_gold.zfill(3))
input("\tPress Enter to return to town")
town()
This is not the full code. I maybe doing stuff drastically wrong though.
current_gold = '10'
def changeToInt():
global current_gold
current_gold = int(current_gold)
print(type(current_gold)) # It's a string right now
changeToInt() # Call our function
print(type(current_gold)) # It's an integer now
Or you could do it by passing a parameter to your function like so:
current_gold = '10'
def changeToInt2(aVariable):
return int(aVariable)
print(type(current_gold)) # It's a string right now
current_gold = changeToInt2(current_gold) # make current_gold the output of our function when called with current_gold as aVariable
print(type(current_gold)) # It's an int now

How to use counter variable inside the body of recursive function

Below the code for counting the no of '1' character in String.
count2=0 #global variable
def Ones(s):
no=0;
global count2 #wanted to eliminate global variable
if(count2>=len(s)):
return no
if(s[count2]=='1'):#count2 is the index of current character in String
no = no+1
count2=count2+1
return no + Ones(s)
else:
count2=count2+1
return Ones(s)
in the above code using count2 as a global variable , is there any possible way to declare and use count2 variable as a local inside the function , have tried like but no luck
def Ones(s):
count2=0 # but everytime it get reset to zero
Note: number of parameter of function should be remain only one and no any other helper function have to use.
The avoidance of explicit state variables is an important part of the recursion concept.
The method you are calling only needs the remainder of the string to find 1s in it. So instead of passing a string, and the position in the string, you can pass only the remainder of the string.
Python's powerful indexing syntax makes this very easy. Just look at it this way: Each instance of the method can take away the part it processed (in this case: one character), passing on the part it didn't process (the rest of the string).
Just like #ypnos said, if you really want to use recursion, here is the code:
def Ones(s):
if not s:
return 0
if s[0]=='1':
return 1 + Ones(s[1:])
else:
return Ones(s[1:])
Hope it helps.

google python exercises

I'm watching the instructional videos on you youtube and started doing some of the exercises at http://code.google.com/edu/languages/google-python-class but I'm puzzled by the below problem in the string1.py file.
What I can't seem to understand is, what is the "s" in both_ends(s): doing?
# B. both_ends
# Given a string s, return a string made of the first 2
# and the last 2 chars of the original string,
# so 'spring' yields 'spng'. However, if the string length
# is less than 2, return instead the empty string.
def both_ends(s):
# +++your code here+++
# LAB(begin solution)
if len(s) < 2:
return ''
first2 = s[0:2]
last2 = s[-2:]
return first2 + last2
At the bottom of strings1.py there are some functions:
def main()
print 'both_ends'
test(both_ends('spring'), 'spng')
if __name__ == '__main__':
main()
So how does the program know to substitute "spring" for (s) or is that not what it's doing? I can post the entire file if need be. It's only 140 lines.
'spring' is the literal string passed as a parameter into function both_ends(), and 's' is the formal parameter to the function. Replacing a formal parameter with an actual parameter is performed when the function is called.
The 'test()' function is just there to confirm that the function behaves as expected.
When you call a function, the values you give the function are assigned to the corresponding arguments in the function header. In code:
def my_func(a): #function header; first argument is called a.
#a is not a string, but a variable.
print a #do something with the argument
my_func(20) #calling my_func with a value of 20. 20 is assigned to a in the
#body of the function.
s is a variable that we presume to hold a string. We pass 'spring' in through as a parameter.
s in def both_ends(s) is the parameter for the input string. The length of this string is checked with the call to len(s) < 2, and various characters in the string are accessed by position with s[0:2] and s[-2:]
See http://docs.python.org/tutorial/controlflow.html#defining-functions for specifics. Also the tutorial at http://docs.python.org/tutorial/index.html is pretty good - I mostly learnt from it.
s is the parameter to the function, but you plug in real strings like hello or world into the function instead of just the letter s. Think of it like a math function: you have f(x) = x + 5. When you plug in a number, say 2, you get f(2) = 2 + 5. That's exactly what happens with the both_ends function. To make it simpler, here's some code:
def f(x):
return x + 5
f(2)
The way you plug into the function in the code here is the same way you plug a string into your original function.

Categories

Resources