Bất ngờ với __builtins__

by Pymier0

Python có vài chục function có sẵn, liệt kê tại https://docs.python.org/3/library/functions.html, bật lệnh python3 lên gõ là có:

$ python3
Python 3.10.10 (main, Mar  5 2023, 22:26:53) [GCC 12.2.1 20230201] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> print(len([1,3,2]))
3

Định nghĩa 1 function rồi gọi globals để liệt kê tất cả các “tên” có thể truy cập được:

>>> def double(x):
...     return x*2
...
>>> n = 42
>>> globals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'double': <function double at 0x7f729f6065f0>, 'n': 42}
>>> help(globals)
globals()
    Return the dictionary containing the current scope's global variables.

    NOTE: Updates to this dictionary *will* affect name lookups in the current
    global scope and vice-versa.

Python interpreter interative mode có hỗ trợ “autocomplete”, gõ __ rồi bấm phím Tab, thấy:

>>> __
__annotations__   __doc__           __name__
__build_class__(  __import__(       __package__
__debug__         __loader__()      __spec__

Thấy có chút khác biệt: autocomplete không hiện __builtins__, còn globals() lại không có __debug____import__, __build_class__.

__import__

__import__(...)
    __import__(name, globals=None, locals=None, fromlist=(), level=0) -> module

    Import a module. Because this function is meant for use by the Python
    interpreter and not for general use, it is better to use
    importlib.import_module() to programmatically import a module.
    ...

Function __import__ thực hiện import khi gõ import lib.

__builtins__

__builtins__ là module builtins

>>> import builtins
>>> builtins.print(builtins.len([3,2,1]))
3
>>> help(__builtins__)
Help on built-in module builtins:

NAME
    builtins - Built-in functions, exceptions, and other objects.
    ...

nơi chứa các builtin functions như print, len, …

>>> [i for i in dir(__builtins__) if not i.startswith("__") and i.islower()]
['abs', 'aiter', 'all', 'anext', 'any', 'ascii', 'bin', 'bool', 'breakpoint', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']

Trong tài liệu viết

CPython implementation detail: Users should not touch builtins; it is strictly an implementation detail. Users wanting to override values in the builtins namespace should import the builtins module and modify its attributes appropriately.

should not không có nghĩa là cannot, thử gán cho __builtins__ một module khác:

>>> import os
>>> __builtins__ = os
>>> getcwd()
'/home/hvn'
>>> globals()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'globals' is not defined
>>> print
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'print' is not defined

các builtin function như print hay globals không còn nữa, thay vào đó là các funtion trong module os.

Bất ngờ chưa?!

Kết luận

Python vẫn luôn có những bí mật rất không muốn bật mí.

Hết.

Đăng ký ngay tại PyMI.vn để học Python tại Hà Nội TP HCM (Sài Gòn), trở thành lập trình viên #python chuyên nghiệp ngay sau khóa học.