在 Python 中,為什麼 pow 這樣的函數可以直接調用,而 floor 這樣的函數得先匯入模組?

來源:互聯網
上載者:User
python新手,望大神們多指教

回複內容:

本來寫在 @bhuztez 大大的回答的評論裡的。算了還是發到頂層好了。

誒這裡 @藍色 大大的回答真的誤解一些了, @bhuztez 大大的回答才是完全正解。

這個問題,要看最精闢的答案的請看 @flow memory 大大的,要深入到Python的內部機制的請看 @bhuztez 大大的,要看點具體代碼的請看 @藍色 大大修正過的答案。

Python的__builtin___模組完全是個運行時的東西, @藍色 大大引用的代碼其實是在VM初始化的時候把初始的__builtin___模組中的名字與函數指標的對應關係註冊好;然而Python的(源碼到位元組碼)編譯器是不關心這個的。
Python的pow()跟像GCC的__builtin_powi()不可以相提並論;前者的行為可以在運行時改變,而編譯器完全不把它當作特殊的東西看待;後者則是編譯器直接支援的intrinsic function。

剛初始化好的時候,__builtin__模組裡的"pow"映射到的是builtin_pow()函數,後者進一步調用PyNumber_Power()函數來實現功能;cpython/bltinmodule.c at 2.7 · python/cpython · GitHub
Python的源碼編譯器會把 ** 運算子編譯為BINARY_POWER位元組碼指令,而Python的位元組碼解譯器為BINARY_POWER的實現則是直接調用PyNumber_Power()函數(不通過符號解析__builtin__模組裡的"pow"的當前綁定)。cpython/ceval.c at 2.7 · python/cpython · GitHub

由於在Python代碼裡調用pow()實際上要先經過一次符號解析(LOAD_NAME)找到目標然後再調用過去,而模組的綁定又是可變的,所以可以做到下面這種事情:
$ pythonPython 2.7.5 (default, Mar  9 2014, 22:15:05) [GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwinType "help", "copyright", "credits" or "license" for more information.>>> 2 ** 532>>> pow(2, 5)32>>> __builtins__<module '__builtin__' (built-in)>>>> dir(__builtins__)['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BufferError', 'BytesWarning', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'NameError', 'None', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'ReferenceError', 'RuntimeError', 'RuntimeWarning', 'StandardError', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'ZeroDivisionError', '_', '__debug__', '__doc__', '__import__', '__name__', '__package__', 'abs', 'all', 'any', 'apply', 'basestring', 'bin', 'bool', 'buffer', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'cmp', 'coerce', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'execfile', 'exit', 'file', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'intern', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'long', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'raw_input', 'reduce', 'reload', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'unichr', 'unicode', 'vars', 'xrange', 'zip']>>> pow<built-in function pow>>>> mypow = pow>>> mypow<built-in function pow>>>> __builtins__.pow = lambda x, y: mypow(x, y) - 1>>> pow(2, 5)31>>> 2 ** 532
看到藍色來冒充Python專家了,特來批判一番。這裡首先是黑魔法,不然有些問題就解釋不清楚啦。

>>> __builtins__>>> pow(2,2)4>>> __builtins__ = None>>> pow(2,2)Traceback (most recent call last):  File "", line 1, in NameError: name 'pow' is not defined>>> __builtins__ = {'pow':1}>>> pow1>>>
很多人扯一大堆道理,然而對於本問題並沒什麼卵用。

真正原因在於,這是Python設計者的喜好罷了,因為設計者完全可以把floor也做成可以直接調用的嘛。pow()是built-in function,所以不需要匯入.
floor()是math module的function,需要import math(from math import floor)後才能用.
不過要注意的是math module中也有個pow(),和built-in的pow()有些不同.
可以看看官方文檔:
2. Built-in Functions
以及
9.2. math — Mathematical functions -------------------------------Update------------------
可以看 @RednaxelaFX 的解釋,我的理解有所偏差,還是放在前面吧,讓更多人看到









上面說的很清楚,pow是Builtin函數,而Builtin函數是編譯器直接支援的,可以參考這個連結瞭解Built in函數與普通函數的不同:Intrinsic function

下面我將順便展開說說Python中是如何?Builtin Pow的。首先在Python中,Built in函數定義在了Bltinmodules.c這個檔案中,具體的代碼在:

static PyMethodDef builtin_methods[]
pow 貌似比 floor 更常用 更適合作為 build-in 存在這個問題的實質就是:為什麼有的函數在__builtins__,而有的不在?除了scope原因之外,造成這樣scope的原因,還有一個可能是Pow 是int, floor可能是float。雖然python裡面並沒有什麼type。
  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.