print 底层 和 input 底层如何实现的?

print()

先提前说下 print() 用 sys.stdout.write() 实现后面解释…

描述

print() 方法用于打印输出,最常见的一个函数。

在 Python3.3 版增加了 flush 关键字参数。

print 在 Python3.x 是一个函数,但在 Python2.x 版本不是一个函数,只是一个关键字。

语法

以下是 print() 方法的语法:

print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
参数

objects -- 复数,表示可以一次输出多个对象。输出多个对象时,需要用 , 分隔。
sep -- 用来间隔多个对象,默认值是一个空格。
end -- 用来设定以什么结尾。默认值是换行符 \n,我们可以换成其他字符串。
file -- 要写入的文件对象。
flush -- 输出是否被缓存通常决定于 file,但如果 flush 关键字参数为 True,流会被强制刷新。

返回值

无。

接下来,我们来看他的底层 是怎么写的。

def print(self, *args, sep=' ', end='\n', file=None): # known special case of print
    """
    print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
    
    Prints the values to a stream, or to sys.stdout by default.
    Optional keyword arguments:
    file:  a file-like object (stream); defaults to the current sys.stdout.
    sep:   string inserted between values, default a space.
    end:   string appended after the last value, default a newline.
    flush: whether to forcibly flush the stream.
    """
    pass

我们可以看到这句话:Prints the values to a stream, or to sys.stdout by default.

  • 译:将值打印到流或sys中。stdout默认情况下

我们再来看 sys 中的 stdout 的底层

stdout = None # (!) forward: __stdout__, real value is "<_io.TextIOWrapper name='<stdout>' mode='w' encoding='cp1252'>"

我们可以看到 mode 代表的是 写 ‘w’,也就是 write

接着我们再看 sys.stdont都可以接受什么参数?

print(dir(sys.stdout))

hello['_CHUNK_SIZE', '__class__', '__del__', '__delattr__', '__dict__', '__dir__', '__doc__', '__enter__', '__eq__', '__exit__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__ne__', '__new__', '__next__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_checkClosed', '_checkReadable', '_checkSeekable', '_checkWritable', '_finalizing', 'buffer', 'close', 'closed', 'detach', 'encoding', 'errors', 'fileno', 'flush', 'isatty', 'line_buffering', 'mode', 'name', 'newlines', 'read', 'readable', 'readline', 'readlines', 'reconfigure', 'seek', 'seekable', 'tell', 'truncate', 'writable', 
'write' # look here
, 'write_through', 'writelines']

我们看到了 有 write方法。

  • 测试:

    import sys
     
    print('hello')
    sys.stdout.write('hello')
    print('new')
     	 
    # 结果:
    # hello
    # hellonew
    

此时 可以看到,sys.stdout.write 同样的将数据 打印出来了。

所以 print() 用 sys.stdout.write() 实现

但还是可以看到两者还是有不同的。

  • sys.stdout.write()结尾没有换行,而print()是自动换行的。另外,write()只接收字符串格式的参数。

  • print()能接收多个参数输出,write()只能接收一个参数。

还记得刚才 print底层的这句话嘛: end: string appended after the last value, default a newline.

  • 译:结束:最后一个值后面的字符串,默认是一个换行符。

既然都说到这里了,大家肯定会问 刚才的 flash参数是什么鬼?

  • flush – 输出是否被缓存通常决定于 file,但如果 flush 关键字参数为 True,流会被强制刷新。

使用 flush 参数生成一个 Loading 的效果:

import time

print("---RUNOOB EXAMPLE : Loading 效果---")

print("Loading",end = "")
for i in range(20):
    print(".",end = '',flush = True)
    time.sleep(0.5)

效果图:
在这里插入图片描述



input()

先说下 Python3中的input() 用 sys.stdin.readline() 实现。接线来解释

  • Python3.x 中 input() 函数接受一个标准输入数据,返回为 string 类型。

  • Python2.x 中 input() 相等于 eval(raw_input(prompt)) ,用来获取控制台的输入。

raw_input() 将所有输入作为字符串看待,返回字符串类型。而 input() 在对待纯数字输入时具有自己的特性,它返回所输入的数字的类型( int, float )。

注意:input()raw_input() 这两个函数均能接收 字符串 ,
但 raw_input() 直接读取控制台的输入(任何类型的输入它都可以接收)。
而对于 input() ,它希望能够读取一个合法的 python 表达式,
即你输入字符串的时候必须使用引号将它括起来,否则它会引发一个 SyntaxError 。

除非对 input() 有特别需要,否则一般情况下我们都是推荐使用 raw_input() 来与用户交互。

注意:python3 里 input() 默认接收到的是 str 类型。

函数语法

input([prompt])

参数说明:

prompt: 提示信息

我们看一下 input()底层的书写:

def input(*args, **kwargs): # real signature unknown
    """
    Read a string from standard input.  The trailing newline is stripped.
    
    The prompt string, if given, is printed to standard output without a
    trailing newline before reading input.
    
    If the user hits EOF (*nix: Ctrl-D, Windows: Ctrl-Z+Return), raise EOFError.
    On *nix systems, readline is used if available.
    """
    pass

大家看注释中的这一句 On *nix systems, readline is used if available.

  • 译:在 * nix system上 ,如果可用 则使用readline。

\*nix 就是unix 操作系统和 linux操作系统。就是说只要你的操作系统是Unix或者linux,无论哪个开发商或者版本,就是属于*nix。
这种命名方式主要是用于软件兼容性说明或者网络建站上传服务器文件时需要确认的信息。

所以 input 是 sys.readline()实现的?
no no no...

大家都知道 readline()是读一行,可是 读谁呢?

大家 在电脑中输入的东西 都是要通过键盘来输入的吧,所以
此时会有一个监听 键盘 输入的函数(方法)stdin

stdin是标准输入,一般指键盘输入到缓冲区里的东西。

# sys 支持的所有方法
print(dir(sys))

['__breakpointhook__', '__displayhook__', '__doc__', '__excepthook__', '__interactivehook__', '__loader__', '__name__', '__package__', '__spec__', '__stderr__', '__stdin__', '__stdout__', '_clear_type_cache', '_current_frames', '_debugmallocstats', '_enablelegacywindowsfsencoding', '_framework', '_getframe', '_git', '_home', '_xoptions', 'api_version', 'argv', 'base_exec_prefix', 'base_prefix', 'breakpointhook', 'builtin_module_names', 'byteorder', 'call_tracing', 'callstats', 'copyright', 'displayhook', 'dllhandle', 'dont_write_bytecode', 'exc_info', 'excepthook', 'exec_prefix', 'executable', 'exit', 'flags', 'float_info', 'float_repr_style', 'get_asyncgen_hooks', 'get_coroutine_origin_tracking_depth', 'get_coroutine_wrapper', 'getallocatedblocks', 'getcheckinterval', 'getdefaultencoding', 'getfilesystemencodeerrors', 'getfilesystemencoding', 'getprofile', 'getrecursionlimit', 'getrefcount', 'getsizeof', 'getswitchinterval', 'gettrace', 'getwindowsversion', 'hash_info', 'hexversion', 'implementation', 'int_info', 'intern', 'is_finalizing', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'set_asyncgen_hooks', 'set_coroutine_origin_tracking_depth', 'set_coroutine_wrapper', 'setcheckinterval', 'setprofile', 'setrecursionlimit', 'setswitchinterval', 'settrace', 
'stderr', 'stdin', # look here
'stdout', 'thread_info', 'version', 'version_info', 'warnoptions', 'winver']
sys.stdin 底层源码:

stdin = None # (!) real value is "<_io.TextIOWrapper name=3 mode='r' encoding='cp1252'>"

大家看到了 mode 类型是 读了吧 ‘r’,看下 sys.stdin 所支持的方法

print(dir(sys.sdtin))

['_CHUNK_SIZE', '__class__', '__del__', '__delattr__', '__dict__', '__dir__', '__doc__', '__enter__', '__eq__', '__exit__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__ne__', '__new__', '__next__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_checkClosed', '_checkReadable', '_checkSeekable', '_checkWritable', '_finalizing', 'buffer', 'close', 'closed', 'detach', 'encoding', 'errors', 'fileno', 'flush', 'isatty', 'line_buffering', 'mode', 'name', 'newlines', 
'read', 'readable', 'readline', 'readlines', # 我们在这里
'reconfigure', 'seek', 'seekable', 'tell', 'truncate', 'writable', 'write', 'write_through', 'writelines']

Python3中的 input() 用 sys.stdin.readline() 实现。

import sys
 
a = sys.stdin.readline()
print(a, len(a))
 
b = input()
print(b, len(b))
 
 
# 结果:
# hello
# hello
#  6
# hello
# hello 5
  • readline()会把结尾的换行符也算进去。

  • readline()可以给定整型参数,表示获取从当前位置开始的几位内容。当给定值小于0时,一直获取这一行结束。

import sys
 
a = sys.stdin.readline(3)
print(a, len(a))
 
# 结果:
# hello
# hel 3

readline()如果给定了整型参数结果又没有把这一行读完,那下一次readline()会从上一次结束的地方继续读,和读文件是一样的。

import sys
 
a = sys.stdin.readline(3)
print(a, len(a))
 
b = sys.stdin.readline(3)
print(b, len(b))
 
# 结果
# abcde
# abc 3
# de
#  3

input()可以接收字符串参数作为输入提示,readline()没有这个功能。

参考原址:https://blog.csdn.net/lnotime/article/details/81385646
参考原址 菜鸟教程:https://www.runoob.com/python/python-func-input.html



真的希望 CSDN 能够推出 代码缩放的功能,这些 底层源码 展示太占用屏幕空间了

发布了128 篇原创文章 · 获赞 261 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/weixin_44685869/article/details/105609007
今日推荐