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.
Related
For instance, let's say I have a variable named D with a value of 3.
D = 3
Is it possible to get the name of the variable D, with just knowing the value of it, which is 3?
with(3) # get name of variable (pseudo code of what I need to do)
Does that make sense? Is that possible?
Assume that this is a global variable, don't worry about the scope.
I tried to see if anyone else has asked this and no one else has.
Yes it is possible.
Should you do it?
Definitely not.
All variables in Python are kept in namespaces, that in easier or tougher ways, can be viewed as dictionaries (mappings, more accuratlly).
Once you get to the proper dictionary, just iterate through it and compare the values with the one you desire.
For a global variable in the current module, it is simple - for arbitrarily placed references, one can make use of the garbage collector module (gc) and retrieve all references to a given object - it can get a lot of edge-cases, but it is feasible. (in this case you need to have a reference to the instance you want to locate, not just an equivalent value that would compare equal).
Getting back to a global variable in the current module:
looking_for = 3
for name, value in globals().items():
if value == looking_for:
print(f"{value} is stored in the variable {name!r}")
again: there is no reason to do that in "real world" code except if you are writing a debugger - it can be a nice toy to learn more about the language, though.
You can use dir() without any parameters to have it return every single property and method and then iterate looking for anything that evals to 3. This just feels like a bad idea though, so I would reconsider whatever problem you encountered that led you to thinking this is a solution.
a = "foo"
b = "bar"
c = [1,2,3]
d = 3
e = {1:"a",2:"b"}
#grab a list of variables in play
all_variables = dir()
#iterate over variables
for name in all_variables:
#eval the variable to get the value
myvalue = eval(name)
if myvalue == 3:
print(f'{name} is a variable equal to 3')
At first: This is only a question about the "cleanest" way to code.
I've written a Python script/programm with several classes and functions, to store some spanish vocabulary.
At the end all comes together in the interface function, which passes on some user input. Roughly like this:
if __name__ == "__main__":
while True:
answ = raw_input("Please select an option below:\n"
"(1) New Vocab\n"
"(2) Testing Vocabs\n"
"(3) Search vocab (Edit|Delet)\n"
"(4) List all vocabs\n"
"(5) Show Boxes\n")
#...blabla
os.system("clear")
if INPUT(answ,"1"):
IF_new_vocab(book)
book.save_dic()
elif INPUT(answ,"2"):
IF_voc_query(book)
book.save_dic()
elif INPUT(answ,"3"):
book.search_vocab()
book.save_dic()
elif INPUT(answ,"4"):
print book.show_cache() #A
elif INPUT(answ,"5"):
book.update_boxes()
book.show_boxes() #B
#...blabla
Now my QUESTION is:
Should I return a string and use print as late as possible, which would be the "interface" in this case. (e.g. option A)?
Or should the output, which is in most cases a string, be printed by the method/function itself (e.g. option B)?
I know it doesn't affect the overall output at all. But I was always wondering if there is a convention or reason to prefer one option.
Definitely have the function return the string and print as late as possible!
Printing early would violate the open-closed principle. That is, in general your code should strive to be closed to modification. This ensures that if you decide, later, that you want to print the string output twice, or pass the string output to an API, or save the string output in a file, you don't have to modify the original code which puts together the string (the book.show_cache function)
In some scenarios, you may want to sometimes print the output, sometimes save it in a file, sometimes pass it to an API, and sometimes do something else. In this case, you would be happiest if your code up to that point had been open to extension, so that you can simply add different functions / interfaces / handlers to deal with the output in different ways, rather than having to rewrite variations of the show_cache function 3-4 different times to handle the different usages. This is the basis of the strategy design pattern!
You might then end up with something that looks like this:
def print_cache():
print book.show_cache()
def save_cache_to_file():
save(book.show_cache())
def search_google_for_cache():
// google.search(book.show_cache())
Which is a lot shorter than:
def print_cache():
vocab = ['hola', 'como', 'estas', 'bien', 'y', 'tu']
// more code?
print vocab
def save_cache_to_file():
vocab = ['hola', 'como', 'estas', 'bien', 'y', 'tu']
// more code?
save(book.show_cache())
def search_google_for_cache():
vocab = ['hola', 'como', 'estas', 'bien', 'y', 'tu']
// more code?
// google.search(vocab)
Plus, in the second example, if you want to add more vocab, you have to remember to do it in three different places, making your code easier to maintain!
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.
From Learn Python the Hard Way:
Python sees you mentioned mystuff and looks up that variable. It might have to look backwards to see if you created with =, look and see if it is a function argument, or maybe it's a global variable. Either way it has to find the mystuff first.
Once it finds mystuff it then hits the . (period) operator and starts
to look at variables that are a part of mystuff. Since mystuff is a
list, it knows that mystuff has a bunch of functions.
It then hits append and compares the name "append" to all the ones
that mystuff says it owns. If append is in there (it is) then it grabs
that to use. Next Python sees the ( (parenthesis) and realizes, "Oh
hey, this should be a function." At this point it calls (aka runs,
executes) the function just like normally, but instead it calls the
function with an extra argument.
That extra argument is ... mystuff! I know, weird right? But that's
how Python works so it's best to just remember it and assume that's
alright. What happens then, at the end of all this is a function call
that looks like: append(mystuff, 'hello') instead of what you read
which is mystuff.append('hello').
Where does he get "mystuff" from? And I'm still unsure about how that period operator thing works (sorry I'm new at this please bear with me), later on we get this:
ten_things = "Apples Oranges Crows Telephone Light Sugar"
print "Wait there's not 10 things in that list, let's fix that."
stuff = ten_things.split(' ')
I don't see how that string becomes a list after the last line, does the .split automatically turn it into one or what? What is the name of that period "split" or "append" thing he's doing? One of the main things screwing me up in programming is that I don't know what a lot of things are actually called. I know functions, variables, etc but some stuff like that .split just confuse me.
Help?
stuff = ten_things.split(' ') doesn't change the value of ten_things. Instead, it creates a new variable named stuff and saves the list created by ten_things.split(' ') to it. The space passed as an argument to the split method here is significant. What it is saying is that Python should take the string ten_things and split it up, using splits argument as a delimiter.
Example:
"This is a string".split(' ') == ["This", "is", "a", "string"]
or
"This|is|a|string".split('|') == ["This", "is", "a", "string"]
Regarding “Where does he get "mystuff" from?”, mystuff is an object of some kind, and there are methods or functions among the object's attribute values (or among the attribute values of its class). The dot (period) is a qualifier operator; for example, mystuff.append qualifies or identifies the relevant append function to be the one associated with object mystuff. Object methods typically have an implicit argument (often called self) as the first argument, and that argument is made equal to the object the method belongs to. In this case, that's mystuff.
As mentioned in a previous answer, split splits a string and returns a list. For more information, also see tutorialspoint regarding split:
The method split() returns a list of all the words in the string, using str as the separator (splits on all whitespace if left unspecified), optionally limiting the number of splits to num. ... Following is the syntax for split() method: str.split(str="", num=string.count(str)).
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.