回复内容:
本来写在 @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)找到目标然后再调用过去,而模块的绑定又是可变的,所以可以做到下面这种事情:
$ python Python 2.7 . 5 ( default , Mar 9 2014 , 22 : 15 : 05 ) [ GCC 4.2 . 1 Compatible Apple LLVM 5.0 ( clang - 500.0 . 68 )] on darwin Type "help" , "copyright" , "credits" or "license" for more information . >>> 2 ** 5 32 >>> 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 ** 5 32看到蓝色来冒充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} >>> pow 1 >>>很多人扯一大堆道理,然而对于本问题并没什么卵用。
真正原因在于,这是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。
查看更多关于在Python中,为什么pow这样的函数可以直接调用,而floor这样的函数得先导入模块?的详细内容...