I'm struggling to concatenate a string to a function - python

This is my code. Solution #1:
def age():
input('Age: ')
def friends():
print("John" + age)
Expected outcome:
John13
Actual outcome #1:
TypeError: can only concatenate str (not "function") to str
Solution #2:
def age():
input('Age: ')
def friend():
print("John" + age())
Solution outcome #2:
TypeError: can only concatenate str (not "NoneType") to str
How can I concatenate my function age (age is an input() function declaration) to a string or strings? The age function is an input() and I want to add it to the appropriate name or string.

You need to add a return statement to your function age, for example:
def age():
agein = input(...)
return agein

age() doesn't do anything with the input, it just throws it away immediately. You need to actually return the value.
Also, there's little point in creating a method that does nothing but call another method. Why not just call input(...) "directly"?
Also, your first solution does not concatenate the string returned by age - without the (), you try to append the age() method itself to the string, which doesn't make sense.

As you know, the variable age as you've defined it is a function, not a string.
So your question boils down to:
How can we extract the actual data we want -- in this case, a string representing an age -- from
our function?
In other words,
How can we make our function "return" the data we want?
Simple! There is a construct in Python (and just about every other programming language) that does exactly this!
It is called a return statement. It "returns" a value -- any value you want -- from a function, which simply means that your code outside the function may use that value.
For example:
def age():
age = input('Age: ')
return age // We can now use this value outside the function!
You can use it like so:
def friends():
johns_age = age() // calling the age function and assigning its returned value
print("John is " + johns_age)
If you found this answer helpful, I suggest you read a beginner-friendly Python book (such as the free Automate the Boring Stuff with Python), as you'll learn much faster that way than asking questions on this rather strict and unfriendly site.

Related

How to write multiple conditions in one line

Is there a way that we can add multiple conditions in a single line? this is not working atm, but if it were separated into different sequences, it would work.
Just to mention, I used and/or and still not working
user_input = remove_punct(user_input), remove_spaces(user_input), user_input.lower
return user_input
Just nest all the operations! Your approach doesn't work as a tuple is being created on the right hand side and the value of user_input doesn't get updated.
Try this
user_input = remove_punct(remove_spaces(user_input.lower()))
Edit:
As pointed out by #S3DEV, the above solution assumes that the functions remove_punct, remove_spaces return the updated value of the input after performing the operation
You could create a list of your functions you want to use, and then iterate over them storing the result back into the input string. Alternativly if your functions are just using string methods then you can just keep chaining them. Lastly if you want to chain them like in string but need your own methods you could write your own class.
def remove_space(some_string: str):
return some_string.strip()
def remove_punct(some_string: str):
return some_string.replace("!", "")
def clean(some_string):
functions = remove_space, remove_punct, str.lower
for fun in functions:
some_string = fun(some_string)
return some_string
def clean2(some_string: str):
return some_string.strip().replace("!", "").lower()
print(clean(" hello world! "))
print(clean2(" hello world! "))

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())

Handling function param that can str or list in Python

I'm not an experienced Python programmer but I feel my solution to this problem isn't right, I think there is a better way to deal with this problem in Python.
In this case, this is using Hug API but that's probably mostly irrelevant.
Let's say the code is like this:
#hug.get_post('/hello')
def hello (name)
print(type(name))
return name
When a request is sent with one instance of the name parameter, the hello function gets a str - as in:
POST /hello?name=Bob
But if the request is sent multiple name parameters, the method receives a list of strings, as in
POST /hello?name=Bob&name=Sally
If I write the method like the following:
#hug.get_post('/hello')
def hello (name: list)
print(type(name))
return name
Then the single parameter becomes a list of characters. I.e. ['B', 'o', 'b']. But this works fine if there is multiple instances of the name parameter (e.g. ['Bob', 'Sally'] )
So the way I solved it right now is by adding this code:
#hug.get_post('/hello')
def hello (name)
names=list()
if type(name) != 'list'
names.append(name)
else:
names=name
return names
This works, but feels wrong. I think there is a better way to do this but I can't figure it out at the moment.
Hug provides a type for that: hug.types.multiple
import hug
from hug.types import multiple
#hug.get()
def hello(name: multiple):
print(type(name))
return name
Now /hello?name=Bob returns ['Bob'] and /hello?name=Bob&name=Sally returns ['Bob', 'Sally'].
If you want to validate the inner elements, you can create a customized type like this:
import hug
from hug.types import Multiple, number
numbers = Multiple[number]()
#hug.get()
def hello(n: numbers):
print(type(n))
return n
In this case /hello?n=1&n=2 returns [1, 2] and /hello?n=1&n=a results in an error:
{"errors": {"n": "Invalid whole number provided"}}
If you want to be more concise you could use the ternary operator like so:
#hug.get_post('/hello')
def hello (name)
return name if isinstance(name, list) else [name]
I'm not sure you can do it in a much more elegant matter.
isinstance() is a very common way of checking types.
Below code can handle tuples, lists or strings
#hug.get_post('/hello')
def hello (name):
if isinstance(name, (list, tuple)):
names = name
else:
names = [name]
return names

How can I tell my function to do something specific thing when it receives no parameters?

So, I have the following function which should resemble the already implemented " print " function in Python. ( I know it is silly to make a function that only uses a pre-defined function but I am practicing with different things ) The thing that I want to do with my function is: make it act the same as the pre-defined one. That is, when the print function is called with no parameters, I would like it to print an empty line just as " print() " does. How do i do that ?
def print_str( string, how_many_times, tail ):
print ( string * how_many_times, end = tail )
print doesn't take a single string, it takes 0 or most strings as argument. end has a reasonable default. You can imagine a (simplified) definition of
def print(*args, end='\n'):
...
You need to do the same for yours. A reasonable default for how_many_times would be 1. If you don't want print_str to take multiple arguments, "" would be a reasonable default for string.
def print_str(string="", how_many_times=1, tail='\n'):
print(string * how_many_times, end=tail)
You can do something like this:
def myfunc(a=None):
if a == None:
print()
else:
print("hi")
If no arguments are presented it prints nothing, but if an argument is given it prints 'hi'.

How to create a list containing names of functions?

I am completely new to python and programming but I am trying to learn it using more practical approach.
What I am trying to do is an exercise for converting different units, e.g. pounds -> kilograms, foot -> meter etc.
I have defined all the functions for different unit pairs:
def kg_to_g(value):
return round(value*1000.0,2)
def g_to_kg(value):
return round(value/1000.0,2)
def inch_to_cm(value):
return round(value*2.54,2)
def cm_to_inch(value):
return round(value/2.54,2)
def ft_to_cm(value):
return round(value*30.48,2)
etc.
and created a list with names of these functions:
unit_list = ['kg_to_g','g_to_kg','inch_to_cm','cm_to_inch',
'ft_to_cm','cm_to_ft','yard_to_m','m_to_yard',
'mile_to_km','km_to_mile','oz_to_g','g_to_oz',
'pound_to_kg','kg_to_pound','stone_to_kg','kg_to_stone',
'pint_to_l','l_to_pint','quart_to_l','l_to_quart',
'gal_to_l','l_to_gal','bar_to_l','l_to_bar']
The program should randomly choose a unit pair(e.g. kg->pounds) and value (e.g. 134.23), and the user will be asked to convert those values.
random_unit = random.choice(unit_list)
lower = 0.1001
upper = 2000.1001
range_width = upper - lower
ranval = round(random.random() * range_width + lower, 2)
When user enters answer, the program should compare answer with the calculations defined by function and tell user if it is a correct answer or wrong answer:
def input_handler(answer):
if answer == random_unit(ranval):
label2.set_text("Correct!")
else:
label2.set_text("Wrong!")
Unfortunately, that way program doesn't work, and codesculptor(codesculptor.org) returns with an error
TypeError: 'str' object is not callable
Could someone please explain to me what is wrong with the code and suggest something to solve the problem.
Because you've enclosed the function names (in the list) in quotes, they have become strings.
Change your list to:
unit_list = [kg_to_g, g_to_kg, inch_to_cm, cm_to_inch,
ft_to_cm, cm_to_ft, yard_to_m, m_to_yard,
mile_to_km, km_to_mile, oz_to_g, g_to_oz,
pound_to_kg, kg_to_pound, stone_to_kg, kg_to_stone,
pint_to_l, l_to_pint, quart_to_l, l_to_quart,
gal_to_l, l_to_gal, bar_to_l, l_to_bar]
And now it is a list of functions, which can be called like this: unit_list[0](34), for example.
So now random_unit(ranval) should not throw an exception.
Note also that comparing floats (if answer == random_unit(ranval)) will most likely cause you problems. See Is floating point math broken? for some detailed explanations of why this is.
As you are rounding you may get away with it, but it's good to be aware of this and understand that you need to deal with it in your code.
I think this is what you are asking about. You should be able to store the functions in a list like this
unit_list = [kg_to_g, g_to_kg, inch_to_cm, cm_to_inch, ft_to_cm]
You can then call each item in the list and give it a parameter and it should execute the function for example like this:
unit_list[0](value)

Categories

Resources