Notice: Function _load_textdomain_just_in_time was called incorrectly. Translation loading for the wp-pagenavi domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early. Translations should be loaded at the init action or later. Please see Debugging in WordPress for more information. (This message was added in version 6.7.0.) in /var/www/blog.zhujinhui.net/wp-includes/functions.php on line 6114

Notice: 函数 _load_textdomain_just_in_time 的调用方法不正确twentyseventeen 域的翻译加载触发过早。这通常表示插件或主题中的某些代码运行过早。翻译应在 init 操作或之后加载。 请查阅调试 WordPress来获取更多信息。 (这个消息是在 6.7.0 版本添加的。) in /var/www/blog.zhujinhui.net/wp-includes/functions.php on line 6114
煅魂-JeffreyChu的修炼屋 – 第 6 页 – 做一个胡思乱想的程序员

简单的打印,还可以玩得这么花?

在 Python 编程中,print函数是最基础但却非常重要的工具之一。它不仅用于输出信息到控制台,还可以用于调试和展示程序的运行状态。

print 函数在python3里已经从python2关键字升级为了函数,这让它有了更丰富的用法和玩法,今天我们将深入探讨print函数的各种用法和参数设置。

常用玩法

最简单的

最简单的 print 函数调用只需要一个参数,通常是我们的第一个python程序的内容

print("Hello, world!")

这段代码将输出 Hello, world! 到控制台。

Hello, world!
多个参数

print 函数可以接受多个参数,并将它们以空格分隔的形式输出:

print("Hello", "world", 2024)

输出结果为:

Hello world 2024
自定义分隔符

通过sep参数,可以自定义多个参数之间的分隔符(默认情况下sep参数指定为空格符)。例如,指定使用逗号和空格作为分隔符:

print("Hello", "world", 2024, sep=", ")

输出结果为:

Hello, world, 2024
自定义结束符

默认情况下,print 函数输出内容后会自动添加一个换行符。可以通过 end 参数自定义结束符,例如使用空格代替换行符:

print("Hello, world", end=" ")
print("Welcome to Python!")

输出结果为:

Hello, world Welcome to Python!
输出到文件

print 函数的 file 参数允许我们将输出重定向到文件而不是控制台。例如,将内容写入一个文本文件:

with open("output.txt", "w") as file:
    print("Hello, world!", file=file)

这段代码会在当前目录下创建一个名为 output.txt 的文件,并在其中写入 Hello, world!

flush 参数

flush 参数控制输出缓冲区的刷新。如果设置为 Trueprint 函数会立即将内容输出到目标设备,而不是等待缓冲区满或程序结束时再输出:

import time

print("Loading", end="", flush=True)
for i in range(5):
    time.sleep(1)
    print(".", end="", flush=True)

输出结果为:

Loading.....

上面代码每隔一秒钟会打印一个点,是不是很像某个下载或者进度加载过程?

高级用法

格式化输出

使用 f-string(格式化字符串)来更灵活地格式化输出内容,这样输出的内容更加连贯(而不是像空格有割离感):

name = "Jeff"
age = 25
print(f"Name: {name}, Age: {age}")

输出结果为:

Name: Jeff, Age: 25

另外,Python3.8以上的版本甚至可以这样打印

name = "Jeff"
age = 25
print(f"{name=}, {age=}")

输出为:

name='Jeff', age=25
多行输出

可以使用三重引号(””” 或 ”’)来输出多行字符串:

print("""
Line 1
Line 2
Line 3
""")

输出结果为:

Line 1
Line 2
Line 3

花活玩法

带颜色字符串

使用 ANSI 转义序列可以在支持这些序列的终端中输出带颜色的文本。以下是一些常见的 ANSI 转义序列:

前景色:

  • 黑色: \033[30m
  • 红色: \033[31m
  • 绿色: \033[32m
  • 黄色: \033[33m
  • 蓝色: \033[34m
  • 紫色: \033[35m
  • 青色: \033[36m
  • 白色: \033[37m
    背景色:
  • 黑色: \033[40m
  • 红色: \033[41m
  • 绿色: \033[42m
  • 黄色: \033[43m
  • 蓝色: \033[44m
  • 紫色: \033[45m
  • 青色: \033[46m
  • 白色: \033[47m
    重置颜色:
  • \033[0m

例如:

print("\033[32m这是绿文本\033[0m")
print("\033[33m这是黄色文本\033[0m")
print("\033[31m\033[47m这是红色白底文本\033[0m")

输出:

循环加载

上面已经有一个loading加载的例子了,但是有些时候,我们重复在某一行进行循环加载,尤其是模拟网络下载时(比如像npm install某些库时的命令行动态效果)。

因为涉及到同行循环,所以会用上退格符 \b,来回退覆盖已经输出的字符串。

import time

print("Loading", end="", flush=True)
for _ in range(5):
    for _ in range(3):
        time.sleep(1)
        print(".", end="", flush=True)
    time.sleep(1)
    print("\b\b\b   \b\b\b", end="", flush=True)

其实还有其他特殊字符(如\t\r等)可以和print进行联动

打印形状
打印爱心
print('\n'.join([''.join([('*' if ((x * 0.04) ** 2 + (y * 0.1) ** 2 - 1) ** 3 - (x * 0.04) ** 2 * (y * 0.1) ** 3 <= 0 else ' ') for x in range(-30, 30)]) for y in range(15, -15, -1)]))

效果图:

“佛祖保佑,永无BUG”,这个打印可以用在程序启动的时候,有buff加成,非常玄学。

注意,这里用的是raw stingr字符串,主要是避免里面的\符号被转义了。

print("""
                  _ooOoo_
                 o8888888o
                 88" . "88
                 (| -_- |)
                 O\  =  /O
              ____/`---'\____
            .'  \\|     |//  `.
           /  \\|||  :  |||//  \\
          /  _||||| -:- |||||-  \\
          |   | \\\  -  /// |   |
          | \_|  ''\---/''  |   |
          \  .-\__  `-`  ___/-. /
        ___`. .'  /--.--\  `. . __
     ."" '<  `.___\_<|>_/___.'  >'"".
    | | :  `- \`.;`\ _ /`;.`/ - ` : | |
    \  \ `-.   \_ __\ /__ _/   .-` /  /
=====`-.____`-.___\_____/___.-`____.-'======
                  `=---='

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         佛祖保佑       永无BUG
""")

输出:

打印logo

以打印“X秘书”为例

print("""
X         X         X      X                 X     X                          
 X       X       X X         X   X        XXXXXXXX  X 
   X   X           X       X    X            X   X
     X          XXXXXXX  X X   X  X      XXXXXXXXXXXX                        
   X   X           X    X  X X     X         X      X
 X       X       X X X     X    x            X    xXX    
X         X     X  X  X  X XXXXXX            X
"""
)

输出:

结论
print 函数是 Python 中最基本但却功能强大的工具之一。通过了解和掌握 print 的各种参数和用法,可以更高效地调试和展示程序的运行结果。

如果你还发现print有其他玩法,欢迎讨论交流

flake8,一个让你的Python代码更漂亮的库

众所周知,PEP 8规范是 Python 社区制定的一份关于代码格式和风格的优秀指南。

高质量的代码不仅提高了软件的可维护性和可读性,还减少了错误和漏洞,从而提升了软件的可靠性和安全性。

概念

Flake8 是一个广泛使用的 Python 代码质量检查工具,它结合了多个流行的静态代码分析工具,为开发人员提供了全面的代码检查功能。Flake8 的核心组件包括:

  • PyFlakes:检测代码中的错误,例如未使用的变量或未定义的名称。
  • pycodestyle (原名 PEP8):检查代码是否符合 PEP 8,即 Python 的官方编码规范。
  • McCabe:计算代码的圈复杂度,帮助开发人员识别复杂度过高的函数和方法。

为何要装

  • 保持代码的一致性和可读性
  • 发现代码中的潜在错误和问题
  • 让代码遵循 Python 编码规范(PEP 8)

安装和配置

pip安装

pip install flake8

接下来,在项目根目录创建.flake8配置文件,如:

[flake8]
max-line-length = 88
exclude = 
  .git,
  __pycache__,
  old,
  build,
  dist
ignore = E501,W503

上述ini代码配置中:

  • max-line-length = 88表示设置了代码行的最大长度限制为 88 字符。如果代码行超过这个长度,Flake8 将报告一条错误信息。这个值不同于默认的 79 字符,通常是为了与其他工具(如black格式化器)保持一致。
  • exclude这一项指定了 Flake8 在进行代码检查时要排除的目录列表。配置中的这些目录将不会被 Flake8 检查,比如例子就排除了.git__pycache__oldbuilddist这几个目录。
  • ignore = E501,W503则选项用于指定 Flake8 在进行代码检查时应忽略的错误和警告类型。这里忽略了两种特定的错误和警告

使用 Flake8 检查代码

配置之后,就可以使用flake8进行检查代码质量,

单个文件
flake8 your_script.py
整个项目
flake8 .

其实还可以这样临时指定参数运行,这里命令行参数会覆盖掉上面的.flake8文件里的配置参数

flake8 --ignore=E501,W503 your_script.py

输出解读

在执行完flake8命令后,比如用 Flake8 检查这段代码:

def my_function():
    print("Hello, World!")
print("This line is too long, it exceeds the maximum line length recommended by PEP 8.")

我们可能看到类似这样的错误或告警的输出

example.py:3:1: E305 expected 2 blank lines after class or function definition, found 1
example.py:4:80: E501 line too long (86 > 79 characters)

这些错误/告警提示,都是在指导你怎么把代码写的更加PEP 8规范化,提示也是比较明显了。更多错误可以参考这个PEP 8文档:

https://pep8.readthedocs.io/en/latest/intro.html#error-codes

忽略规则

在 Flake8 中,除了通过在.flake8配置文件中指定文件或文件夹外,它还提供了使用特定的注释来告诉 Flake8 在代码中忽略特定行的检查。这些注释称为 “Flake8 noqa comments”。

在代码中插入 # noqa 注释可以告诉 Flake8 忽略该行的检查。这在某些情况下很有用,例如当你知道某一行违反了规范,但你有充分的理由保留它时(尤其是一些比较急的热修复时)。

全局禁用
# flake8: noqa
import os  # noqa

在这个例子中,# flake8: noqa 告诉 Flake8 忽略整个文件的检查,而 # noqa 注释告诉 Flake8 忽略 import os 这一行的检查。

特定禁用
import os  # noqa: F401

在这个例子中,# noqa: F401 告诉 Flake8 忽略 import os 这一行的 F401 错误(未使用的导入)检查。

注意事项

尽量减少使用 # noqa 注释,它们应该只在确实需要的情况下使用,并且要确保有充分的理由来禁用检查,否则会导致漏检查引发隐藏问题。

集成到工作流

  • 在 IDE/编辑器中集成 Flake8(如 VSCode、PyCharm),这样在写代码的时候就能注意到问题
  • 在 CI/CD 管道中使用 Flake8, 比如在 GitHub Actions 中使用 Flake8
name: Flake8 Lint

on: [push, pull_request]

jobs:
  flake8:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Set up Python
        uses: actions/setup-python@v2
        with:
          python-version: '3.x'
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install flake8
      - name: Run Flake8
        run: |
          flake8 .

这样就能保证合并到仓库的代码是统一规范的。

插件

Flake8 还提供了其他优秀插件扩展功能,比如flake8-docstrings可以帮我们进行一些文档字符串检查(如函数/类/模块是否有文档注释等)

总结

Flake8 是 Python 开发中常用的代码质量检查工具,通过集成多个静态分析工具,帮助开发者确保代码符合PEP 8规范,提高可读性和一致性,提高了团队开发的效率。

参考链接

  • flake8 官方文档:https://flake8.pycqa.org/en/latest/index.html#quickstart
  • PEP 8 编码规范:https://wangmeng-python.readthedocs.io/en/latest/readability/PEP8.html