# 内置函数

# 关于输入输出

# print()

print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False) -> None
  • 功能:将 value 参数的值,输出到终端。
    • 如果输入了多个 value 参数,则在它们之间加上一个 sep 值,从而拼接成一个字符串。
    • 输出 value 之后,在末尾加上一个 end 值。
    • file 参数表示,将 value 输出到哪个文件对象。默认会输出到终端 sys.stdout ,俗称为"打印到终端"。
    • flush 参数默认为 False ,表示调用 print() 函数时,不会立即输出到 file ,而是等缓冲了一定体积的字符串之后才输出。
  • 例:
    >>> print('Hello', end='\n\n')
    Hello
    
    >>> print('Hello', 'World', '!')
    Hello World !
    
  • 例:显示一个动态进度条
    >>> for i in range(101):
    ...     print('\rProgress: {:12}{}%'.format((i // 10) * '▇', i), end='', flush=True)
    ...     time.sleep(0.1)
    ...
    Progress: ▇▇▇▇▇▇▇▇▇▇  100%
    
    这里配置了 end='' ,使得每次输出之后不换行,因此可以通过 \r 回到行首,重新输出这一行内容。

# input()

input(prompt=None) -> str
  • 功能:将 prompt 输出到 stdout ,作为提示语,供用户查看。然后从 stdin 读取一行字符串(由用户键盘输入,会忽略末尾的换行符),将它作为 input() 函数的返回值。
  • 例:
    >>> a = input('Please input a number: ')
    Please input a number: 1
    >>> a
    '1'         # input() 的返回值为 str 类型
    >>> int(a)
    1
    

# 关于执行代码

# exec()

exec(src, globals=..., locals=...) -> None
  • 功能:输入一段 Python 代码,让 Python 解释器执行。

    • 可选输入 globals 参数(取值为 dict 类型),决定全局作用域有哪些标识符。默认不输入 globals 参数,会继承当前的全局作用域。
    • 可选输入 locals 参数(取值为 dict 类型),决定局部作用域有哪些标识符。默认不输入 locals 参数,会继承当前的局部作用域。
  • 例:

    >>> exec('a=0')   # 执行 exec() 函数,创建一个变量 a
    >>> a
    0
    >>> exec('print(a)', {'a':1}) # 执行 exec() 函数的同时,指定变量 a 的取值
    1
    >>> a                         # 在 exec() 函数之外,变量 a 的取值不变
    0
    >>> exec('print(a)', globals(), locals()) # 执行 exec() 函数的同时,输入当前的所有标识符,默认就会这样做
    0
    

# eval()

eval(src, globals=..., locals=...) -> object
  • 功能:输入一个 Python 表达式,让 Python 解释器执行,然后返回表达式的值。
  • 对比 exec() 与 eval() 函数:
    • exec() 用于执行一段 Python 代码,不考虑返回值。而 eval() 用于执行一个 Python 表达式,并得到其返回值。
      >>> exec('1+2')
      >>> eval('1+2')
      3
      >>> eval('[print(i) for i in range(3)]')
      0                       # 这是 print() 打印的内容
      1
      2
      [None, None, None]      # 这是 eval() 的返回值
      
    • exec() 可以执行任意类型的 Python 代码,而 eval() 只能执行 Python 表达式。
      >>> eval('print(1)')    # 可以调用函数
      1
      >>> eval('a=1')         # 不能赋值
      SyntaxError: invalid syntax
      >>> eval('import sys')  # 不能导入模块
      SyntaxError: invalid syntax
      
    • exec() 中能执行多行 Python 代码(通过分号或换行符作为分隔),而 eval() 不能。
      >>> exec('1;2')
      >>> eval('1;2')
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
        File "<string>", line 1
          1;2
          ^
      SyntaxError: invalid syntax
      

# compile()

compile(src, filename, mode) -> code
  • 功能:将 src 编译成一个 code 对象。
    • filename 参数表示,从某个文件中读取 src 。
    • mode 参数表示编译模式。
      • 如果 src 是一个 Python 模块(也就是多行 Python 代码),则应该传入 mode='exec' 。
      • 如果 src 是一个 Python 表达式(保存为 str 或 bytes 对象),则应该传入 mode='eval' 。
      • 如果 src 是单行 Python 代码(保存为 str 或 bytes 对象),则应该传入 mode='single' 。
    • code 对象可以被 exec() 或 eval() 执行。
  • 例:
    >>> compile('a=1; print(a)', '', 'exec')
    <code object <module> at 0x00000193EB6BB2F0, file "", line 1>
    >>> exec(_)
    1
    

# 关于标识符

# help()

help(name)
  • 功能:查看一个标识符的说明文档。
  • 例:
    >>> help(id)
    Help on built-in function id in module builtins:
    
    id(obj, /)
        Return the identity of an object.
    

# callable()

callable(name) -> bool
  • 功能:判断一个标识符是否可以通过 name() 的语法调用。
    • 一般情况下,只有函数名、类名可以调用。
  • 例:
    >>> callable(1)
    False
    >>> callable(int)
    True
    

# dir()

dir(...) -> list
  • 功能:查询某个作用域(也就是某个命名空间)中的所有标识符(包括变量、函数、类、模块等)。
  • 直接执行 dir() ,会返回当前作用域的所有标识符:
    >>> dir()
    ['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__']
    
    不过这会省略 Python 的内置函数、内置异常名,如果想查看这些标识符,可以执行:
    >>> import builtins
    >>> dir(builtins)
    ['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', ...]
    
  • 执行 dir(object) ,会返回指定对象的所有属性:
    >>> dir('hello')
    ['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', ...]
    

# globals()

globals() -> dict
  • 功能:查看全局作用域的所有标识符。
  • 例:
    >>> globals()
    {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>}
    

# locals()

locals() -> dict
  • 功能:查看当前作用域的所有标识符。
  • 如果在全局作用域执行 locals() ,则相当于执行 globals()
    >>> locals()
    {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>}
    
  • 如果在局部作用域执行 locals() ,则只会看到局部的标识符:
    >>> def fun1():
    ...     x = 1
    ...     print(locals())
    ...
    >>> fun1()
    {'x': 1}
    

# vars()

vars()    -> dict
vars(obj) -> dict
  • 功能:
    • 如果不输入参数,则相当于执行 locals()
      >>> vars() == locals()
      True
      
    • 如果输入一个对象,则读取该对象的 __dict__ 内置变量。
      >>> a = 1
      >>> vars(a)
      TypeError: vars() argument must have __dict__ attribute
      

# 关于类

# isinstance()

isinstance(obj, class_or_tuple) -> bool
  • 功能:判断一个对象,是否为某个 class 创建的实例。
  • 例:
    >>> isinstance(1, float)
    False
    >>> isinstance(1, (int, float)) # 可以将多个 class 放在一个 tuple 中,只要匹配其中一个 class ,就返回 True
    True
    

# issubclass()

issubclass(cls, class_or_tuple) -> bool
  • 功能:判断一个类 cls ,是否为 class_or_tuple 其中一个类,或它们的子孙类。
  • 例:
    >>> class Test(int):
    ...     pass
    ...
    >>> issubclass(Test, Test)
    True
    >>> issubclass(Test, float)
    True
    >>> issubclass(Test, (int, float))
    False
    

# 关于反射

  • 如何访问一个对象的某个成员?
    • 一般做法是,使用成员运算符 . ,执行 <object>.<meber> 形式的代码。
      • 这种做法的缺点:编写代码时,就固定了成员的名称,不能改变。
      • 例:
        >>> 'hello'.encode
        <built-in method encode of str object at 0x0000025E41188C30>
        
    • 另一种做法:根据某个成员的名称,获取这个成员的引用。名称是一个字符串,可以随时改变。
      • 这种做法称为反射(reflection)。
      • 大部分编程语言都不支持反射,而 Python 支持反射,体现了它作为一种动态语言的灵活性。

# getattr()

getattr(obj, name:str, default=...) -> attribute
  • 功能:获取对象中,名为 name 的那个属性(又称为成员)。
    • 如果不存在该属性,且未传入 default 参数,则抛出异常。
    • 如果不存在该属性,且传入了 default 参数,则返回 default 值。
  • 例:
    >>> a = 'hello'           # 创建一个对象,赋值给变量 a
    >>> getattr(a, 'encode')  # 获取对象中,名为 encode 的那个属性
    <built-in method encode of str object at 0x0000025E41188C30>
    >>> _()   # 调用 encode() 方法,相当于执行 a.encode()
    b'hello'
    >>> getattr(a, 'len')
    AttributeError: 'str' object has no attribute 'len'
    

# hasattr()

hasattr(obj, name:str) -> bool
  • 功能:判断对象中,是否存在名为 name 的属性。
  • 例:
    >>> hasattr('hello', 'encode')
    True
    >>> hasattr('hello', 'len')
    False
    

# setattr()

setattr(obj, name:str, attribute) -> None
  • 功能:在对象中,给名为 name 的那个属性赋值,让它引用 attribute 。

  • 例:

    >>> class Test:
    ...     pass
    ...
    >>> t1 = Test()
    >>> setattr(t1, 'name', 't1')   # 添加一个名为 name 的属性,它的取值为 't1' 字符串,因此 t1.name 是一个变量
    >>> t1.name
    't1'
    >>> setattr(t1, 'print', print) # 添加一个名为 print 的属性,它的取值为 print 函数,因此 t1.print 是一个方法
    >>> t1.print('hello')
    hello
    
  • 如果声明了类的内置变量 __slots__ ,则只允许对指定名称的属性,进行 setattr()、delattr() 操作。

    >>> class Test:
    ...     __slots__ = ('name', 'method1')
    ...     def method2(self):
    ...         pass
    ...
    >>> t1 = Test()
    >>> setattr(t1, 'name', 't1')     # 相当于执行 t1.name = 't1'
    >>> setattr(t1, 'method1', print) # 相当于执行 t1.method1 = print
    >>> setattr(t1, 'method2', print)
    AttributeError: 'Test' object attribute 'method2' is read-only
    

# delattr()

delattr(obj, name:str) -> None
  • 功能:在对象中,删除名为 name 的那个属性。
  • 例:
    >>> delattr(str(), 'encode')
    AttributeError: 'str' object attribute 'encode' is read-only
    

# 关于迭代

# enumerate()

enumerate(iterable, start=0) -> iterable
  • 功能:输入一个可迭代对象,枚举其中的所有元素。每迭代一次,就生成一个元组 (n, iterable[n]) ,包含序号 n 和第 n 个元素。
    • start 参数表示,从哪个序号开始迭代。
    • 该函数常用于给各个元素添加序号。
  • 例:
    >>> enumerate('Hello')
    <enumerate object at 0x0000025E40DC5A40>
    >>> list(_)
    [(0, 'H'), (1, 'e'), (2, 'l'), (3, 'l'), (4, 'o')]
    

# filter()

filter(func=None, iterable) -> iterable
  • 功能:遍历 iterable 对象中的所有元素,进行过滤,保留部分元素,然后以迭代器的形式返回。
    • 输入一个函数 func 用于决定如何过滤:每迭代一个元素 x ,会调用 func(x) ,如果函数返回值为 True ,才保留该元素。
  • 例:
    >>> def is_int(x):
    ...     try:
    ...         _ = int(x)
    ...         return True
    ...     except ValueError:
    ...         return False
    ...
    >>> iterable = [1, '2', 'three']
    >>> filter(is_int, iterable)
    <filter object at 0x0000025520DDCDC0>
    >>> list(_)
    [1, '2']
    

# range()

range(start: int, stop: int, step: int=1) -> iterable
range(stop: int) -> iterable
  • 功能:生成一个等差数列。从 start 这个数开始,到 stop 这个数结束(不包含 stop 这个数),步进值为 step (即每次递增多少)。

    • 输入的这几个参数必须为 int 整型,可以为负数。
    • 可以只输入 stop 参数,此时 start 默认值为 0 。
  • 例:

    >>> range(5)          # range() 的返回值是一个可迭代对象
    range(0, 5)
    >>> list(range(5))    # 可再加一层 list() 进行迭代,展开 range() 中的各个元素
    [0, 1, 2, 3, 4]
    >>> list(range(1, 5)) # 生成一个在 [1, 5) 区间的等差数列
    [1, 2, 3, 4]
    >>> list(range(-1, -10, -2))  # 生成一个在 [-1, -10) 区间、步进值为 -2 的等差数列
    [-1, -3, -5, -7, -9]
    
  • 以下情况中,range() 生成的等差数列为空:

    >>> list(range(0))      # stop 不能小于等于 start
    []
    >>> list(range(5, 5))   # stop 不能小于等于 start
    []
    >>> list(range(1, 10, -2))  # 如果 step 为负数,则从 stop 这个数开始反向递增,此时 start 不能小于等于 stop
    []
    

# sorted()

sorted(iterable, key: callable=None, reverse=False) -> list
  • 功能:输入一个可迭代对象,遍历其中所有元素,按从小到大的顺序,放在一个 list 中返回。
    • 如何比较大小?
      • 默认是通过 item1 < item2 的方式,比较两个元素的大小。
      • 如果用户输入了 key 函数,则会通过 key(item1) < key(item2) 的方式,比较两个元素的大小。
    • 默认设置了 reverse=False ,表示从小到大,升序排列。
  • 例:
    >>> a = [0, 3, 2, 1]
    >>> sorted(a)
    [0, 1, 2, 3]
    >>> sorted(a, key=lambda x:-x)
    [3, 2, 1, 0]
    >>> sorted(a, reverse=True)
    [3, 2, 1, 0]
    
  • 默认是通过比较运算符 < 进行排序,而某些类型的对象之间,不允许比较运算。
    >>> sorted([1, 'A'])
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: '<' not supported between instances of 'str' and 'int'
    
  • 例:对字典进行排序
    >>> dic = {1:'a', 3:'c', 2:'b'}
    >>> sorted(dic.keys())  # 迭代字典中所有 key ,进行排序
    [1, 2, 3]
    >>> sorted(dic.items()) # 迭代字典中所有 item ,进行排序。此时每个 item 是二元组 (key, value) ,因此优先根据 key 的大小进行排序
    [(1, 'a'), (2, 'b'), (3, 'c')]
    >>> dict(sorted(dic.items())) # 排序之后再转换成 dict 类型
    {1: 'a', 2: 'b', 3: 'c'}
    >>> dict(sorted(dic.items(), key=lambda item: item[1])) # 提取 item[1] 也就是 value ,根据它的大小进行排序
    {1: 'a', 2: 'b', 3: 'c'}
    

# zip()

zip(*iterable) -> generator
  • 功能:
    • 该函数接收一个或多个输入参数,每个参数都是一个 iterable 可迭代对象。
    • 该函数返回一个生成器,用户每次对它进行迭代,会同时从各个 iterable 输入参数中获取一个元素,组成一个 tuple 然后返回。
      • 由于是生成器,用户每对它进行一次迭代,该函数才会对各个 iterable 进行一次迭代,不会提前遍历各个 iterable 的所有元素。
  • 例:
    >>> zip(range(3))
    <zip object at 0x000001A6FA909240>
    >>> list(_)   # 可以用 list() 来迭代,展开 zip() 的返回值
    [(0,), (1,), (2,)]
    >>> list(zip(range(3), 'hello'))  # 如果几个 iterable 的可迭代次数不同,则最短的那个 iterable 迭代完毕,就会导致 zip() 函数结束迭代。因此可能遗漏一些元素,没有迭代
    [(0, 'h'), (1, 'e'), (2, 'l')]
    >>> list(zip(*zip(range(3), 'hello'))) # 再加一层 zip(*...) 可以将矩阵恢复原来的顺序
    [(0, 1, 2), ('h', 'e', 'l')]
    
  • 使用 itertools.zip_longest() 函数,会保证将所有 iterable 迭代完毕。如果某个 iterable 提前迭代完毕,则后续的每次迭代,该 iterable 都返回 fillvalue 作为值。
    >>> import itertools
    >>> itertools.zip_longest(range(3), 'hello', fillvalue=None)
    <itertools.zip_longest object at 0x0000014CF02C1EA0>
    >>> list(_)
    [(0, 'h'), (1, 'e'), (2, 'l'), (None, 'l'), (None, 'o')]
    

# map()

map(func, *iterable) -> generator
  • 功能:map() 相当于在 zip() 的基础上,增加调用一个用户自定义的 func 函数。相当于以下代码:

    def map(func, *iterable):
        for _tuple in zip(*iterable):
            yield func(*_tuple)
    
  • 例:

    >>> map(print, range(3), 'hello')
    <map object at 0x000001A6FACBCF70>
    >>> list(_)
    0 h
    1 e
    2 l
    [None, None, None]
    
  • 例:实现矩阵的转置

    >>> list(zip([1, 2, 3, 4], [5, 6, 7]))
    [(1, 5), (2, 6), (3, 7)]
    >>> list(map(lambda x, y: (x, y), [1, 2, 3, 4], [5, 6, 7]))
    [(1, 5), (2, 6), (3, 7)]
    

# 关于运算

# all()

all(iterable) -> bool
  • 功能:输入一个可迭代对象,遍历其中所有元素,检查是否每个元素的 bool 值都为 True 。相当于以下代码:
    def all(iterable):
        for i in iterable:
            if not i:
                return False
        return True
    
  • 例:
    >>> all([0, 1, 2])
    False
    >>> all([1, 2])
    True
    >>> all([])   # 如果输入的可迭代对象为空,不包含任何元素,则结果为 True
    True
    

# any()

any(iterable) -> bool
  • 功能:输入一个可迭代对象,遍历其中所有元素,检查是否存在某一元素的 bool 值为 True 。相当于以下代码:
    def any(iterable):
        for i in iterable:
            if i:
                return True
        return False
    
  • 例:
    >>> any([0, 1, 2])
    True
    >>> any([])   # 如果输入的可迭代对象为空,不包含任何元素,则结果为 False
    False
    

# len()

len(obj) -> int
  • 功能:输入一个对象,返回该对象的长度。实际上是调用内置方法 obj.__len__()
  • 例:
    >>> len('Hello')
    5
    >>> 'Hello'.__len__()
    5
    

# abs()

abs(number) -> number
  • 功能:输入一个数字,返回它的绝对值。
  • 例:
    >>> abs(-1)
    1
    >>> abs(-1.0) # 如果输入为 float 类型,则输出也为 float 类型
    1.0
    

# round()

round(number, digits=0) -> number
  • 功能:将一个数字的小数部分,进行四舍五入,只保留指定位数。
  • 例:
    >>> round(123.456)
    123
    >>> round(123.456, 2)
    123.46
    >>> round(123.456, 5)   # 如果保留的位数,比实际小数位数多,则会返回原数字
    123.456
    >>> round(123.456, -2)  # 保留 -2 位小数,这会对整数部分进行四舍五入
    100.0
    

# max()

max(iterable, key: callable=None) -> value
max(*args, key: callable=None) -> value
  • 功能:
    • 如果只输入一个参数,则视作 iterable 可迭代对象,遍历其中所有元素,比较大小,然后返回最大的一个元素。
    • 如果输入 *args 多个参数,则比较这些参数的大小,然后返回最大值。
    • 如何比较大小?
      • 默认是通过 item1 < item2 的方式,比较两个元素的大小。
      • 如果用户输入了 key 函数,则会通过 key(item1) < key(item2) 的方式,比较两个元素的大小。
  • 例:
    >>> max([1, 2, 3])
    3
    >>> max(1, 2, 3)
    3
    
  • 例:找到字典中 value 最大的一个 key
    >>> dic = {1:'a', 3:'c', 2:'b'}
    >>> max(dic.keys(), key=dic.get)
    3
    
  • 例:找到出现次数最多的一个元素
    >>> a = [1, 2, 3, 2]
    >>> max(set(a), key=a.count)
    2
    
    • 如果想统计每个元素的出现次数,建议使用 collections.Counter

# min()

  • 功能:min() 函数的用法与 max() 相似,但是返回最小值。
  • 例:
    >>> min([1, 2, 3])
    1
    >>> min(1, 2, 3)
    1
    

# sum()

sum(iterable) -> value
  • 功能:输入一个可迭代对象,遍历其中所有元素,将它们通过运算符 + 相加,然后返回总和。
  • 例:
    >>> sum(range(5))
    10