1

I feel that this is a wrong question to ask because it is simply to wide, and as per my understanding, questions should always be very concise and precise.

But I have a lingering issue on the notion of function.

I feel that my problem is as follows:

  • When a function exist, and as a specific argument, how is python going to know how and when it should pass a variable to a function? My answer / understanding so far: Python will know because you will need to call the function. So the function is written somewhere, and then, you call the function by writing its name, plus the thing that you want to pass as parameter inside of it.

  • When several functions exist, how should they be organized? Is a something defined in a function going to impact another function? Or are they more or less "self contained", and hence a function could "seemingly" refer to exactly the same thing as another function, it is ok, because it is in a sense completely "hidden" from the other function? My answer / understanding so far: Functions can be written in whichever order, it does not matter. What matters is that then, they should be called in the right order afterwards. Functions can also refer to "overlapping" things (name etc...) it is ok, because they are all independent from each other.

I am trying to test on my own things, to finally resolve my blockage in understanding functions.

I have been trying to do the following below:

  • A user gives an input (his name)
  • A function takes it and tells to the user that he is a dog
  • A function checks if the user is a dog, and writes something has a result

My first function works. But when using my second function I get this error for line 18:

TypeError: 'in <string>' requires string as left operand, not function

Here is my code:

x = input("give me your name")


def dog(value):
    print(f"you are a dog, {value}")


def Anti_dog(blabla):
    if dog in blabla:
        print("Ho my goooood, he is a dog")
    else:
        print("everything is ok, he is a cat")
        

dog(x)

Anti_dog(x)

Following the comment, I tried to edit the code.

I tried doing two things.

First changing the print of the first function with a "return", but this did nothing.

Second, changing the dog into "dog", in order not to refer to the function dog, but to the presence of the string dog. I indeed do not have the old error, but the result is absurd, because the program is telling me that this is not a dog. Why?

Here is my code:

    x = input("give me your name")
    
    
    def dog(value):
        return(f"you are a dog, {value}")
    
    
    def Anti_dog(blabla):
        if "dog" in blabla:
            print("Ho my goooood, he is a dog")
        else:
            print("everything is ok, he is a cat")
            
    
    dog(x)
    
    Anti_dog(x)

I thought this would be really really simple as an exercise to "master" function, but this seems to become not as simple as I would have wished. I updated my code based on the answer below, but still get an error.

I tried really calling the function dog in the function anti_dog, as below:

x = input("give me your name")


def dog(value):
    print(f"you are a dog, {value}")


def Anti_dog(blabla):
    if "dog" in dog(x):
        print("Ho my goooood, he is a dog")
    else:
        print("everything is ok, he is a cat")
        

dog(x)

Anti_dog(x)

My output is (with input "Luc" for "x"):

you are a dog, Luc you are a dog, Luc

Followed by the error:

TypeError: argument of type 'NoneType' is not iterable

I also deleted "dog(x)" at some point, because I felt that it may stupidily call the function twice (once as a stand alone, and a second time within "Anti_dog(x)"?), but I still have the error.

I am reading this to understand what caused the error, but I do not see how what I wrote would have caused this. I do not understand: my function returns something, and I have not set the value of my variable to "None".

After all these issues and comment here is a code that works (with the variable naming issue fixed):

x = input("give me your name: ")


def dog(value):
    return(f"you are a dog, {value}")


def anti_dog(blabla):
    if "dog" in dog(x):
        print("Ho my goooood, he is a dog")
    else:
        print("everything is ok, he is a cat")
        
anti_dog(x)
4
  • 1
    this is actually a fantastic question and probably one of the most articulate and well written questions to gain knowledge you have submitted!
    – UpAndAdam
    Commented Mar 31 at 18:52
  • Many thanks!!!! Commented Mar 31 at 19:35
  • 1
    The problem is you changed the definition of dog to print and not to return anything. If you don't return anything then you cant process the result. The error message is telling you the problem, NoneType ( what you are returning from calling dog(x)) is not iterable.
    – UpAndAdam
    Commented Apr 1 at 14:04
  • Hoalalal! It works at last!!!!!!!!! Many thanks!!!! Commented Apr 1 at 14:10

2 Answers 2

1

When you define a function you define it's name and what if any arguments it takes... there is more possible complexity to this available but lets keep things basic for you.

first example
no parameters
def foo(): this defines a function which takes no arguments, you simply call it in your code by saying foo() or possibly result = foo() if foo is designed to return a value.

second example:
two parameters

def bar(alpha, beta):
    if len(alpha) > 2:
        alpha.append(beta)

here bar is defined as a function taking in two parameters which will be internally named alpha and beta respectively, regardless of what they are called outside... modifications which mutate alpha and beta will be passed along externally, while for other operations you may have to return a value. so after this function is called whatever is passed in as the first argument (alpha) will potentially modified to have appended beta to it. if alpha does not have an append method this will raise an error/exception. but that's a whole separate can of worms. Alternatively it could return things or it could do both.

You could call this like so:

a = ['a', 'b', 'c']
b = "somestring"
result = bar(a, b)

it could even be such that b = some_other_func(...) where ... represents possible input parameters.

you also seem to be confused about variable scope even though I have explained it and given you a link to explanation else where.

now one thing you could have done that you didn't do in Anti_dog is the following:

def Anti_dog(x):
    if "dog" in dog(x):
        print("woof")
    else:
        print("meow")

in this case the function dog is called from within Anti_dog because you properly called it. it will search for the string 'dog' being in the returned result (which it would be) and then it would yield true, and print "woof".

5
  • Ok, many thanks. This is interesting and still not "natural" for me. Commented Mar 31 at 19:32
  • But when modifying the code based on your example (i.e actually calling the function dog(value), I still get an error. Commented Mar 31 at 19:34
  • 1
    I dont know what you mean by calling dog(value).. what error calling it where? specifics matter. you keep talking in vague generalities and applying our advice inconsistently. adding one thing we say but making some other odd change in the process. we cant hit a moving target.
    – UpAndAdam
    Commented Apr 2 at 22:50
  • Yes...this is true. This now solved. The issue stemmed from the fact that I added a print statement in my first function rather than a "return". I added the final code (which worked) to the answer. Commented Apr 5 at 21:45
  • I see what you mean regarding the moving target, and changing stuff. I am sorry about that!! Commented Apr 5 at 21:51
1

Your understanding is by and large correct. The key to this particular problem is what you say here

you call the function by writing its name,

This line if dog in blabla: gives this error message 'in <string>' requires string as left operand, not function because dog is the left operand and dog is a function name. Program expects a string

The program "knows" that dog is a function and "knows" that blabla is a string.

--AFTER COMMENT--

dog is a function that takes a string (we know x is a string because that is what the function input returns). dog does not return anything.

When used in Anti-dog the python interpreter gives the TypeError because it is evaluating the use of dog in the context of dog in blabla. The interpreter assumes program is using dog as a string because dog does not have the argument that the function definition requires.

NB: using dog(something) in the function would also cause a problem (error) because dog has not return value.

This program is, IMO, nothing like "A bit like f(x) =y , and then "y" used for function g, g(y). No?". It is not sending the result of one function to be used as the argument to another function. It is two distinct functions that are operating on the same argument (in this case x).

10
  • 1
    Answer edited.... Commented Mar 31 at 15:40
  • 1
    the thing is you don't capture the return of calling dog(x) anywhere, so that return value is lost. as a result like dino said, this is like you called f(x) and then called g(x) to get what you want you'd need to say y = dog(x) and then Anti_dog(y) or Anti_dog(dog(x)) for f(g(x))
    – UpAndAdam
    Commented Mar 31 at 18:58
  • 1
    your description isn't what you are doing, your current written implementation is that the second function checks is the users name contains the string "dog" in it.
    – UpAndAdam
    Commented Mar 31 at 19:00
  • 1
    this is a million times simpler than C or java, you dont have to declare types for any of your variables and theres a million other things under the hood you dont understand or have not yet covered where that comes into play. you are at the very foundations of the language, these bits tend to be common to almost every high level language. you generally have to define something before you use it, you generally have to capture return values if you wish to use them, and you generally have to provide the correct number of arguments when you call a function.
    – UpAndAdam
    Commented Mar 31 at 19:25
  • 1
    name your functions consistently no matter what standard you choose. I'd strongly suggest using lower case letters to start your function names, but having one be dog and the other Anti_dog is quite confusing and has made me almost make typos so many times trying to help you here
    – UpAndAdam
    Commented Mar 31 at 19:27

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .