Apparently, this:
def f():
pass
# maybe the function is over
pass # oh wait, it's not
f()
is valid syntax, whereas this is not:
def f():
pass
''' maybe the function is over '''
pass # oh wait, it's not
f()
That comes as a huge surprise to me. So my questions are:
Why? Why does Python not consider the first version to be a syntax error?
Is there anything in PEP8 recommending that this not be done?
Yes the first one is valid because it starts with # which defined in the language to be a comment line so it's ignored and its indentation won't end functions or start new ones.
The latter is different, it's a string evaluated but its value is never used, you could use that to achieve multi line comments but still the interpreter will try to evaluate that string as code, so the indentation of this string matter to the interpreter and it could end scopes.
for the second one writing something like
'''comment''''
is as much code to the interpreter as this
my_var = '''comment'''
But this
# comment
is ignored and is not code to the interpreter.
Related
def enumerator(fruits):
for index, fruit in enumerate(fruits):
print(f"Fruit: {fruit}, under the index: {index}.")
just_a_variable = enumerator(["apple", "banana", "lemon"]) # Im just assigning function call
# to the variable "just_a_variable"
# and boom, when I run the program the function is called. Makes no sense (it shouldn't work this way, does it?)
I assume this is happening because there is a print statement in the function but it still doesn't make sense. if I change the print statement to "return" it suddenly doesn't compile, that is what I was expecting from just using print. I'm I missing something here?
In general if you add parenthesis after a function (like one of the two examples below), it is called.
function_name(arguments)
variable = function_name(arguments)
If you just want a variable to point to a function:
variable = function
Then the following two statements will become identical:
variable(arguments)
function(arguments)
Having said so, this seems a bit useless to me. With you function defined the way it currently is, there isn't a way I know to "assign" it to a variable and pass arguments at the same time.
This does change the structure of your code, but you can perhaps use yield instead of return.
The line just_a_variable = enumerator(["apple", "banana", "lemon"]) is calling function enumerator. Technically, that is what the parenthesis after enumerator do.
Perhaps you noticed that simply running the file is running that line (and calling enumerator). As a scripting language, this is how Python works (in contrast to Java or other compiled languages).
I fell in doubt why below two code work correctly and what is the difference with or without paranthesis?
And I see some answered question about first part.
Firts part
def hello():
pass
hello# first
hello()#second
Then I compile following two examples,again it works but I get different result for second part.
Second part
df["method"].value_counts()#first
df["method"].value_counts# second
My Questions
1-)Why are the results different?
2-)After df["method] ".value_counts" Are the expressions with parentheses and expressions without parentheses different things? Like method or function.
hello is a function itself. Actually, it is a pointer to bytes (wow!) representing underlying algorithm, an essence of your function. So you don't invoke function in such a way, you reference it. For example, myFunc = hello is perfectly valid Python code and you can pass both hello directly and myFunc as arguments to other functions. Same applies to lambdas, x = lambda (): print('hi') is also valid code.
() after some function make it run, i.e. you invoke it, enforce encoded algorithm to return some result. If you don't use () to invoke your functions, nothing will ever happen, they won't run, they wont use your CPU to compute something, your program will be dead no matter how good it's code is.
Well, functions are also variables, think of them as executable variables.
def hello():
pass
hello # first
hello() # second
So basically the first version is reading the variable, and the second version is executing the variable.
When Python reads those lines it sees hello and it's like "Oh yeah, I know hello, it's a function" but that's all it's going to do.
Then it reads hello() and it's like "Oh you want me to execute it? Sure, here it goes".
If you change hello's definition to this one you'll see the difference more clearly.
def hello():
print("I am executing a function")
pass
The first version is going to say "Oh yeah, I know hello, that's a function".
The second version is going to print "I am executing a function" because of the parens.
hello is a referece to a value of type function. hello() is Python syntax for invoking a value's __call__ method, equivalent here to hello.__call__(). The parentheses are a request to actually call the function bound to the name hello.
Edit: The suggested duplicate, does not answer my question, as I am primarily concerned with the difference in Python specifically. The suggested duplicate is far broader than this question.
I have recently started to learn Python. I'm currently reading "Learn Python the Hard Way". I have some ad-hoc programming experience, but am going back to the beginning to learn everything from the ground up this time.
In the book, one of the first lessons concerns print and the author provides various instructions of its use in Python 2.7, e.g.:
print "This is fun."
I found myself wondering what print is technically called here from the programming perspective. Some research found this, PEP-3105
In which case is made to make print a function:
The print statement has long appeared on lists of dubious language
features that are to be removed in Python 3000, such as Guido's
"Python Regrets" presentation 1 . As such, the objective of this PEP
is not new, though it might become much disputed among Python
developers.
So print is a statement in Python 2.7, and a function in Python 3.
But I have been unable to find a straight-forward definition for the difference between a statement and a function. I found this also by the person who invented Python, Guido van Rossum in which he explains why it would be good to make print a function instead of a statement.
From what I have read it appears that a function is some code that takes parameters and returns a value. But isn't print doing this in python 2.7? Isn't it taking in strings and returning a concatenated string?
What is the difference between a statement and a function in Python?
A statement is a syntax construct. A function is an object. There's statements to create functions, like def:
def Spam(): pass
So statements are one of the ways to indicate to Python that you want it to create a function. Other than that, there's really not much relation between them.
A statement in Python is any chunk of code you've written. It's more a theoretical concept than a real thing. If you use the correct syntax when writing your code, your statements will get executed ("evaluated"). If you use the incorrect syntax, your code will throw an error. Most people use "statement" and "expression" interchangeably.
Probably the easiest way to see the difference between a statement and a function is to see some example statements:
5 + 3 # This statement adds two numbers and returns the result
"hello " + "world" # This statement adds to strings and returns the result
my_var # This statement returns the value of a variable named my_var
first_name = "Kevin" # This statement assigns a value to a variable.
num_found += 1 # This statement increases the value of a variable called num_found
print("hello") # This is a statement that calls the print function
class User(BaseClass): # This statement begins a class definition
for player in players: # This statement begins a for-loop
def get_most_recent(language): # This statement begins a function definition
return total_count # This statement says that a function should return a value
import os # A statement that tells Python to look for and load a module named 'os'
# This statement calls a function but all arguments must also be valid expressions.
# In this case, one argument is a function that gets evaluated
mix_two_colors(get_my_favorite_color(), '#000000')
# The following statement spans multiple lines and creates a dictionary
my_profile = {
'username': 'coolguy123'
}
Here is an example of a statement that is invalid:
first+last = 'Billy Billson'
# Throws a Syntax error. Because the plus sign is not allowed to be part of a variable name.
In Python, you tend to put each statement on their own line, except in the case of nested statements. But in other programming languages like C and Java, you could put as many statements on a single line as you wanted as long as they are separated by a colon (;).
In both Python2 and Python3, you can call
print("this is a message")
and it will print the string to standard out. This is because they both have a function defined called print that takes in a string argument and prints it.
Python2 also allowed you to make a statement to print to standard out without calling a function. The syntax of this statement was that it started with the word print and whatever came after was what got printed. In Python3 this is no longer a valid statement.
print "this is a message"
Both function and statement are words that Python understands.
Function needs parenthesis to act on anything (including nothing).
Statement does not.
Hence in Python 3 print is function not statement.
Let us take a funny case. not True and not(True) both work. But type(not) is not function hence not is statement. not(True) works only because Python takes parenthesis also for grouping. Bad design, indeed.
Another difference: (not) fails, (print) does not fail, because a statement has no value while a function has one (for the interpreter, not in the mathematical sense of the image of some antecedent).
In free-form languages, sometimes I use indentation to represent some implicit structure in my statements. In the following example, I'm just doing a sequence of prints but the indentation indicates that the first and fourth print statements are "bracketing" the two in the middle.
print("<div>")
print("hello")
print("world")
print("</div>")
Is there a way to do something similar in Python without triggering an IndentationError: unexpected indent?
So far, the best I could think is to use a vacuous if statement to introduce a new indentation level.
print("<div>")
if True:
print("hello")
print("world")
print("</div>")
I, too, remember sometimes wanting such structure. This is what comes to mind (in C code that allows this mis-indentation):
glBegin(GL_TRIANGLES);
drawVertices();
glEnd();
Note that we have a begin and an end, and from here on I'm going to assume that the same happens in your case: you want to denote the beginning and ending of something. Another situation would be opening and closing a file, or even the example in your question. Python has a specific feature for this: context managers. Python's documentation even has an example with exactly this:
(this is not recommended as a real way of generating HTML!):
from contextlib import contextmanager
#contextmanager
def tag(name):
print("<%s>" % name)
yield
print("</%s>" % name)
>>> with tag("h1"):
... print("foo")
...
<h1>
foo
</h1>
I have to mention that context managers aren't simply a way to restructure your code, they can actually act on exceptions raised from the enclosed code, and execute some code regardless of the exception (e.g. to ensure that a file is closed). With the simple examples using #contextmanager this does not happen because its default behavior is to simply re-raise the exception so no surprises happen.
Other than this, the people you work with will not be happy about the false indentation. If you insist on it, sure, if True is an option.
In general, no, indentation is significant in Python.
Some alternatives that you can use are comments and line spacing:
print("start")
print("middle1")
print("middle2")
print("end")
or
# Header
print("start")
# Middle
print("middle1")
print("middle2")
# End
print("end")
You could also consider breaking your code up into sub-functions, if it makes sense to do so.
def printMiddle():
print("middle1")
print("middle2")
print("start")
printMiddle()
print("end")
However, for the specific use-case of generating nested output (like HTML), I'd suggest using a templating library instead; writing raw HTML via string manipulation can lead to both hassle and bugs (especially when things like escaping of values is involved).
Let's say, I've got a function like this:
def myFunc():
# useful function to calculate stuff
This will produce an indentation error, unless I add pass:
def myFunc():
# useful function to calculate stuff
pass
However, if I replace a comment with docstring, no pass is necessary:
def myFunc():
"""useful function to calculate stuff"""
This seems like an odd feature as neither of these are used in the program, as far as I know. So, why does it behave like this?
A comment is outright ignored by the interpreter, so omitting a block after an indent is a syntax error. However, a docstring is a real Python object--at its most basic, a literal str. A lone expression is a valid block of code:
'This is a string. It is a valid (though pretty useless) line of Python code.'
In the case of docstrings in particular, there's also some additional functionality going on, such as being used to set the __doc__ attribute.
>>> def myFunc():
... '''MyDocString'''
...
>>> print(myFunc.__doc__)
MyDocString
Note that this also works for classes:
>>> class MyClass(object):
... '''MyClassDocString'''
...
>>> print(MyClass.__doc__)
MyClassDocString
A docstring isn't just a comment. It actually has meaning to the interpreter. In the case with a docstring, you could do myFunc.__doc__ and actually get your docstring back (In the other case with a pass, the result myFunc.__doc__ would be None).
In other words, you are actually adding some code to the function body to modify it's behavior (in some circumstances), so no pass is necessary.