Why don't functions take a `self` argument? - python

I am very new to programming in Python and I just had a question as to why when I call a function it doesn't work. I see the TypeError about die_roll needing two arguments but why isn't that covered by self.result when added to the parenthesis?
import random
def die_roll(self, result):
self.result = random.randint(1, 10)
print "Roll the dice, Dennis. "
print "You have rolled a %s!" % self.result
print ("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
print (" Welcome... ")
print (" TO THE WORST GAME IN THE WORLD!!!!!!!!!!! ")
print (" REALLY, IT IS QUITE BAD. YOU'LL SEE...... ")
print ("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n")
name = raw_input('Welcome to this awful adventure. Please enter your name to get started: \n')
print "\n%s? I don't like that name. \n" % (name)
name1 = raw_input('Try again: \n')
print "\n%s?! Really? That's the best you can do? You know what - just forget it. You will be called Dennis. \n" % (name1)
print "I happen to like Dennis. It's a good name. Regal. It's nice to meet you.... Dennis. \n"
print "You begin your adventure peering into a long, gloomy cave. You move by rolling a 10-sided dice.\n"
print "You will encounter random enemies along the way. If your combined rolls equal 100, you win!\n"
die_roll()

You are defining your function as
def die_roll(self, result):
This tells python interpreter that die_roll , needs two arguments self and result.
I am guessing you copied this method from within some other class, because self is the normal naming convention for the first parameter to a method in a class, in the later case, self (first parameter) refers to 'this' (from c++ or java) .
From the function body, it seems like you do not need any parameters, maybe you can try -
def die_roll():
result = random.randint(1, 10)
print "Roll the dice, Dennis. "
print "You have rolled a %s!" % result

Hmm. I'm not sure where your main misunderstanding is, but there are several in your question.
You're not following the flow of the program and where the error comes from:
def die_roll(self, result):
/stuff here/
/stuff/
print "You will encounter random enemies along the way. If your combined rolls equal 100, you win!\n"
die_roll() <--- here is where the TypeError about die_roll needing two arguments is triggered
why isn't that covered by self.result when added to the parenthesis?, you ask? Because the error is saying that the parentheses when you call die_roll() aren't following the pattern you set when you made def die_roll(...). You can't avoid that error by doing something at the place where the function is defined. They always need to match in both places - all places. If def die_roll says it needs two parameters, then when you call it you need to give it two parameters.
Another misunderstanding is that you are using def die_roll(self, result) and then self.result - as if the comma and the dot operators are somehow related, or that you need to use these arguments as a way to get or return a result. (They aren't, you don't).
Another is that you are using the words self and result as if Python understands them. They aren't keywords, they have no special meaning in Python.
self has no special meaning in Python, however, it is the standard name people give for one particular variable which is ... unfortunately related to object orientation, something else that can be quite a slippery concept to pickup from scratch.
Your title question Why don't functions need a self argument? can be answered in many ways, all basically unhelpful to you right now. blah blah Classes define objects, they contain things which look exactly like functions but are called methods. Methods need a way to reference the object they are 'in', so the first argument to a method is always the object it is in, and the Python engine supplies the first argument so method calls always look like they don't match up because the definition has one more argument than the call. self is a convention that Python programmers have adopted for naming the variable that receives the object reference, although it's not a special name inherently. But that's all unrelated background, setting up...
Functions don't need self because they aren't 'in' objects, so they have no need for a way to reference the object they are 'in', because they aren't in one.
Yeah that's not very helpful, sorry. The most helpful thing I can say is, write more code, use the interactive interpreter more, explore more, and things will become much clearer.

Related

Python, Explain Return Within a Function, (Amateur Programmer)

I am an amateur Python coder learning in school. We recently went over functions and did some work at home. I am confused on the point/meaning of the return statement. Our goal was to simply turn a letter into its ASCII counter part using ord(). My code works as intended however what is the use of the return statement, and how can it be used in this situation to take this function further?
Letter = input("What is your letter? ")
def ordfunction ( x ):
x=ord(x)
print(x)
return[x]
ordfunction(Letter) x
Whenever we write a function it perform some task, on basis of execution it provide some result. Now we have lot of options to use this result.
One we can print/display that result on console. for which we use print to show o/p. Here is use:-
Letter = input("What is your letter? ")
def ordfunction ( x ):
x=ord(x)
print(x)
ordfunction(Letter)
So it will display output on console apart from this it dosn't perform any things. We can use this output to store in a file or send on any device.
Further other way is to use return to provide result of function. Here we can hold this value to use further in any kind of calculation like:-
Letter = input("What is your letter? ")
def ordfunction ( x ):
x=ord(x)
return x
a = ordfunction(Letter)
print (a+100)
So return with provide use result of execution to use it further throughout program.
Further you can refer:-
Why would you use the return statement in Python?
There are basically two things that a method/function can do: change some kind of state or give the caller some kind of information.
For example, if you write something to the console, you've changed something about the system state. This is sometimes called a side effect.
The second thing a method can do is give its caller some kind of information. return is a way to pass data back to the caller - it's the "result" of the method. (In many programming languages, you can also use it to exit a method immediately, but that's a different topic).
Think about a common function: 2 + 3. Most people aren't used to thinking of + as a function, but it is. (If it helps, you can think of this as plus(2, 3)). In this case, the plus function "returns" five - that's the result of the operation, the information you were looking for when you "called" it to begin with.
Hopefully, this clarifies things a little bit - if not please feel free to comment and I can edit.
Quoting definition of a math function:
In mathematics, a function is a relation between a set of inputs and a
set of permissible outputs with the property that each input is
related to exactly one output.
In short, the return is the output. Think about a math function f(x) = x + 100.
x is the input
x + 100 is the implementation of the function
The return is the output of the function, which is the result of x + 100
Equivalent python function:
def f_of_x(x):
result = x + 100
return result
Return is your answer to one statement; example: is it raining? Yes, it's raining
Your answer is returned to your question.
Simple
I also had trouble understanding the difference between return and print. After you return a function you should:
print(ordfunction(Letter))
To see your function. Print is just made for humans to see what is going on. We usually don't need the print function.

Learn Python the Hard way ex25 - Want to check my understanding

total noob here confused all to hell about something in "Learn Python the Hard Way." Apologies if this has been covered; I searched and could only find posts about not getting the desired results from the code.
My question relates to the interaction of two functions in exercise 25:
def break_words(stuff):
words = stuff.split(' ')
return words
and
def sort_sentence(sentence):
words = break_words(sentence)
return sort_words(words)
So, near the end of the exercise Zed has you run this in the terminal:
>>> sorted_words = ex25.sort_sentence(sentence)
>>> sorted_words
['All', 'come', ’good’, ’things’, ’those’, ’to’, ’wait.’, ’who’]
Now I assume the argument in 'sort_sentence' comes from the following, entered in the terminal at the start of the exercise:
>>> sentence = "All good things come to those who wait."
But although we now know the above is the argument for 'sort_sentence,' 'sort_sentence' can't complete without running 'break_words', with 'sentence' again as its argument. Here's where I get confused: The argument for 'break_words' is labeled 'stuff.' Does this matter? Can 'sentence' just be passed into 'break_words' from 'sorted_words' no matter what the argument for 'break_words' is labeled?
So assuming what I assumed - that the argument label doesn't matter - 'break_words' ought to run with 'sentence' as its argument and return 'words', which is the output of the function 'stuff.split' contained therein. This is where I get really confused - what does the 'words' returned from 'break_words' have to do with the variable 'words' defined as a part of 'sort_sentence'? I simply can't figure out how these functions work together. Thank you in advance for your help!
How Python functions more or less work is the following:
def function_name(parameter_name_used_locally_within_function_name):
#do stuff with parameter_name_used_locally_within_function_name
some_new_value = parameter_name_used_locally_within_function_name
return some_new_value
Notice how the parameter is only with in the scope of the function function_name. As that variable will only be used in that function and not outside of it. When we return a variable from a function, we can assign it to another variable calling the function:
my_variable = function_name("hello")
my_variable now has "hello" as it's value since we called the function, passing in the value "hello". Notice I didn't call the function with a specify variable name? We don't care what the parameter name is, all we know is it takes one input for the function. That parameter name is only used in the function. Notice how we receive the value of some_new_value with out knowing the name of that variable when we called the function?
Let me give you a more broad example of what's going on. Functions can be thought of a task you give someone to do. Lets say the function or task is to as them to cook something for us. The chef or task needs ingredients to cook with (that's our input), and we wish to get food back (our output return). Lets say I want an omelette, I know I have to give the chef eggs to make me one, I don't care how he makes it or what he does to it as long as I get my output/omelette back. He can call the eggs what he wants, he can break the eggs how he wants he can fry it in the pan how he likes, but as long as I get my omelette, I'm happy.
Back to our programming world, the function would be something like:
def cook_me_something(ingredients):
#I don't know how the chef makes things for us nor do I care
if ingredients == "eggs":
food = "omelette"
elif ingredients == "water":
food = "boiled water"
return food
We call it like this:
my_food_to_eat = cook_me_something("eggs")
Notice I gave him "eggs" and I got some "omelette" back. I didn't say the eggs are the ingredients nor did I know what he called the food that he gave me. He just return food that contain omelettes
Now let's talk about chaining functions together.
So we got the basic down about me giving something to the chef and he giving me food back based on what I gave him. So what if we gave him something that he needs to process before cooking it with. Let's say what if he doesn't know how to grind coffee beans. But his co-chef-worker knows how too. He would pass the beans to that person to grind the coffee beans down and then cook with the return process.
def cook_me_something(ingredients):
#I don't know how the chef makes things for us nor do I care
if ingredients == "eggs":
food = "omelette"
elif ingredients == "water":
food = "boiled water"
elif ingredients == "coffee beans"
co_worker_finished_product = help_me_co_worker(ingredients)
#makes coffee with the co_worker_finished_product which would be coffee grindings
food = "coffee"
return food
#we have to define that function of the co worker helping:
help_me_co_worker(chef_passed_ingredients):
if chef_passed_ingredients == "coffee beans"
ingredients = "coffee grinding"
return ingredients
Noticed how the co worker has a local variable ingredients? it's different from what the chef has, since the chef has his own ingredients and the co worker has his own. Notice how the chef didn't care what the co worker called his ingredients or how he handle the items. Chef gave something to the co worker and expected the finished product.
That's more or less how it's work. As long as functions get's their input, they will do work and maybe give an output. We don't care what they call their variables inside their functions cause it's their own items.
So let's go back to your example:
def break_words(stuff):
words = stuff.split(' ')
return words
def sort_sentence(sentence):
words = break_words(sentence)
return sort_words(words)
>>> sentence = "All good things come to those who wait."
>>> sorted_words = ex25.sort_sentence(sentence)
>>> sorted_words
['All', 'come', ’good’, ’things’, ’those’, ’to’, ’wait.’, ’who’]
Let's see if we can break it down for you to understand.
You called sorted_words = ex25.sort_sentence(sentence) and set sorted_words to the output of the function sort_sentence() which is ['All', 'come', ’good’, ’things’, ’those’, ’to’, ’wait.’, ’who’]. You passed in the input sentence
sort_sentence(sentence) get's executed. You passed in the string is now called sentence inside the variable. Note that you could have called the function like this and it will still work:
sorted_words = ex25.sort_sentence("All good things come to those who wait.")
And the function sort_sentence() will still call that string sentence. The function basically said what ever my input is, I'm calling it sentence. You can pass me your object named sentence, which I'm going to rename it to sentence while I'm working with it.
Next on the stack is:
words = break_words(sentence)
which is now calling the function break_words with that the function sort_sentence called it's input as sentence. So if you follow the trace it's basically doing:
words = break_words("All good things come to those who wait.")
Next on the stack is:
words = stuff.split(' ')
return words
Note that the function call it's input as stuff. So it took the sort_sentence's input that sort_sentence called sentence and function break_words is now calling it stuff.
It splits the "sentence" up into words and stores it in a list and returns the list "words"
Notice how the function sort_sentence is storing the output of break_words in the variable words. Notice how the function break_words is returning a variable named words? They are the same in this case but it doesn't matter if one called it differently. sort_sentence can store the output as foo and it still work. We are talking about different scope of variables. Outside of the function break_words the variable words can be anything, and break_words would not care. But inside break_words that variable is the output of the function.
Under my house my rules? Outside of my house you can do what ever you want type of thing.
Same deal with sort_sentence return variable, and how we store what we got back from it. It doesn't matter how we store it or what we call it.
If you wanted you can rename it as:
def break_words(stuff):
break_words_words = stuff.split(' ')
return break_words_words
def sort_sentence(sentence):
words = break_words(sentence)
return sort_words(words) #not sure where this function sort_words is coming from.
#return words would work normally.
>>> sentence = "All good things come to those who wait."
>>> sorted_words = ex25.sort_sentence(sentence)
>>> sorted_words
['All', 'come', ’good’, ’things’, ’those’, ’to’, ’wait.’, ’who’]
You just have to think of local variables, and parameters as like just naming things to work with. Like our example with the chef, Chef might called the eggs, ingredients, but I called it what ever I wanted and just passed it "eggs". It's all about the scope of things, think of functions as a house, while you are in the house, you can name what ever objects you want in the house, and outside of the house those same names could be different things but inside the house, they are what you want them to be. And when you throw something out, you naming that item has nothing to do with the outside world, since the outside world will name it something else. Might name it the same thing tho...
If I just rambled too much, ask questions I will try to clear it up for you.
Edited
Coming back from lunch I thought of variable as containers, They hold the values but you don't care what other people's containers are named. You only care about yours and when someone gives you something you put it in a container and name it something you care about that will help you know what inside it. When you give away an item, you don't give the container, cause you need it to store other things..
that the argument label doesn't matter
It matters in the sense that it's used "locally" within the function definition. Basically think of it as another local variable you define in the function definition but the values of the arguments are given to the function.
Keeping this in mind, your next question is easy to answer:
what does the 'words' returned from 'break_words' have to do with the
variable 'words' defined as a part of 'sort_sentence'?
Nothing. As stated previously, words is a local variable of sort_sentence and so is basically trashed when you leave the function ("falls out of scope" is the lingo). Of course, you can use words as the name of variables elsewhere, such as in another function definition, and that's what's happening here.

Is it pointless to receive a parameter/argument and do nothing with it?

I'm learning python from a textbook. This code is for the game Tic-Tac-Toe.
The full source code for the problem:
http://pastebin.com/Tf4KQpnk
The following function confuses me:
def human_move(board, human):
""" Get human move."""
legal = legal_moves(board)
move = None
while move not in legal:
move = ask_number("Where will you move? (0 - 8): ", 0, NUM_SQUARES)
if move not in legal: print "\nThat square is already taken. Choose another.\n"
print "Fine..."
return move
I do not know why the function receives 'human' parameter. It appears to do nothing with it.
def human_move(board, human):
How would I know to send 'human' to this function if I were to write this game from scratch? Because I can't see why it is sent to this function if it isn't used or returned.
The answer: it depends. In your example it seems useless to me, but I haven't checked it in depth.
If you create a function to be used only from your code, it is in fact useless.
def calculate_money(bank_name, my_dog_name):
return Bank(bank_name).money
money = calculate_money('Deutsche bank', 'Ralph')
But if you are working with some kind of API/Contract, the callbacks you specify might accept arguments that are not needed for a certain implementation, but for some others, are necessary.
For instance, imagine that the following function is used in some kind of framework, and you want the framework to show a pop up when the operation is finished. It could look something like this:
def my_cool_callback(names, accounts, context):
# do something blablab
context.show_message('operation finished')
But what if you don't really need the context object in your callback? you have to speficy it anyway for the signature to match... You can't call it pointless because that parameter is used sometimes.
EDIT
Another situation in which it could be useful, would be to loop through a list of functions that have almost the same signature. In that case could be ok also to have extra arguments as "garbage placeholders". Let's say all your functions need 3 arguments in general, but one needs only 2.

Can someone explain some simple python concepts to me?

I've been working through "Learn Python the Hard Way" and so far it's going pretty well, but I have a couple of questions:
the_count = [1, 2, 3, 4, 5]
fruits = ['apples', 'oranges', 'pears', 'apricots']
change = [1, 'pennies', 2, 'dimes', 3, 'quarters']
# this first kind of for-loop goes through a list
for number in the_count:
print "This is count %d" % number
# same as above
for fruit in fruits:
print "A fruit of type: %s" % fruit
# also we can go through mixed lists too
# notice we have to use %r since we don't know what's in it
for i in change:
print "I got %r" % i
In these for loops, respectively, does it matter what the words "number", "fruit" and "i" are? It feels like everything in python needs to be defined but we never really "defined" number if that makes sense. I'm not exactly sure how to word this question correctly =/
No, it doesn't matter what you use for those names. You can pick any name you wish for these identifiers, as long as they are valid python identifiers.
Name them foo, bar, vladiwostok, whatever. It is a good idea to pick a name that is a little more descriptive of course, so fruit or number are great names in the context that they are used.
In any case, all of te following are equivalent:
for foo in fruits:
print "A fruit of type: %s" % foo
for bar in fruits:
print "A fruit of type: %s" % bar
for vladivostok in fruits:
print "A fruit of type: %s" % vladivostok
The actual word you use to call these variables is not important. Obviously if you called them something else, you would have to use the new name to refer to them.
ie) you couldn't have
for bla in the_count:
print "This is the count &d" %number
because you havn't defined what number is
Python is different from many other languages in the fact that it is very weakly typed.
you don't need to explicetly say anywhere what the type of a variable is.
In C/C++ an integer variable would be defined as such
int i;
i=24;
In Python, to define a variable, it is sufficient to just set it to some value. For example,
i=24
will implicitly define i to be an integer.
likewise, the line
for number in the_count:
will implicetly define number to be a variable of the same type as the_count.
However, a variable's type can change. It can switch any number of times just by assigning value of a different type to the variable.
ie.
i=12 #i is an integer
i="bla" #i has changed to a string
i=true #i has changeed to a bool
for <name> in <value>: is semantically equivalent to a loop like
__iter = iter(<value>)
while 1:
try:
<name> = __iter.next()
except StopIteration:
break
<block>
Therefore, you can put anything you want for <name> so long as it would normally fit on the left-hand side of an assignment. Normally, this is a plain identifier, but you can use attributes too:
class Namespace: pass
foo = Namespace()
for foo.bar in range(10):
print foo.bar
l = [1,2,3,4,5]
for l[0] in range(10):
print l
As other fellas said before, it does not matter because Python is smart enough and is able to understand under the hood what is the exact type of the object that is been referencing. You just have to be worried about if the name of the variable is not weird and/or meaningless :)
Also, you said these sentence:
In these for loops, respectively, does it matter what the words
"number", "fruit" and "i" are? It feels like everything in python
needs to be defined but we never really "defined" number if that makes
sense. I'm not exactly sure how to word this question correctly =/
The good point in Python is that you don't have to code anything based on types, but in objects. What I mean is that you should not work with codes like this sample:
def hello(arg):
if type(arg) is "str":
// do something
elif type(arg) is "list":
// do another thing
You must be the less restrictive possible in that way, because in Python a lot of functions implements polymorphism and they work well accepting different types as passed in parameters. This makes a lot easier to create programs, because the language is strongly typed, but a well-coded function for a specific problem could be able to work with ints, floats and strings.

Python Parameters (beginner)

I need help with parameteres. Do both of these function definitions do the exact same thing for print_twice?
def print_twice(lol):
print lol
print lol
def print_twice(michael):
print michael
print michael
If yes, then I'm guessing the word used for the parameter doesn't matter, correct?
The word we use for the parameter does matter. It is important that the word you use:
is meaningful and clearly explains what the argument is for,
does not override some variable name from the external scope.
Importance of meaningful arguments' names
The name you use for argument is important, because the names of the arguments, their default values and the function name are the things developers using your function first see, even without the need to look into function documentation (eg. by using help(your_function)). Just use IDLE to define your function and then try to use it - when writing it, the IDLE will show you possible arguments.
So please, give them meaningful names that will make using your function easier and will not require looking into the documentation.
Overriding variables from outer scopes
When it comes to the second point, just look at this example:
def show_elements(elements):
"""Shows elements of the passed argument
"""
for element in elements:
print element
which works ok, but if you replace elements with eg. list, you will override list within this specific scope:
def show_elements(list):
"""Shows elements of the passed argument
"""
for element in list:
print element
and then if you would like to use list eg. for building a list, or converting from other type into list, then you will have problems. list is a builtin and you should not override it. Similar is true also about the other variables from the scopes surrounding the function.
Historically, when Python was resolving variable names by first looking into local scope, then global and builtin scopes, skipping all nonlocal ones (eg. scope from the function in which our function was defined), enclosing scope's variables were passed that way:
def funca():
local_val1 = 'some value1'
local_val2 = 'some value2'
def funcb(local_val1=local_val1):
# local_val1 is accessible here, even though local_val2 is not
...
...
But since the above is no longer true, you will need to take surrounding scopes into account, thus using non-conflicting name is important.
Yes they do. The name of a parameter is irrelevant, although good programming practices mandate that the name should be clear and self-explanatory
That's correct, the name of the parameter doesn't matter.
yes that is correct its just a variable name ...
That is correct. The word used for the parameter in the function definition is only a name, and does not refer to anything external.
Programming is supposed to be logical. So, let's think logically. If you write "a" on a paper twice, you get "a" two times. Same with "b." So you're doing the same function with letters. But what if you reassigned a value to a, each time a went through the function. I mean, what if a was a number, then IMO the closest you could get is something like this:
def func1(a, b):
a = input("Enter a number: ")
b = input("Enter another number: ")
b *= b
a *= a
print func1(a)
print func1(a)
print func1(b)
print func1(b)
Now, when I try to compile this specific code online, I get an error but I think something like this will work for the sake of trying to do what you're doing if done correctly? It's a good experiment, and I would imagine some usage in it.

Categories