Python笔记【十二】

本文为博主原创,未经授权,严禁转载及使用。
本文链接:https://blog.csdn.net/zyooooxie/article/details/129037817

继续学习Python,继续更新。

这是我自己学习Python的系列博客: https://blog.csdn.net/zyooooxie/category_9592654.html

个人博客:https://blog.csdn.net/zyooooxie

_call_()

https://docs.python.org/zh-cn/3.8/reference/datamodel.html#object.call

"""
@blog: https://blog.csdn.net/zyooooxie
@qq: 153132336
@email: zyooooxie@gmail.com
"""

def test_0407():
    # object.__call__(self[, args...])
    # 此方法会在 实例作为一个函数被“调用”时 被调用;
    # 如果定义了此方法,则 x(arg1, arg2, ...) 就大致可以被改写为 type(x).__call__(x, arg1, ...)。

    # 如果类中定义了__call__()方法,那么该类的实例对象也将成为可调用对象。
    # 该实例对象被调用时,就会自动触发这个方法,执行__call__()中的代码。

    pass


class TestClass(object):

    def __call__(self, *args, **kwargs):
        Log.info('TestClass __call__() 开始执行')

        Log.info(args)
        Log.info(kwargs)

        Log.info(self)
        Log.info(' __call__() 执行完')


class TestClass2(object):
    pass


if __name__ == '__main__':
    pass

    tc = TestClass()
    Log.info(tc)
    Log.info(isinstance(tc, TestClass))

    tc()
    tc('参数1')
    tc('参数1', k2='v2')

    tc2 = TestClass2()
    tc2()  # TypeError: 'TestClass2' object is not callable

callable()

https://docs.python.org/zh-cn/3.8/library/functions.html?#callable

"""
@blog: https://blog.csdn.net/zyooooxie
@qq: 153132336
@email: zyooooxie@gmail.com
"""


def test_callable():
    # callable(object)
    # 如果参数object是可调用的,就返回 True,否则返回 False。
    # 如果返回 True,调用仍可能失败,
    # 但如果返回 False,则调用 object 将肯定不会成功。

    # 请注意类是可调用的(调用类将返回一个新的实例);如果实例所属的类有 __call__() 则它就是可调用的。
    Log.info(callable(list))
    Log.info(callable(list()))  # 如果类中未设置__call()__方法的话是会返回False的


def test_callable2():
    # 一个可callable的对象是指可以被调用执行的对象,并且可以传入参数;

    # 下面列举callable对象的种类
    # 1.函数(自定义函数、Python内置函数、lambda表达式)
    # 2.类
    # 3.类的方法
    # 4.实现了__call__()的 类实例对象

    # 对于可调用对象,对象名() 等价于 对象名.__call__()
    pass


def func_0407():
    Log.info('func_0407() 在执行')


class TestClass(object):
    pass


class TestClass1(object):

    def func_0407001(self):
        Log.info('TestClass1 -- func_0407001')

        Log.info(self)


class TestClass2(object):

    def __call__(self, *args, **kwargs):
        Log.info('TestClass2 -- __call__')

        Log.info(self)


if __name__ == '__main__':
    pass

    Log.info(callable(func_0407))
    func_0407()
    func_0407.__call__()

    Log.info(callable(int))
    Log.info(int(1.2))
    Log.info(int.__call__(-11.2))

    Log.info(callable(lambda x: x * 2))
    Log.info((lambda x: x * 2)(88))
    Log.info((lambda x: x * 2).__call__(-888))

    Log.info('*')

    Log.info(callable(TestClass))
    TestClass()
    TestClass.__call__()

    Log.info(TestClass())

    Log.info('**')

    Log.info(callable(TestClass1().func_0407001))
    t = TestClass1()
    t.func_0407001()
    t.func_0407001.__call__()

    Log.info(t.func_0407001())

    Log.info('')

    res = TestClass1().func_0407001
    Log.info(callable(res))
    res()
    res.__call__()
    Log.info(res())

    Log.info('***')

    Log.info(callable(TestClass2()))
    TestClass2()()  # 像调用函数一样使用
    TestClass2().__call__()
    Log.info(TestClass2()())

    Log.info('')

    res = TestClass2()
    Log.info(callable(res))
    res()
    res.__call__()

    Log.info(res())

operator模块【1】

https://docs.python.org/zh-cn/3.8/library/operator.html

"""
@blog: https://blog.csdn.net/zyooooxie
@qq: 153132336
@email: zyooooxie@gmail.com
"""

# operator 模块提供了一套与Python 的内置运算符对应的高效率函数。
# 许多函数名与特殊方法名相同,只是没有双下划线。为了向后兼容性,也保留了许多包含双下划线的函数。
# 为了表述清楚,建议使用没有双下划线的函数。


def test_1():
    # 比较运算:eq(),ne(),lt(),le(),gt(),和ge()
    # 适用于所有的对象,函数名根据它们对应的比较运算符命名。

    # python的比较运算符有6种,对应着两个对象之间的6种大小关系:相等,不相等,大于,小于,大于等于,小于等于。

    a1 = 14.0
    a2 = 14

    b1 = '15'
    b2 = 'abc'

    # operator.lt(a, b)
    # operator.le(a, b)
    # lt(a, b) 与a < b 相同,
    # le(a, b) 与a <= b 相同
    Log.info(operator.lt(a1, a2))
    Log.info(operator.le(a1, a2))

    Log.info(operator.lt(b1, b2))
    Log.info(operator.le(b1, b2))
    Log.info('')

    # operator.eq(a, b)
    # operator.ne(a, b)
    # eq(a,b) 与a == b 相同,
    # ne(a, b) 与a != b 相同
    Log.info(operator.eq(a1, a2))
    Log.info(operator.ne(a1, a2))
    Log.info('')

    # operator.gt(a, b)
    # operator.ge(a, b)
    # gt(a, b) 与a > b 相同,
    # ge(a, b)与 a >= b 相同
    Log.info(operator.gt(a1, a2))
    Log.info(operator.ge(a1, a2))

    Log.info(operator.gt(b1, b2))
    Log.info(operator.ge(b1, b2))

    # operator.__lt__(a, b)
    # operator.__le__(a, b)
    # operator.__eq__(a, b)
    # operator.__ne__(a, b)
    # operator.__ge__(a, b)
    # operator.__gt__(a, b)

    # 比较运算会产生布尔值: True 或 False。 自定义的 富比较方法 可能返回非布尔值。
    # 比较运算可以任意串连,例如 x < y <= z 等价于 x < y and y <= z,除了 y 只被求值一次(但在两种写法下当 x < y 值为假时 z 都不会被求值)
    pass


def test_2():
    # 逻辑运算:not_(),truth(),is_(),is_not()
    # 通常也适用于所有对象,并且支持真值检测、标识检测和布尔运算

    a1 = '15'
    a2 = 15

    # operator.not_(obj)
    # operator.__not__(obj)
    # 返回not obj 的结果。(请注意对象实例并没有__not__() 方法;只有解释器核心可定义此操作。结果会受__bool__() 和__len__() 方法影响。)
    Log.info(operator.not_(a1))
    Log.info(operator.not_(a2))

    Log.info(operator.not_(True))
    Log.info(operator.not_(False))
    Log.info(operator.not_(0))
    Log.info(operator.not_(1))
    Log.info(operator.not_(None))

    Log.info('')

    # operator.truth(obj)
    # 如果obj 为真值则返回True,否则返回False。
    # 这等价于使用bool 构造器。
    Log.info(operator.truth(a1))
    Log.info(operator.truth(a2))
    Log.info(operator.truth(True))
    Log.info(operator.truth(False))
    Log.info(operator.truth(0))
    Log.info(operator.truth(1))
    Log.info(operator.truth(None))

    Log.info('')

    # operator.is_(a, b)
    # 返回a is b。检测对象标识。
    Log.info(operator.is_(a1, a2))
    Log.info(operator.is_(a1, True))
    Log.info(operator.is_(a1, 15))
    Log.info(operator.is_(a2, 15))

    Log.info('')

    # operator.is_not(a, b)
    # 返回a is not b。检测对象标识。
    Log.info(operator.is_not(a1, a2))
    Log.info(operator.is_not(a1, True))
    Log.info(operator.is_not(a1, 15))
    Log.info(operator.is_not(a2, 15))


def test_3():
    # 数学运算:abs() add() mul() neg() pos() pow() sub()

    a1 = -555
    a2 = 555
    a3 = -55.5
    a4 = 5.55

    # operator.abs(obj)
    # operator.__abs__(obj)
    # 返回obj 的绝对值。
    Log.info(operator.abs(a3))
    Log.info(operator.abs(a4))

    Log.info('')

    # operator.add(a, b)
    # operator.__add__(a, b)
    # 对于数字a 和b,返回a + b。
    Log.info(operator.add(a1, a2))
    Log.info(operator.add(a1, a3))

    Log.info('')

    # operator.mul(a, b)
    # operator.__mul__(a, b)
    # 对于数字a 和b,返回a * b。
    Log.info(operator.mul(a1, a2))
    Log.info(operator.mul(a3, a4))

    Log.info('')

    # operator.neg(obj)
    # operator.__neg__(obj)
    # 返回obj 取负的结果(-obj)。
    Log.info(operator.neg(a3))
    Log.info(operator.neg(a4))

    Log.info('')

    # operator.pos(obj)
    # operator.__pos__(obj)
    # 返回obj 取正的结果(+obj)。
    Log.info(operator.pos(a3))
    Log.info(operator.pos(a4))

    Log.info('')

    # operator.pow(a, b)
    # operator.__pow__(a, b)
    # 对于数字a 和b,返回a ** b。
    Log.info(operator.pow(a1, a4))
    Log.info(operator.pow(a2, a4))

    Log.info('')

    # operator.sub(a, b)
    # operator.__sub__(a, b)
    # 返回a - b。
    Log.info(operator.sub(a1, a2))
    Log.info(operator.sub(a3, a4))


def test_3_():
    # floordiv() mod() truediv()

    a1 = -555
    a2 = 555
    a3 = -55.5
    a4 = 5.55

    # operator.floordiv(a, b)
    # operator.__floordiv__(a, b)
    # 返回a // b。
    Log.info(operator.floordiv(a1, a2))  # 地板除
    Log.info(operator.floordiv(a3, a4))  # floordiv()函数也用于对两个数字 地板除法,并返回 最大小整数;
    Log.info(operator.floordiv(a2, a4))  # 向下取整

    Log.info(operator.floordiv(a4, a4))

    Log.info('')

    # operator.truediv(a, b)
    # operator.__truediv__(a, b)
    # 返回a / b 例如2/3 将等于.66 而不是0。这也被称为“真”除法。
    Log.info(operator.truediv(a1, a2))  # 传统的除法
    Log.info(operator.truediv(a3, a4))
    Log.info(operator.truediv(a2, a4))

    Log.info(operator.truediv(a4, a4))

    Log.info('')

    # operator.mod(a, b)
    # operator.__mod__(a, b)
    # 返回a % b。
    Log.info(operator.mod(a3, a1))
    Log.info(operator.mod(a2, a4))

    Log.info(operator.mod(a1, a4))  # 这个是取模操作,也就是取余数
    Log.info(operator.mod(abs(a1), a4))


def test_0316():
    # 将运算符映射到函数

    # 取绝对值  abs(obj)
    # 加法  a + b    add(a, b)
    # 普通除法  a / b    truediv(a, b)
    # 除法  a // b    floordiv(a, b)
    # 取幂  a ** b    pow(a, b)
    # 取模  a % b    mod(a, b)
    # 乘法  a * b    mul(a, b)
    # 减法  a - b    sub(a, b)
    # 取反(算术)   - a    neg(a)
    # 正数   + a    pos(a)

    # 真值测试  truth(obj)
    # 取反(逻辑)   not_(obj)  not_(a)
    # 标识  a is b    is_(a, b)
    # 标识  a is not b    is_not(a, b)

    # 比较  a < b    lt(a, b)
    # 比较  a <= b    le(a, b)
    # 相等  a == b    eq(a, b)
    # 不等  a != b    ne(a, b)
    # 比较  a >= b    ge(a, b)
    # 比较  a > b    gt(a, b)

    pass


open()

https://docs.python.org/zh-cn/3.7/library/functions.html#open

"""
@blog: https://blog.csdn.net/zyooooxie
@qq: 153132336
@email: zyooooxie@gmail.com
"""

def test_open():
    # open(file, mode=’r’, buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)

    # 打开file 并返回对应的file object。
    # 如果文件不存在则引发FileNotFoundError异常,如果文件存在却不能被打开,则引发OSError异常。

    # file 是一个path-like object,表示将要打开的文件的路径(绝对路径或者当前工作目录的相对路径),也可以是要被封装的整数类型文件描述符。
    # (如果是文件描述符,它会随着返回的I/O 对象关闭而关闭,除非 closefd 被设为False)

    # --------

    # mode 是一个可选字符串,用于指定打开文件的模式。
    # 默认值是'r' ,这意味着它以文本模式打开并读取。It defaults to 'r' which means open for reading in text mode.
    # 其他常见模式有:写入'w' (截断已经存在的文件);排它性创建'x' ;追加写'a';

    # 默认模式为'r' (打开用于读取文本,与'rt' 同义)。模式'w+' 与'w+b' 将打开文件并清空内容。模式'r+' 与'r+b' 将打开文件并不清空内容。

    # 可用的模式有:
    # 'r' 读取(默认)(打开文件进行读取,如果文件不存在,则发生错误)
    # 'w' 写入,并先截断文件(如果指定的文件不存在,将创建一个文件)
    # 'x' 【写入】排它性创建,(将创建一个文件,如果文件存在则返回错误)
    # 'a' 写入,如果文件存在则在末尾追加(如果指定的文件不存在,将创建一个文件)

    # 'b' 二进制模式
    # 't' 文本模式(默认)
    # '+' 打开用于更新(读取与写入)

    #     'r'       open for reading (default)
    #     'w'       open for writing, truncating the file first
    #     'x'       create a new file and open it for writing
    #     'a'       open for writing, appending to the end of the file if it exists
    #     'b'       binary mode
    #     't'       text mode (default)
    #     '+'       open a disk file for updating (reading and writing)

    # --------

    # encoding 是用于解码或编码文件的编码的名称。这应该只在文本模式下使用。

    # 在文本模式下(默认情况下,或者在*mode* 参数中包含`’t’‘ )时,文件内容返回为str ,首先使用指定的encoding (如果给定)或者使用平台默认的的字节编码解码。
    # 在文本模式,如果encoding 没有指定,则根据平台来决定使用的编码:使用locale.getpreferredencoding(False) 来获取本地编码。

    pass


def test_open_mode1():
    # 文本模式(默认):

    # file_path = '123456.txt'
    file_path = '一直会被删除的不存在.txt'

    # r 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。如果该文件不存在,报错。
    # file_obj = open(file_path)  # 因为 "r" (读取)和 "t" (文本)是默认值,所以不需要指定它们。
    # file_obj = open(file_path, encoding='utf-8')

    # file_obj = open(file_path, mode='r', encoding='utf-8')
    # 如果该文件不存在,FileNotFoundError: [Errno 2] No such file or directory: '一直会被删除的不存在.txt'

    # w 打开一个文件只用于写入。如果该文件已存在则将其覆盖,即原有内容会被删除。如果该文件不存在,创建新文件。
    # file_obj = open(file_path, mode='w', encoding='utf-8')

    # a 打开一个文件用于追加。如果该文件已存在,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
    # file_obj = open(file_path, mode='a', encoding='utf-8')

    # x 排它性创建;
    # The 'x' mode implies 'w' and raises an `FileExistsError` if the file already exists.
    # file_obj = open(file_path, mode='x', encoding='utf-8')  # FileExistsError: [Errno 17] File exists: '123456.txt'
    # file_obj = open(file_path, mode='x+', encoding='utf-8')

    # file_obj = open(file_path, mode='+', encoding='utf-8')  # ValueError: Must have exactly one of create/read/write/append mode and at most one plus

    # --------

    # r+    打开一个文件用于读写。文件指针将会放在文件的开头。
    # 直接写入会覆盖文件开头的内容。【是 从前往后 覆盖】
    # file_obj = open(file_path, mode='r+', encoding='utf-8')

    # w+	打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
    file_obj = open(file_path, mode='w+', encoding='utf-8')

    # a+	打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写
    # file_obj = open(file_path, mode='a+', encoding='utf-8')

    # --------

    Log.info(f'{file_obj, type(file_obj)}')

    # 如果文件是可写,则 writable() 返回 True,否则返回 False。
    # 如果文件是可读的,则 readable() 返回 True,否则返回 False。
    # closed,True if the stream is closed.
    Log.info(file_obj.writable())
    Log.info(file_obj.readable())
    Log.info(file_obj.closed)

    # tell() 给出文件中的当前位置,以文件的开头为原点;seek() 设置文件当前位置。
    Log.info(file_obj.tell())  # TODO 需要特别留意:指针位置!!! 尤其是 可读可写时,常常出现:读 但没数据,因为指针在最后。

    # write() 将字符串写入文件,返回写入的字符数。
    # write(s)
    # Write the string s to the stream and return the number of characters written.

    # writelines() 向文件写入一个序列(如字符串、列表),如果需要换行,则要自己加入每行的换行符。
    # writelines(lines)
    # Write a list of lines to the stream. Line separators are not added, so it is usual for each of the lines provided to have a line separator at the end.

    # readlines() 以列表的形式返回文件里的所有数据,文件有多少行,列表里就有多少个字符串。
    # 如果文件特别大,readlines() 会一次性把数据读取到内存中,这样会非常耗费内存;
    # readlines(hint=-1)
    # Read and return a list of lines from the stream.

    Log.info(file_obj.write('写入{}()'))  # 返回的是写入的字符长度
    file_obj.write('\n')
    file_obj.write('随机写入-{}-'.format(random.randint(1, 99999)))  # 使用r时,报错 io.UnsupportedOperation: not writable
    Log.info(file_obj.tell())

    file_obj.writelines(['a', 'b', 'c', 'A', 'B', 'C', '\n'])
    file_obj.writelines('123')
    # Log.info(f'{file_obj.readlines()}')  # 使用w时,使用a时,使用x时,报错 io.UnsupportedOperation: not readable
    Log.info(file_obj.tell())

    file_obj.seek(0, os.SEEK_SET)
    for _ in range(5):
        Log.info(f'{file_obj.readline(3)}')  # readline() 在一行中每次读取3个字节

    file_obj.seek(0, os.SEEK_SET)
    for _ in range(5):
        Log.info(f'{file_obj.readline(13)}')  # readline() 读取的字节长度若是大于本行长度时,不会继续读取下一行的。

    # close() 关闭文件。关闭后文件不能再进行读写操作
    file_obj.close()
    Log.info(file_obj.closed)

    # --------

    file_path = os.path.join(os.path.curdir, file_path)
    Log.info(f'{type(file_path), file_path}')

    if os.path.exists(file_path):
        # 打开的文件对象一定要记得在使用结束后 调用close方法关闭文件,否则将引发内存泄漏,

        # 使用with可以避免遗忘关闭文件
        with open(file_path, encoding='utf-8') as f:
            Log.info(f)
            Log.info(type(f))

            Log.info(f.readline())  # 每一行数据都包含了换行符
            Log.info(f.readline().rstrip())

            f.seek(0, 0)

            data = f.readlines()  # 每一行数据都包含了换行符
            Log.info(data)
            Log.info([d.rstrip() for d in data])

            Log.info(f.tell())

            f.seek(0)
            # hint can be specified to control the number of lines read: no more lines will be read if the total size (in bytes/characters) of all lines so far exceeds hint.
            Log.info(f.readlines(200))  # 其实readlines()的内部是通过循环调用readline()来实现
            # Log.info(f.readlines(20))
            Log.info(f.readlines(2))

        if file_path.find('一直会被删除的') != -1:
            os.remove(file_path)


def test_open_mode2():
    # 二进制模式:
    # Python 区分二进制和文本I/O。以二进制模式打开的文件(包括mode 参数中的'b' )返回的内容为bytes`对象,不进行任何解码。

    file_path = '7u908.png'
    # file_path = '一直会被删除的不存在{}.png'.format(random.randint(1, 1000))

    # rb	以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。
    # 如果文件不存在:FileNotFoundError: [Errno 2] No such file or directory: '一直会被删除的不存在.png'
    # file_obj = open(file_path, mode='rb')

    # wb	以二进制格式打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
    # file_obj = open(file_path, mode='wb')

    # ab	以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
    # file_obj = open(file_path, mode='ab')

    # --------

    # rb+	以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。
    file_obj = open(file_path, mode='rb+')

    # wb+	以二进制格式打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件
    # file_obj = open(file_path, mode='wb+')

    # ab+	以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写
    # file_obj = open(file_path, mode='ab+')

    # --------

    file_obj.write(bytes(12))  # 使用rb时,会报错 io.UnsupportedOperation: write

    r = random.randint(1, 9999)
    Log.info(file_obj.write(bytes('zfc{}'.format(r), encoding="utf-8")))
    w = ['字符串{}'.format(r).encode(encoding='utf-8'), '\n'.encode(encoding='utf-8'),
         'string{}'.format(r).encode(encoding='utf-8')]
    random.shuffle(w)
    file_obj.writelines(w)

    Log.info(file_obj.tell())

    # SEEK_SET = 0
    # SEEK_CUR = 1
    # SEEK_END = 2
    file_obj.seek(0, os.SEEK_SET)

    # read() 从文件中读取指定数量的字节。 如果未指定字节数,它将读取整个文件。
    # read(size=-1)
    # Read and return at most size characters from the stream as a single str. If size is negative or None, reads until EOF.
    Log.info(file_obj.read(5))
    Log.info(file_obj.read())

    file_obj.seek(0)  # whence: int = 0;默认whence=0,从开头起;

    # readline() 一次只读取一行(一整行);若指定size,将从该行读取最多size数量的字符。 函数到达文件末尾时,将返回一个空字符串。
    # readline(size=-1)
    # Read until newline or EOF and return a single str. If the stream is already at EOF, an empty string is returned.
    # If size is specified, at most size characters will be read.
    Log.info(f'{file_obj.readline()}')  # 使用wb时,使用ab时,会报错 io.UnsupportedOperation: read

    for _ in range(3):
        Log.info(f'{file_obj.readline(3)}')

    file_obj.close()

    file_p = os.path.join(os.path.curdir, file_path)
    Log.info(f'{type(file_p), file_p}')

    with open(file_p, mode='rb') as f:

        Log.info(f)
        Log.info(type(f))

        # Note that it’s already possible to iterate on file objects using  for line in file: ...
        # without calling file.readlines().
        # open返回的文件句柄,是一个可迭代对象,因此,你可以像迭代列表一样去迭代一个文件
        for line in f:
            Log.info(line)

        f.seek(0, os.SEEK_SET)
        Log.info(list(f))

    if file_p.find('一直会被删除的') != -1 and os.path.exists(file_path):
        os.remove(file_p)

str.format()

https://docs.python.org/zh-cn/3.7/library/stdtypes.html#str.format

https://docs.python.org/zh-cn/3.7/library/string.html#format-string-syntax

https://docs.python.org/zh-cn/3.7/library/string.html#format-specification-mini-language

https://docs.python.org/zh-cn/3.7/tutorial/inputoutput.html#the-string-format-method

之前写了些 字符串的format(): https://blog.csdn.net/zyooooxie/article/details/106348204

"""
@blog: https://blog.csdn.net/zyooooxie
@qq: 153132336
@email: zyooooxie@gmail.com
"""

# replacement_field ::=  "{" [field_name] ["!" conversion] [":" format_spec] "}"

# field_name        ::=  arg_name ("." attribute_name | "[" element_index "]")*
# arg_name          ::=  [identifier | digit+]
# attribute_name    ::=  identifier
# element_index     ::=  digit+ | index_string
# index_string      ::=  <any source character except "]"> +
# conversion        ::=  "r" | "s" | "a"
# format_spec       ::=  见 test_str_format1() 前面

def test_str_format_0():
    # field_name 本身以一个数字或关键字 arg_name 打头。如果为数字,则它指向一个位置参数,而如果为关键字,则它指向一个命名关键字参数。
    # 使用 conversion 字段在格式化之前进行类型强制转换。 目前支持的转换有三种: '!s' 会对值调用 str(),'!r' 调用 repr() 而 '!a' 则调用 ascii()。
    # format_spec 字段包含值应如何呈现的规格描述,例如字段宽度、对齐、填充、小数精度等细节信息。

    Log.info('')

    # '.name' 形式的表达式会使用 getattr() 选择命名属性,而 '[index]' 形式的表达式会使用 __getitem__() 执行索引查找。

    # 位置参数说明符对于 str.format() 可以省略,因此 '{} {}'.format(a, b) 等价于 '{0} {1}'.format(a, b)。

    # 一些简单的格式字符串示例:
    # "First, thou shalt count to {0}"  # References first positional argument                      引用第一个位置参数
    # "Bring me a {}"                   # Implicitly references the first positional argument       隐式引用第一个位置参数
    # "From {} to {}"                   # Same as "From {0} to {1}"                                 同"从{0}到{1}"
    # "My quest is {name}"              # References keyword argument 'name'                        引用关键字参数 'name'
    # "Weight in tons {0.weight}"       # 'weight' attribute of first positional arg                第一个位置参数的 weight属性
    # "Units destroyed: {players[0]}"   # First element of keyword argument 'players'               关键字参数“players”的第一个元素

    abc_list = ['1one', '2TWO', '3叁', '4四', '5Ⅴ']

    Log.info('{0!s}||{1!s}||{2!s}||{3!s}||{4!s}'.format(*abc_list))
    Log.info('{0!r}||{1!r}||{2!r}||{3!r}||{4!r}'.format(*abc_list))
    Log.info('{0!a}||{1!a}||{2!a}||{3!a}||{4!a}'.format(*abc_list))

    Log.info('')

    # 按位置访问参数:
    Log.info('{0}-{1}'.format('A', 'B'))
    Log.info('{2}-{3}-{1}-{0}'.format('A', 'bb', 'CCC', 'd'))

    Log.info('{}-{}-{}'.format('a', 'b', 'CCC'))
    Log.info('{0}-{0}-{1}-{1}-{1}'.format('a', 'B', 'c'))

    Log.info('{1}-{0}-{4}'.format(*abc_list))
    # Log.info('{1}-{55}'.format(*abc_list))  # IndexError: Replacement index 55 out of range for positional args tuple

    Log.info('')

    # 按名称访问参数:
    Log.info('{长}-{宽}'.format(=11,=22,=33))

    abc_dict = dict(=111,=-2222,=3, 重量=44, 密度=55555.55)
    Log.info('{长}-{重量}-{宽}-{宽}-{宽}-{宽}'.format(**abc_dict))
    Log.info('{长:.2f}||{重量:%}||{宽:+9}||{高:#o}'.format(**abc_dict))

    Log.info('{1}-{4}-{0}||{密度}-{重量}'.format(*abc_list, **abc_dict))

    Log.info('')

    # 访问参数的属性:
    from collections import namedtuple

    human = namedtuple('人', '身高, 体重, 性别')
    xiaoMing = human(1.8, 180, '男')
    xiaoHong = human(1.6, 160, '女')

    Log.info('小明的性别是{.性别},身高是{.身高:.0%}CM。'.format(xiaoMing, xiaoMing).replace('%', ''))
    Log.info('小明的身高是{0.身高}M,体重是{0.体重};小红的性别是{1.性别}。'.format(xiaoMing, xiaoHong))

    Log.info('')

    # 访问参数的项:
    Log.info('元素:{0[1]}-{0[4]}-{0[0]}'.format(abc_list))
    Log.info('元素:{0[密度]}'.format(abc_dict))

    Log.info('abc_list的元素:{1[1]};abc_dict的其中一个value:{0[宽]}'.format(abc_dict, abc_list))

    # Log.info('{0[假的]}'.format(abc_dict))  # KeyError: '假的'
    # Log.info('{0[-1]}'.format(abc_list))  # TypeError: list indices must be integers or slices, not str

    Log.info('再来几个:{list_[0]} {list_[3]} {list_[2]}'.format(list_=abc_list))
    Log.info('再来几个:{dict_[密度]} {dict_[密度]:,} {dict_[重量]} {dict_[重量]:x}'.format(dict_=abc_dict))

    Log.info('')

    # 对齐文本以及指定宽度:
    Log.info('{:<30}'.format('left aligned'))
    Log.info('{:>30}'.format('right aligned'))
    Log.info('{:^30}'.format('centered'))

    # 定义的width 和 小数点前长度+小数点后补齐的位数,后面的优先级更高
    Log.info('{:+^+6f}'.format(765.432))
    Log.info('{:+^+16f}'.format(765.432))

    Log.info('{:+^6.4f}'.format(765.432))
    Log.info('{:+^8.4f}'.format(765.432))
    Log.info('{:+^18.4f}'.format(765.432))

    Log.info('')

    # 替代 %+f, %-f 和 % f 以及指定正负号:
    Log.info('{:+f}; {:+f}'.format(3.1415, -3.1415))
    Log.info('{: f}; {: f}'.format(3.1415, -3.1415))
    Log.info('{:-f}; {:-f}'.format(3.1415, -3.1415))
    Log.info('{:f}; {:f}'.format(3.1415, -3.1415))

    Log.info('')

    # 替代 %x 和 %o 以及转换基于不同进位制的值:
    Log.info("int: {0:d};  hex: {0:x};  oct: {0:o};  bin: {0:b}".format(44))
    Log.info("int: {1:d};  hex: {1:#x};  oct: {1:#o};  bin: {1:#b}".format(55, 44))

    Log.info('')

    # 使用逗号作为千位分隔符:
    Log.info('{:,}'.format(12345.1234567890123))
    Log.info('{:,}'.format(1234567.1234567890123))
    Log.info('{:,}'.format(123456789.1234567890123))
    Log.info('{:,}'.format(12345678901.1234567890123))
    Log.info('{:,}'.format(1234567890123.1234567890123))
    Log.info('{:,}'.format(123456789012345.1234567890123))

    Log.info('')

    # 表示为百分数:
    Log.info('百分数:{:.2%}'.format(7 / 21))

    Log.info('')

    # 使用特定类型的专属格式化:
    import datetime
    d = datetime.datetime(2000, 1, 22, 3, 44, 5)
    Log.info('{:%Y-%m-%d %H:%M:%S}'.format(d))

    Log.info('')

    # 占位宽度 以变量形式 传入
    s = '123456'
    width = 20
    Log.info('{:*^{w}}'.format(s, w=width))
    Log.info('{0:*^{2}}||{1:.>{w}}||'.format(s, s[-3:], width - 10, w=width))
    Log.info('{:.<{}}'.format(s, width))


# format_spec     ::=  [[fill]align][sign][#][0][width][grouping_option][.precision][type]

# fill            ::=  <any character>
# align           ::=  "<" | ">" | "=" | "^"
# sign            ::=  "+" | "-" | " "
# width           ::=  digit+
# grouping_option ::=  "_" | ","
# precision       ::=  digit+
# type            ::=  "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%"

def test_str_format1():
    dd = 728833999444
    # dd = dd * -1

    Log.info('{}'.format(dd))

    Log.info('')

    # 如果指定了一个有效的 align 值,则可以在该值前面加一个 fill 字符,它可以为任意字符,如果省略则默认为空格符。
    Log.info('不给width')

    Log.info('{:>d}'.format(dd))
    Log.info('{:<d}'.format(dd))
    Log.info('{:^d}'.format(dd))
    Log.info('{:=d}'.format(dd))

    Log.info('{:a>d}'.format(dd))
    Log.info('{:b<d}'.format(dd))
    Log.info('{:c^d}'.format(dd))
    Log.info('{:d=d}'.format(dd))

    Log.info('给width')

    Log.info('{:>20d}'.format(dd))
    Log.info('{:<20d}'.format(dd))
    Log.info('{:^20d}'.format(dd))
    Log.info('{:=20d}'.format(dd))

    Log.info('{:A>20d}'.format(dd))  # 强制字段在可用空间内右对齐。
    Log.info('{:B<20d}'.format(dd))  # 强制字段在可用空间内左对齐。
    Log.info('{:C^20d}'.format(dd))  # 强制字段在可用空间内居中。
    Log.info('{:D=20d}'.format(dd))  # 强制将填充放置在符号(如果有)之后但在数字之前。这用于以“+00000111”形式打印字段。此对齐选项仅对数字类型有效。

    Log.info('{:e^10d}'.format(dd))

    # 使用 str.format() 方法时是无法使用花括号字面值 ("{" or "}") 作为 fill 字符的。
    Log.info('{:{}^20d}'.format(dd, '{'))
    Log.info('{:{}^20d}'.format(dd, '}'))

    Log.info('')

    # sign 选项仅对数字类型有效
    Log.info('{:+d}'.format(dd))  # '+'     表示标志应该用于正数和负数。
    Log.info('{:-d}'.format(dd))  # '-'     表示标志应仅用于负数(这是默认行为)。
    Log.info('{: d}'.format(dd))  # space   表示应在正数上使用前导空格,在负数上使用减号。

    Log.info('')

    # '#' 选项可以让“替代形式”被用于转换。 替代形式可针对不同类型分别定义。 此选项仅对整数、浮点、复数和 Decimal 类型有效。
    # 对于整数类型,当使用二进制、八进制或十六进制输出时,此选项会为输出值添加相应的 '0b', '0o' 或 '0x' 前缀。
    Log.info('{:#b}'.format(dd))
    Log.info('{:#o}'.format(dd))
    Log.info('{:#x}'.format(dd))

    Log.info('')

    # width 是一个定义最小总字段宽度的十进制整数,包括任何前缀、分隔符和其他格式化字符。 如果未指定,则字段宽度将由内容确定。
    Log.info('{:25d}'.format(dd))
    Log.info('{: 25d}'.format(dd))
    Log.info('{:d}'.format(dd))

    # 当未显式给出对齐方式时,在 width 字段前加一个零 ('0') 字段将为数字类型启用感知正负号的零填充。 这相当于设置 fill 字符为 '0' 且 alignment 类型为 '='。
    Log.info('{:025d}'.format(dd))

    Log.info('{:10d}'.format(dd))

    Log.info('')

    # ',' 选项表示使用逗号作为千位分隔符。
    # '_' 选项表示对浮点表示类型和整数表示类型 'd' 使用下划线作为千位分隔符。 对于整数表示类型 'b', 'o', 'x' 和 'X',将为每 4 个数位插入一个下划线。 对于其他表示类型指定此选项则将导致错误。
    Log.info('{:,}'.format(dd))

    Log.info('{:_}'.format(dd))
    Log.info('{:_b}'.format(dd))
    Log.info('{:_o}'.format(dd))
    Log.info('{:_x}'.format(dd))
    Log.info('{:_X}'.format(dd))

    Log.info('')

    # 对于整数值则不允许使用 precision。
    # Log.info('{:.1d}'.format(dd))  # ValueError: Precision not allowed in integer format specifier
    # Log.info('{:.1}'.format(dd))  # ValueError: Precision not allowed in integer format specifier

    Log.info('')

    # type 确定了数据应如何呈现。

    # 可用的整数表示类型是:

    # 'b'   二进制格式。 输出以 2 为基数的数字。
    Log.info('{:b}'.format(dd))
    Log.info('使用内置函数转换:{}'.format(bin(dd)))  # 前缀为“0b”

    # 'c'   字符。在打印之前将整数转换为相应的unicode字符。
    for i in range(50, 70):
        Log.info(str(i) + ' 对应的unicode字符: ' + '{:c}'.format(i))

    # 'd'   十进制整数。 输出以 10 为基数的数字。
    Log.info('{:d}'.format(dd))

    # 'o'   八进制格式。 输出以 8 为基数的数字。
    Log.info('{:o}'.format(dd))
    Log.info('使用内置函数转换:{}'.format(oct(dd)))  # 前缀为“0o”

    # 'x'   十六进制格式。 输出以 16 为基数的数字,使用小写字母表示 9 以上的数码。
    Log.info('{:x}'.format(dd))
    Log.info('使用内置函数转换:{}'.format(hex(dd)))  # 以“0x”为前缀

    # 'X'   十六进制格式。 输出以 16 为基数的数字,使用大写字母表示 9 以上的数码。
    Log.info('{:X}'.format(dd))
    Log.info('使用内置函数转换:{}'.format(hex(dd)))  # 以“0x”为前缀

    # 'n'   数字。 这与 'd' 相似,不同之处在于它会使用当前区域设置来插入适当的数字分隔字符。
    Log.info('{:n}'.format(dd))

    Log.info('')

    # 浮点数和小数值可用的表示类型有:
    # 【整数还可以通过下列的浮点表示类型来格式化 (除了 'n' 和 None)。 当这样做时,会在格式化之前使用 float() 将整数转换为浮点数】

    # 'e'   指数表示。 以使用字母 'e' 来标示指数的科学计数法打印数字。 默认的精度为 6。
    Log.info('{:e}'.format(dd))

    # 'E'   指数表示。 与 'e' 相似,不同之处在于它使用大写字母 'E' 作为分隔字符。
    Log.info('{:E}'.format(dd))

    # 'f'   定点表示。 将数字显示为一个定点数。 默认的精确度为 6。
    Log.info('{:f}'.format(dd))

    # 'F'   定点表示。 与 'f' 相似,但会将 nan 转为 NAN 并将 inf 转为 INF。
    Log.info('{:F}'.format(dd))

    # 'g'   常规格式。 对于给定的精度 p >= 1,这会将数值舍入到 p 位有效数字,再将结果以定点格式或科学计数法进行格式化,具体取决于其值的大小。
    Log.info('{:g}'.format(dd))

    # 'G'   常规格式。 类似于 'g',不同之处在于当数值非常大时会切换为 'E'。 无穷与 NaN 也会表示为大写形式。
    Log.info('{:G}'.format(dd))

    # 'n'   数字。 这与 'g' 相似,不同之处在于它会使用当前区域设置来插入适当的数字分隔字符。
    Log.info('{:n}'.format(dd))

    # '%'   百分比。 将数字乘以 100 并显示为定点 ('f') 格式,后面带一个百分号。
    Log.info('{:%}'.format(dd))

    Log.info('')

    Log.info('{:.0f}'.format(dd))  # 会在格式化之前使用 float() 将整数转换为浮点数
    Log.info('{:.2f}'.format(dd))
    Log.info('{:.9f}'.format(dd))


def test_str_format2():
    # ff = 77777.55555552222111444
    ff = 77777.55555552222
    ff = ff * -1

    Log.info('{}'.format(ff))

    Log.info('')

    Log.info('{:*^20f}'.format(ff))
    Log.info('{:+<20f}'.format(ff))
    Log.info('{:->20f}'.format(ff))

    Log.info('')

    Log.info('{:*>+20f}'.format(ff))
    Log.info('{:*>-20f}'.format(ff))
    Log.info('{:*> 20f}'.format(ff))

    Log.info('')

    # '#' 选项可以让“替代形式”被用于转换。
    # 对于浮点数、复数和 Decimal 类型,替代形式会使得转换结果总是包含小数点符号,即使其不带小数。

    Log.info('{:*>+#20f}'.format(ff))

    Log.info('{:*>+#20.0f}'.format(ff))

    Log.info('')

    Log.info('{:*>+#20,f}'.format(ff))
    Log.info('{:*>+#20_f}'.format(ff))

    Log.info('')

    # precision 是一个十进制数字,表示对于以 'f' and 'F' 格式化的浮点数值要在小数点后显示多少个数位,或者对于以 'g' 或 'G' 格式化的浮点数值要在小数点前后共显示多少个数位。

    Log.info('{:*>+#20,.0f}'.format(ff))
    Log.info('{:*>+#20,.3f}'.format(ff))
    Log.info('{:*>+#20_.5f}'.format(ff))

    Log.info('')

    Log.info('{:*>+#20,.3e}'.format(ff))
    Log.info('{:*>+#20,.3E}'.format(ff))
    Log.info('{:*>+#20,.4f}'.format(ff))
    Log.info('{:*>+#20,.4F}'.format(ff))

    Log.info('{:*>+#20,.2%}'.format(ff))

    Log.info('')

    Log.info('{:}'.format(ff))
    Log.info('{:f}'.format(ff))
    Log.info('{:,}'.format(ff))
    Log.info('{:%}'.format(ff))
    Log.info('{:+}'.format(ff))
    Log.info('{:-}'.format(ff))
    Log.info('{: }'.format(ff))

def test_str_format3():
    ss = 'zyooooxie'

    # 's'   字符串格式。这是字符串的默认类型,可以省略。
    Log.info('{:s}'.format(ss))

    Log.info('{:->20}'.format(ss))
    Log.info('{:-^20}'.format(ss))

    # precision 对于非数字类型,该字段表示最大字段大小,换句话说就是要使用多少个来自字段内容的字符。
    Log.info('{:*<20.5}'.format(ss))
    Log.info('{:*<20.15}'.format(ss))

    ll = ['zyooooxie', '博客', 'https://blog.csdn.net/zyooooxie', 123456789]

    Log.info('{!r}'.format(ll))
    Log.info('{!s}'.format(ll))
    Log.info('{!a}'.format(ll))

    Log.info('{!s:100}'.format(ll))

    Log.info('{!s:^100}'.format(ll))
    Log.info('{!s:>100}'.format(ll))

    Log.info('{!s:>100.10}'.format(ll))

本文链接:https://blog.csdn.net/zyooooxie/article/details/129037817

个人博客 https://blog.csdn.net/zyooooxie

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值