[PYTHON] Return value of quit ()-Is there anything returned by the "function that ends everything"?

Thanks to chun and cocoatomo for their answers and reference articles in the Discord community, we have made great strides in solving and convincing. thank you very much. I would like to take this opportunity to thank you.

The beginning of the matter

When I was reading this article, I found the code that I was interested in in the comments of the article.

x = f"{quit()}"
while True:
    print("hello")

As the article comment contributor said, when I execute this code, hello is not output and it ends.

I felt a little uncomfortable here, so I looked it up.

Regarding f-string, according to the Official Document,

A formatted string literal or f-string is a string literal prefixed with'f'or'F'. These strings can contain replacement fields, which are expressions separated by curly braces {}. Formatted string literals are evaluated as expressions at run time, whereas other string literals are always constant and do not change.

And that. In other words, if you put a function inside {}, it will replace its return value with a field. Formats a string, whether the return value of the function is an int, a list, or a dict. In the end, even NoneType becomes a string " None ", and f-string is a fairly powerful white thing.

** What the quit () function that broke this powerful f-string returned **

This was my first question.

Approach 1 See type ()

First, I thought that if I knew what kind of "type" quit () returned, I could see a clue, so I executed the following code.

>>> print(type(quit()))

C:\work>

Rainy day ** The python interpreter itself has ended **

As mentioned above, if the return value is NoneType, the string " None " will be output when you put it in f-string, so I expected that the return value of quit () would not be NoneType. Instead of getting no results, the whole interpreter is dropped ...

Approach 2 See the function definition part

Even if you can't get the type, you can see what you're doing by looking at the source of the actual quit () function. I thought, and took a peek at quit in the built in.

builtin.pyi


def quit(code: object = ...) -> NoReturn: ...

** There is no return in the first place, and the mysterious No Return claims that it is not an omission or mistake **

I took it for granted that the function had a return, so I was already exhausted and decided to ask a question in the Discord community.

Approach 3 taught me

I was able to get a reply from the community. I will quote.

sys.exit (), exit (), quit () feels like throwing a SystemExit exception Reference: https://docs.python.org/3/library/constants.html

  1. Evaluate inside {}
  2. Throw an exception Conclusion: It will not be executed after the second line I think it's like I think NoReturn is typing.NoReturn Reference: https://docs.python.org/3/library/typing.html If you do not specify the return value of the function (if you do not use return), None will be the return value automatically, so it is not No Return. def function name ()-> None: pass

In other words, quit (), sys.exit (), exit (), etc. are ** functions that always give exceptions **.

Exception identity and No Return

As for the SystemExit exception that you told me, even if you execute quit () or sys.exit () normally, the exception cannot be caught and no traceback appears. This is because SystemExit exceptions are not ** Exceptions, but are directly inheriting BaseException, the main class they inherit. It seems that the exceptions that can be caught normally, KeyError and TypeError, are inherited from the Exception class, and SystemExit is not in it.

About BaseException

** BaseException is the masterpiece of all python exceptions **, and there are only four exception classes that directly inherit from it: SystemExit, GeneratorExit, KeyboardInterrupt, and Exception.

Keyboard Interrupt is a Ctrl + C thing. Exception is the base class for all other exceptions, and user-defined exceptions should also be based on it. When you write a code with a mistake, what is caught and output by Traceback is the one that inherits this Exception class, and the exception that directly inherits BaseException is not caught.

Use the traceback module to catch a BaseException. Let's catch the SystemExit exception that we expect to occur on the first line of the opening code.

import traceback
try:
    x = f"{quit()}"
    print(x)
except BaseException: #BaseException is specified just in case, but just except:But they will pick it up
    print(traceback.format_exc())

The result is as follows

python


Traceback (most recent call last):
  File "c:/work/catchBaseException.py", line 3, in <module>
    x = f"{quit()}"
  File "C:\Python\Python37\lib\_sitebuiltins.py", line 26, in __call__
    raise SystemExit(code)
SystemExit: None

** I was able to catch the System Exit of BaseException safely **

About No Return

This isn't that difficult, it's a type hint, a representation of the expected result.

Originally, it seems that the function implicitly return None when return is not specified. For example, the following code

python


def no_return():
    pass

x = no_return()
print(type(x))


<class 'NoneType'>

Far from return None, return itself is not set in the function no_return (), but the return type is NoneType. In other words, the no_return function implicitly return None. However, this is the case when the function is executed normally to the end and there is no return.

** quit () and sys.exit () that end up throwing an exception don't even implicitly return None **

The type hint of a function describes the expected value of what type the function will return, but the expected result of these functions that even None does not return is that the content of the type hint is NoReturn. It seems to be this way.

Summary

--quit (), sys.exit () raise exception SystemExit --SystemExit is a special one that directly inherits the main exception class BaseException. --A function that does not specify return implicitly return None, but it is not even done by the exception SystemExit, and the execution result does not even return None. --For functions that do not return None, write NoReturn in the type hint.

Reference link

Official documentation https://docs.python.org/ja/3/library/constants.html https://docs.python.org/ja/3/library/exceptions.html#SystemExit https://docs.python.org/ja/3/library/typing.html#typing.NoReturn Qiita https://qiita.com/ksato9700/items/44caf7bf0329fb987499 https://qiita.com/hayata-yamamoto/items/259238dad038b5bee51c Pythonjp Official Discord https://www.python.jp/pages/pythonjp_discord.html

Recommended Posts

Return value of quit ()-Is there anything returned by the "function that ends everything"?
The story that the return value of tape.gradient () was None
About the return value of pthread_mutex_init ()
About the return value of the histogram.
Find the minimum value of a function by particle swarm optimization (PSO)
[Python] Summary of functions that return the index that takes the closest value in the array
Watch out for the return value of __len__
The value of pyTorch torch.var () is not distributed
The return value (generator) of a function that combines finally and yield must not be passed directly to next
Search by the value of the instance in the list
[Python of Hikari-] Chapter 06-02 Function (argument and return value 1)
Around the place where the value of Errbot is stored
# Function that returns the character code of a string
The copy method of pandas.DataFrame is deep copy by default
[Linux] [C / C ++] How to get the return address value of a function and the function name of the caller
The value of meta when specifying a function with no return value in Dask dataframe apply
The return value of len or unichr may change depending on whether it is UCS-2 or UCS-4.