Why Do Some Built-In Python Functions Only Have Pass

Why do some built-in Python functions only have pass?

PyCharm is lying to you. The source code you're looking at is a fake that PyCharm has created. PyCharm knows what functions should be there, and it can guess at their signatures using the function docstrings, but it has no idea what the function bodies should look like.

If you want to see the real source code, you can look at it in the official Github repository in Modules/mathmodule.c. A lot of the functions in there are macro-generated thin wrappers around C functions from math.h, but there's also a bunch of manually-written code to handle things like inconsistent or insufficient standard library implementations, functions with no math.h equivalent, and customization hooks like __ceil__.

Why do some of functions have pass

For user-defined functions, pass means doing nothing, but for some library functions (including third-party libraries), they usually mean that their logic is not written in pure Python code, such as NumPy and Python standard library, in order to pursue efficient operation, most functions are written in C language, and provides the corresponding Python interface.

More detailed answer

Python3 : Why there are no actual codes except some annotations, 'pass' and 'return' in the methods of some module?

An abstract class like this one, simply put, is made to be extended by another class which will then implement these empty methods. This is like an interface in software. Python follows principles of Duck-typing, which means certain objects should be implementing methods with specific names, arguments and return types (the method signature), as well as specific properties. So, this abstract class helps maintain these principles.

The module is likely expecting you to extend this class, fill in the methods, and then another object or function in the module used later can expect to make calls on one or more of these three specific methods on your custom button object. This is Duck-typing.

EDIT: This would be true if it were an abstract base class, but instead it's just a noisy class stub auto-generated by PyCharm.

Why do I only need the name of the module in front of module functions sometimes in python?

You've omitted some things here that make it difficult to see the reason.

First, let's start by using the built-in dir function to see what we actually get when import pandas:

import pandas as pd

print(dir(pd))

#['BooleanDtype', 'Categorical', 'CategoricalDtype', 'CategoricalIndex',
# 'DataFrame', 'DateOffset', 'DatetimeIndex', 'DatetimeTZDtype', 'ExcelFile',
# 'ExcelWriter', 'Flags', 'Float32Dtype', 'Float64Dtype', 'Float64Index',
# 'Grouper', 'HDFStore', 'Index', 'IndexSlice', 'Int16Dtype', 'Int32Dtype',
# 'Int64Dtype', 'Int64Index', 'Int8Dtype', 'Interval', 'IntervalDtype',
# 'IntervalIndex', 'MultiIndex', 'NA', 'NaT', 'NamedAgg', 'Period', 'PeriodDtype',
# 'PeriodIndex', 'RangeIndex', 'Series', 'SparseDtype', 'StringDtype', 'Timedelta',
# 'TimedeltaIndex', 'Timestamp', 'UInt16Dtype', 'UInt32Dtype', 'UInt64Dtype',
# 'UInt64Index', 'UInt8Dtype', '__builtins__', '__cached__', '__doc__',
# '__docformat__', '__file__', '__getattr__', '__git_version__', '__loader__',
# '__name__', '__package__', '__path__', '__spec__', '__version__', '_config',
# '_hashtable', '_is_numpy_dev', '_lib', '_libs', '_np_version_under1p17',
# '_np_version_under1p18', '_testing', '_tslib', '_typing', '_version', 'api',
# 'array', 'arrays', 'bdate_range', 'compat', 'concat', 'core', 'crosstab', 'cut',
# 'date_range', 'describe_option', 'errors', 'eval', 'factorize', 'get_dummies',
# 'get_option', 'infer_freq', 'interval_range', 'io', 'isna', 'isnull',
# 'json_normalize', 'lreshape', 'melt', 'merge', 'merge_asof', 'merge_ordered',
# 'notna', 'notnull', 'offsets', 'option_context', 'options', 'pandas',
# 'period_range', 'pivot', 'pivot_table', 'plotting', 'qcut', 'read_clipboard',
# 'read_csv', 'read_excel', 'read_feather', 'read_fwf', 'read_gbq', 'read_hdf',
# 'read_html', 'read_json', 'read_orc', 'read_parquet', 'read_pickle', 'read_sas',
# 'read_spss', 'read_sql', 'read_sql_query', 'read_sql_table', 'read_stata',
# 'read_table', 'reset_option', 'set_eng_float_format', 'set_option',
# 'show_versions', 'test', 'testing', 'timedelta_range', 'to_datetime',
# 'to_numeric', 'to_pickle', 'to_timedelta', 'tseries', 'unique', 'util',
# 'value_counts', 'wide_to_long']

I want to point out two specific things that were imported DataFrame and read_csv, which you mentioned in your question.

Now, if you try to use either of these things directly (i.e without the pd prefix), the compiler will throw a NameError:

df = DataFrame(data=[1,2,3]) # NameError: name 'DataFrame' is not defined
x = read_csv("my_file.csv") # NameError: name 'read_csv' is not defined

When you directly do import pandas as pd, it keeps all the newly imported pandas functions and objects in a sort of box, which you have to refer to explicitly or else the compiler will not know what function you're referring to. This is done intentionally, since there may be namespace clashes between two modules. Take the where function for example - both numpy and pandas have a where function - if you just call where(), how will the compiler know which one you're referring to?

This can be avoided by using the * operator, like so:

import numpy as np
from pandas import *

x = np.array([1,2,3,4,5])
y = np.where((x%2==0), x, -1) # you MUST use np prefix here to refer to the numpy
# "box" of imported functions.
z = x.where(x > 1, -2) # no prefix needed, since * operator was used

Note that you can only use * on one module that you import - you must use a regular import for the rest.

The last thing I want to address is the fact that no prefix is needed when you run df.to_csv(...). This is because df is not something you imported from pandas directly - instead, you initialized df beforehand like this:

import pandas as pd

df = pd.DataFrame(data=[1,2,3])
df.to_csv(...)

No prefix is needed for your function call here because df is something you created! It is a variable whose value has been initialized to a pd.DataFrame object, which can access its internal class method to_csv when you call it. It's almost like an alias for the DataFrame object.

To illustrate this point, you could even do something silly like this:

import pandas as pd

alias_func = pd.read_csv
z = alias_func("my_file.csv")

In short, you only need to use the module prefix when you're actually calling a function imported from a module that was imported without the * operator. You do not need to put the prefix when using variables/objects you initialize to pandas functions or objects, because you have already told the compiler which module's "box" you're referring to, and your new variable just acts as an alias.

Why do some functions have underscores __ before and after the function name?

From the Python PEP 8 -- Style Guide for Python Code:

Descriptive: Naming Styles


The following special forms using leading or trailing underscores are
recognized (these can generally be combined with any case convention):

  • _single_leading_underscore: weak "internal use" indicator. E.g. from M import * does not import objects whose name starts with an underscore.

  • single_trailing_underscore_: used by convention to avoid conflicts with Python keyword, e.g.

    Tkinter.Toplevel(master, class_='ClassName')

  • __double_leading_underscore: when naming a class attribute, invokes name mangling (inside class FooBar, __boo becomes _FooBar__boo; see below).

  • __double_leading_and_trailing_underscore__: "magic" objects or attributes that live in user-controlled namespaces. E.g. __init__,
    __import__ or __file__. Never invent such names; only use them as documented.

Note that names with double leading and trailing underscores are essentially reserved for Python itself: "Never invent such names; only use them as documented".

Why are some functions omitted in `dir()` output?

Good question. Because runfile is made as a built-in, just like dir() itself.

If dir() without argument can list all available calls, it should list itself too...

Python shell will search for the name not only in local scope, but also in built-in module.

You can find both dir and runfile in dir(__builtin__).



Related Topics



Leave a reply



Submit