Python教程 - Linux迷 https://www.linuxmi.com 分享Linux和编程 Tue, 05 Nov 2024 11:54:59 +0000 zh-Hans hourly 1 https://wordpress.org/?v=6.9.4 https://www.linuxmi.com/wp-content/uploads/2020/02/cropped-Favicon-32x32.png Python教程 - Linux迷 https://www.linuxmi.com 32 32 GitHub 开发者报告:Python 成为新霸主,编程语言趋势正在改变 https://www.linuxmi.com/github-python.html?utm_source=rss&utm_medium=rss&utm_campaign=github-python https://www.linuxmi.com/github-python.html#respond Thu, 07 Nov 2024 00:20:32 +0000 https://www.linuxmi.com/?p=25118 GitHub 最近发布了一份关于开发者社区的报告,其中揭示了许多开发趋势的变化,尤其是 AI 对公开 …

The post GitHub 开发者报告:Python 成为新霸主,编程语言趋势正在改变 first appeared on Linux迷.

]]>
GitHub 最近发布了一份关于开发者社区的报告,其中揭示了许多开发趋势的变化,尤其是 AI 对公开和开源项目的深远影响。这份报告对开发者来说非常值得关注,其中几个编程语言的动态尤其引人注目。

Python 首次登顶成最热门语言

这份报告中最具看点的变化莫过于 Python 取代了 JavaScript,成为 GitHub 上的“最常用编程语言”。这是十年来的首次变动,自 2019 年以来首次有编程语言打破 JavaScript 的霸主地位。

Python 的上升与 AI 和数据科学的爆发性增长 密切相关。Python 凭借其简洁的语法、广泛的机器学习库支持、以及对新手友好的特性,吸引了大量开发者。不仅数据科学家和 AI 工程师偏爱 Python,越来越多的编程新人也选择了 Python 作为入门语言。

尽管 JavaScript 在代码提交数量上仍然领先,但 Python 在活跃度上更胜一筹,尤其是在提交请求、问题讨论和代码审查等互动上都表现出色。这种全面的活跃度让 Python 的社区变得更加生机勃勃。

TypeScript 稳步成长

与此同时,TypeScript 也保持着强劲增长的态势,稳居前三。在去年成功超越 Java 后,TypeScript 的受欢迎程度继续上升,成为现代 Web 应用开发中的重要工具。TypeScript 为 JavaScript 添加了类型检查和编译功能,这种增强的结构性和可靠性让越来越多的开发者从 JavaScript 转向 TypeScript,特别是那些注重代码健壮性的团队。

编程语言趋势的新变化

报告还揭示了开发者社区的其他有趣变化。例如:

  • Shell 超越了 C:这表明越来越多的开发者关注与基础设施相关的工作,Shell 脚本在系统运维、自动化任务方面的作用越来越显著。
  • HCL(HashiCorp Configuration Language)Go 语言:随着基础设施即代码(IaC)和云原生开发的普及,HCL 和 Go 在这一领域的使用量大幅增加。HCL 的简洁性使其在配置管理中极具优势,而 Go 则凭借高并发和快速编译,在云服务和微服务开发中得到了广泛应用。

Rust:安全与性能的平衡

在备受瞩目的编程语言中,Rust 的表现尤为亮眼。Rust 最初是作为 C 和 C++ 更安全的替代方案而设计,近年来凭借其内存安全性和高性能得到了大量开发者的青睐。Rust 的应用不仅限于小众领域,它的内存安全代码已被纳入一些主流操作系统的开发中,如 Linux 和 Windows。

Rust 不仅让系统级开发更安全,还因其创新的特性让开发者的生产力显著提升。Rust 社区的活跃度也在不断增加,形成了一个支持开发者学习和交流的良好环境。

总结

GitHub 的报告展示了编程语言的多样化趋势和开发者社区的动态变化。从 Python 的崛起到 TypeScript 和 Rust 的稳步增长,每种语言都在各自的领域展现出优势。对于想深入了解 2024 年开发者趋势的朋友,可以查看 GitHub 发布的完整报告,深入探索最新的开发者动向和技术趋势。

The post GitHub 开发者报告:Python 成为新霸主,编程语言趋势正在改变 first appeared on Linux迷.

]]>
https://www.linuxmi.com/github-python.html/feed 0
7 个 Python 程序员应该了解的列表函数 https://www.linuxmi.com/python-list-functions.html?utm_source=rss&utm_medium=rss&utm_campaign=python-list-functions https://www.linuxmi.com/python-list-functions.html#respond Fri, 01 Dec 2023 00:25:45 +0000 https://www.linuxmi.com/?p=23429 列表在Python的数据结构和算法中占据着重要地位。它们发挥着重要作用,而在项目中忽略它们几乎是不可 …

The post 7 个 Python 程序员应该了解的列表函数 first appeared on Linux迷.

]]>
列表在Python的数据结构和算法中占据着重要地位。它们发挥着重要作用,而在项目中忽略它们几乎是不可能的。

由于列表的重要性,Python提供了一些内置函数来执行常见的列表操作。这些函数旨在帮助开发人员更快速、更轻松地工作。

1、len() 函数

使用 len() 函数获取列表中项的数量。以下是一个示例:

my_list = [1, 2, 3, "hello", "rice", "code", 1.2]
list_length = len(my_list)
print(list_length) # returns 7

如果没有 len() 函数,您将不得不手动计算长度,就像在下面这个示例中使用 Python 的 for 循环一样:

my_list = [1, 2, 3, "hello", "linuxmi", "code", 1.2]
count = 0

for i in my_list:
    count += 1

print(count) # returns 7

从这个例子中可以明显看出 len() 函数节省了一些代码。确保在需要时使用它。

2、append() 函数

append() 函数将一个新项目添加到列表的末尾。一个很好的用法是在您的代码满足某个条件后向列表添加一个项目。以下是一个简单的示例:

my_list = [1, 2, 3, "hello", "linuxmi", "code", 1.2]
question = input("你喜欢Python吗?: ").lower()

if question == "yes":
    my_list.append("Python是最好的!!") # append()函数的使用
else:
    my_list.append("你应该试试Python") # append()函数的使用

print(my_list)

此示例使用if 语句根据用户的输入将某个句子添加到初始列表中。

append ()函数一次只能将一项添加到列表中。您可以使用运算符代替附加函数:

my_list = [1, 2, 3, "hello", "linuxmi", "code", 1.2]
my_list += ["Python是最好的!!"]

使用加法运算符最终会降低效率,因为它不会修改您的初始列表。相反,它在内存中创建一个新列表并向其中添加一个新项目。append ()函数直接修改您的初始列表。

3.extend()函数

extend ()函数是一个内置函数,它可以一次将多个项目添加到现有列表中。它接受新项目作为参数,并使用该参数修改现有列表。以下是如何使用extend()函数:

my_list = [1, 2, 3, "hello", "linuxmi", "code", 1.2]

my_list.extend(["yuyu", "linux", 93139])

print(my_list)
# prints [1, 2, 3, 'hello', 'linuxmi', 'code', 1.2, 'yuyu', 'linux', 93139]

extend ()函数只能接受一个参数,因此您应该将所有项目添加到一个列表中,如上面的代码。

4.reverse()函数

反向函数只是以相反的顺序重写您的列表。这是使用反向函数的示例:

my_list = [1, 2, 3, "hello", "linuxmi", "code"]

my_list.reverse()
print(my_list) # prints ['code', 'linuxmi', 'hello', 3, 2, 1]

要在不使用reverse()函数的情况下反转列表,您需要对列表进行切片。这是一个例子:

my_list = [1, 2, 3, "hello", "linuxmi", "code"]

reversed_list = my_list[::-1]
print(reversed_list) # prints ['code', 'linuxmi', 'hello', 3, 2, 1]

在上面的示例中,my_list[::-1]创建原始列表的反向副本。这意味着内存中将有两个列表,如果您只是想反转原始列表,这不是最好的方法。

5. insert() 函数

insert ()函数会修改列表并向其中添加项目,就像append()函数一样。但是,insert()函数允许您指定新项目在列表中的索引(位置)。这是一个例子:

my_list = [1, 2, 3, "hello", "linuxmi", "code"]

my_list.insert(0, "first") # 将"first"添加到列表的开头
print(my_list) # prints ['first', 1, 2, 3, 'hello', 'linuxmi', 'code']

从上面的代码来看,这是使用insert()函数的正确语法:

your_list.insert(index, new_list_item)

6.sort()函数

sort ()函数采用特定数据类型的列表并按升序重新排列元素。这是一个例子:

my_list = [1, 2, 10, 30, 3, 2.4]
my_list2 = ['code', 'linuxmi', '93139', 'hello']

my_list.sort()
my_list2.sort()

print(my_list) # prints [1, 2, 2.4, 3, 10, 30]
print(my_list2) # prints ['code', 'hello', 'linuxmi', '93139']

如果您在具有不同数据类型(例如字符串和数字)的列表上使用sort()函数,您将收到 TypeError。

7.count()函数

count ()函数计算特定元素在列表中出现的次数并将该值返回给您。使用方法如下:

my_list = ['code', 10, 30, 'code', 3, 'code', 'linuxmi', 5]
print(my_list.count('code')) # prints 3

在没有count()函数的情况下执行此类操作将需要编写更多代码。这是一个例子:

my_list = ['code', 10, 30, 'code', 3, 'code', 'linuxmi', 5]
count_code = 0

for item in my_list:
    if item == 'code':
        count_code += 1

print(count_code) # prints 3

len ()函数将返回列表中元素的总数,而count()函数将返回特定元素在列表中出现的次数。

使用列表函数编写更好的代码

在 Python 中使用列表时,使用可用的列表函数编写高效、简洁的代码非常重要。它们通常可以让您免于编写复杂且耗时的代码。

列表函数使您能够轻松执行常见的列表操作,让您有更多时间专注于代码的其他部分。

The post 7 个 Python 程序员应该了解的列表函数 first appeared on Linux迷.

]]>
https://www.linuxmi.com/python-list-functions.html/feed 0
如何创建高效的 Python Docker 镜像 https://www.linuxmi.com/python-docker-images.html?utm_source=rss&utm_medium=rss&utm_campaign=python-docker-images https://www.linuxmi.com/python-docker-images.html#respond Sun, 01 Oct 2023 21:41:49 +0000 https://www.linuxmi.com/?p=22974 Docker是打包和部署容器中应用程序的行业标准软件。Docker镜像是构建和运行应用程序的基础,为 …

The post 如何创建高效的 Python Docker 镜像 first appeared on Linux迷.

]]>
Docker是打包和部署容器中应用程序的行业标准软件。Docker镜像是构建和运行应用程序的基础,为了充分发挥Docker的潜力,您需要优化镜像以提高资源效率、安全性和性能。这将确保您的应用程序在Docker生态系统内无缝运行。

通过一个实际示例来学习如何实现这一点,演示如何将Python计算器应用程序容器化。

从最小的基础镜像开始

影响Docker镜像效率的因素之一是基础镜像的选择。您应该从一个只包括运行应用程序所需的基本组件的最小镜像开始。

您使用的镜像还应来自可信赖的来源,提供安全更新和补丁。它应该有一个活跃的社区和良好的文档。这在解决问题或寻求帮助时非常有帮助。

对于计算器应用程序,选择python:3.11-slim-bookworm这个最小镜像可以减小镜像的大小,从而减小资源消耗并加快镜像的下载和部署速度。

从最小的基础镜像开始
FROM python:3.11-slim-bookworm AS builder

您还可以选择更小的Alpine Linux镜像,选择python:3.11-alpine。然而,这个镜像不包括Python解释器、包管理器和常见的Python库。

以非root用户身份运行应用程序

以root用户身份运行Docker容器可能会带来重大的安全风险。如果恶意行为者能够访问以root身份运行的容器,他们可以利用容器软件中的漏洞来升级其权限。然后,他们可以使用这些权限来执行对主机系统的完全控制的命令。

解决方案是将应用程序以非root用户身份运行。计算器示例创建并配置了用户calculator。

为安全性设置非root用户
RUN adduser calculator --system

将用户添加到calculator组
RUN addgroup calculator && adduser calculator calculator

为您的应用程序创建一个专用用户会限制潜在攻击者可用的权限。这会增加利用漏洞的难度。

复制必要的文件并创建虚拟环境

在Docker容器内创建虚拟环境可以隔离依赖关系。这可以防止与系统范围的软件包和其他应用程序的冲突。它还确保版本兼容性,因为您可以安装应用程序需要的确切版本的依赖项,而不会影响系统的其余部分。

将必要的文件复制到容器中。然后,使用Python内置的venv模块为计算器应用程序创建一个虚拟环境。

设置工作目录并复制必要的文件
WORKDIR /app
COPY app.py .
COPY requirements.txt .
COPY config.json ./

从本地目录复制config.json
创建虚拟环境并安装依赖项
RUN python -m venv /venv
ENV PATH="/venv/bin:$PATH"
RUN /venv/bin/pip install --upgrade pip --no-cache-dir --requirement requirements.txt

虚拟环境是轻量级和高效的,因为它们不会复制系统范围的软件包。这有助于保持Docker镜像的较小大小,并在容器运行时减少资源消耗。

为提高效率减少层

Dockerfile中的每个指令都会在生成的镜像中创建一个新的层。Docker使用写时复制机制来管理这些层。减少Docker镜像中层次的数量显著提高了镜像的大小和构建性能。减少层次的一种方法是将多个命令合并到单个RUN指令中。

# 为提高效率减少层
# 合并命令以减少层的数量
RUN echo "构建过程在这里" && \
/venv/bin/python -m compileall . && \
rm -rf __pycache__

将上述命令合并起来可以减少在镜像构建过程中创建的中间层的数量。

保护配置处理的安全性

在Docker镜像中处理敏感信息会带来安全风险。为了增强安全性,您应该使用环境变量和外部配置文件。在计算器应用程序示例中,您可以创建一个名为/config的目录来存储配置文件,并设置适当的所有权。

# 保护配置处理的安全性
RUN mkdir /config && chown calculator:calculator /config

然后将config.json文件复制到此目录中,确保它与应用程序代码分开。

# 将config.json文件复制到容器中
RUN cp config.json /config/config.json
ENV CONFIG_PATH=/config/config.json

将配置数据与代码分离并应用适当的权限可以增强Docker镜像的整体安全性。这确保只有授权的进程或用户可以访问关键的配置数据。

使用多阶段构建
多阶段构建允许您将构建环境与最终镜像分开。这会导致更小、更专注的生产镜像。它还通过从最终镜像中排除与构建相关的工具和文件来增强安全性。这减小了攻击面,减少了与不必要组件相关的潜在安全风险。

# 利用多阶段构建
FROM python:3.11-slim-bookworm

COPY --from=builder /etc/passwd /etc/passwd
COPY --from=builder /etc/group /etc/group
COPY --from=builder /venv /venv
COPY --from=builder /config /config
COPY --from=builder /app /app
# 复制应用程序代码

上述代码只将构建阶段(builder)中的必要部分复制到最终镜像中。这通过排除运行计算器应用程序所需的构建相关工具和文件来减小镜像大小。

通过镜像扫描增强安全性

为了进一步增强Docker镜像的安全性,请使用像Trivy或Clair这样的镜像扫描工具。这些工具旨在识别图像层和依赖性中的漏洞。对于计算器应用程序,请使用Trivy进行漏洞扫描。

# 为Debian/Ubuntu安装Trivy
RUN apt-get update && \
apt-get install -y wget apt-transport-https gnupg lsb-release && \
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | apt-key add - && \
echo "deb https://aquasecurity.github.io/trivy-repo/deb bookworm main" \
| tee -a /etc/apt/sources.list.d/trivy.list && \
apt-get update && \
apt-get install -y trivy

将Trivy漏洞扫描添加到Docker镜像中非常重要。这是因为它使用通用漏洞和暴露(CVE)数据库,该数据库定期更新包含已知漏洞的信息。这有助于确保您的镜像始终使用最新的安全补丁,并保护您的应用程序免受已知攻击的影响。

要获取有关您的镜像的漏洞报告,请使用以下命令。

docker run --rm `
-v /var/run/docker.sock:/var/run/docker.sock `
-v $HOME/Library/Caches:/root/.cache/ `
aquasec/trivy:0.18.3 `
<your image name>

上述命令将需要一些时间来运行。运行完毕后,将生成报告。

严重性越高,您就应该更快地解决已识别的漏洞。

以非 root 用户身份运行应用程序

为了增强安全性,以calculator用户身份运行应用程序,以限制潜在的漏洞。

# 以非根用户身份运行应用程序
WORKDIR /app
USER calculator

# 激活虚拟环境并运行应用程序
CMD ["/bin/bash", "-c", "source /venv/bin/activate && python app.py"]

切换到非 root 用户可以最小化攻击面。

容器化非Python应用程序

使用其他编程语言开发的应用程序的Docker容器化方式有所不同。您应该熟悉如何容器化不同类型的应用程序。这将帮助您根据应用程序使用的语言类型决定采用的最佳策略。

The post 如何创建高效的 Python Docker 镜像 first appeared on Linux迷.

]]>
https://www.linuxmi.com/python-docker-images.html/feed 0
理解 Python 中的浅复制和深复制 https://www.linuxmi.com/python-shallow-and-deep-copy.html?utm_source=rss&utm_medium=rss&utm_campaign=python-shallow-and-deep-copy https://www.linuxmi.com/python-shallow-and-deep-copy.html#respond Tue, 26 Sep 2023 00:25:18 +0000 https://www.linuxmi.com/?p=22920 Python 提供了多种有效的方法来管理数据。在处理嵌套列表、字典或自定义对象等数据结构时,理解浅复 …

The post 理解 Python 中的浅复制和深复制 first appeared on Linux迷.

]]>
Python 提供了多种有效的方法来管理数据。在处理嵌套列表、字典或自定义对象等数据结构时,理解浅复制和深复制的概念是至关重要的。

使用浅复制

浅复制通过创建原始对象的顶层结构的副本来工作。这意味着如果原始对象包含嵌套对象,复制将引用与原始对象相同的嵌套对象。换句话说,对对象进行浅复制会复制其最外层结构,而不会复制它可能包含的任何嵌套对象。

要在 Python 中执行浅复制,您可以使用 copy 模块的 copy() 函数或对象上的 .copy() 方法。

考虑一个在 Python 中使用列表或字典的示例。

# Linux迷 www.linuxmi.com
import copy

main_list = [29, 49, ["Q", "R"]]
shallow_copy = copy.copy(main_list)

# 修改嵌套列表
shallow_copy[2][0] = 99
main_list[2][1] = 100

print(f"The main list: {main_list}")
print(f"The shallow copy list: {shallow_copy}")

上面的代码中,main_list 变量包含一个包含整数和包含字母的内部列表(嵌套对象)。copy 函数创建了 main_list 的副本,代码将其存储在另一个变量 shallow_copy 中。

您对 shallow_copy 嵌套列表所做的任何更改也将直接影响到 main_list,反之亦然。这些更改表明 shallow_copy 的嵌套或内部列表只是对 main_list 的引用,使更改也适用于 main_list。

与此同时,对 shallow_copy 或 main_list 中的外部项(整数)所做的任何更改仅会影响该实例。这些外部项本质上是独立的值,而不仅仅是引用。

# Linux迷 www.linuxmi.com
import copy

main_list = [29, 49, ["Q", "R"]]
shallow_copy = copy.copy(main_list)

# 修改外部项
shallow_copy[0] = "M"
main_list[1] = "N"

print(f"The main list: {main_list}")
print(f"The shallow copy list: {shallow_copy}")

输出表明两个列表的外部项是彼此独立的:

对浅复制的外部项进行更改

在处理字典时,相同的理念也适用。

# Linux迷 www.linuxmi.com
dict1 = {'ten': 10, 'twenty': 20, 'double':{'thirty': 30, 'sixty': 60}}
dict2 = dict1.copy()

# 修改内部和外部元素
dict1['double']['thirty'] = 30.00
dict1['ten'] = 10.00

print(f"The main dictionary, {dict1}")
print(f"The shallow copy dictionary, {dict2}")

对 dict1 的嵌套字典进行的更改会影响 dict1 和 dict2。与此同时,对 dict1 的外部项进行的更改只会影响 dict1。

使用嵌套字典的浅复制

使用深复制

深复制不是引用原始复制的嵌套对象,而是完全单独复制原始对象及其嵌套对象。对深复制的修改不会影响原始对象,反之亦然;它们是真正独立的值。

要在Python中创建深度复制,可以使用copy模块的deepcopy()函数。

考虑一个使用列表的示例。

# Linux迷 www.linuxmi.com
import copy

main_list = [200, 300, ["I", "J"]]
deep_copy = copy.deepcopy(main_list)

# 修改内部和外部列表
deep_copy[2][0] = "K"
main_list[0] = 500

print(f"主列表:{main_list}")
print(f"深度复制列表:{deep_copy}")

在这里,代码执行了main_list的深度复制,创建了一个名为deep_copy的独立副本。

当您修改deep_copy中的嵌套列表或外部项时,您的更改不会影响原始列表,反之亦然。这表明嵌套列表或外部元素不在两个副本之间共享。

处理自定义对象

您可以通过定义Python类并创建类的实例来创建自定义对象。

以下是从Book类创建一个简单对象的示例:

class Book:
def __init__(self, title, authors, price):
self.title = title
self.authors = authors
self.price = price

def __str__(self):
return f"Book(title='{self.title}', author='{self.authors}', \
price='{self.price}')"

现在,使用copy模块对这个Book类的实例分别进行浅复制和深复制。

import copy

# 创建一个Book对象
book1 = Book("www.linuxmi.com 如何利用浅拷贝", \
["Bobby Jack", "Princewill Inyang"], 1000)

# 进行浅复制
book2 = copy.copy(book1)

# 修改原始对象
book1.authors.append("Yuvraj Chandra")
book1.price = 50

# 检查对象
print(book1)
print(book2)

如您所见,浅复制(book2)是一个新对象,但它引用与原始对象(book1)相同的内部对象(作者列表)。因此,对原始对象的作者进行的更改会影响两个实例(book1和book2),而对外部项(价格)的更改只会影响原始对象(book1)。

另一方面,进行深复制会创建原始对象的独立副本,包括其中包含的所有对象的副本。

# 创建一个Book对象
book1 = Book("www.linuxmi.com 如何利用浅拷贝?", \
["Bobby Jack", "Yuvraj Chandra"], 5000)

# 进行深复制
book2 = copy.deepcopy(book1)

# 修改原始对象
book1.authors.append("Princewill Inyang")
book1.price = 60

# 检查对象
print(book1)
print(book2)

在这种情况下,深复制(book2)是一个完全独立的对象,对原始对象(book1)的修改不会影响它。

使用浅复制和深复制的用途

了解深度和浅复制非常重要,以便您可以选择适当的方法来操作数据。以下是适用于每种方法的一些情况:

  • 如果您想要复制一个复杂对象而不生成其嵌套对象的新实例,则使用浅复制。这种方法比深复制更节省内存并且更快,因为它不会复制嵌套对象。
  • 如果您想要创建对象状态的快照,同时仍然在原始对象和复制对象之间共享一些基础数据,则使用浅复制。
  • 如果您想要修改对象的副本而不影响原始对象,则使用深复制。这会生成独立的嵌套对象的副本,确保对副本的任何更改不会应用于原始对象。
  • 当您需要独立副本的嵌套数据结构时,特别是在处理递归或复杂的对象层次结构时,深复制非常重要。

性能和注意事项

由于浅复制不生成嵌套对象的新实例,因此通常比深复制运行速度更快,使用的内存更少。然而,原始对象和浅复制可能会因更改共享的内部项目而产生不希望的副作用。

特别是对于大型和深度嵌套的数据结构,深复制是一个递归过程,可能会更慢,使用更多内存。然而,它确保了原始对象和深度副本之间的完全独立性,使复杂的数据操作更加安全。

选择适合您数据的最佳复制选项 许多编程语言都使用浅复制和深复制的概念。了解这一概念使您能够在没有意外后果的情况下操作数据。

通过使用浅复制和深复制技术,您可以选择最安全地复制数据结构的最佳方法。通过了解对数据的影响,您将从代码中获得更可靠和可预测的结果。

The post 理解 Python 中的浅复制和深复制 first appeared on Linux迷.

]]>
https://www.linuxmi.com/python-shallow-and-deep-copy.html/feed 0
Python vs. Java: 2023 年最佳编程语言 https://www.linuxmi.com/python-vs-java.html?utm_source=rss&utm_medium=rss&utm_campaign=python-vs-java https://www.linuxmi.com/python-vs-java.html#respond Mon, 25 Sep 2023 00:25:46 +0000 https://www.linuxmi.com/?p=22909 在众多选择中,两个明显的竞争对手在争夺最佳编程语言的称号,尤其是对初学者来说:Python和Java …

The post Python vs. Java: 2023 年最佳编程语言 first appeared on Linux迷.

]]>
在众多选择中,两个明显的竞争对手在争夺最佳编程语言的称号,尤其是对初学者来说:Python和Java。这场较量一年又一年地持续下去。

无论您是开发游戏、实用工具还是复杂应用程序,相关的问题是:Python是否比Java更好?Java 是否比 Python 更容易?应该学习哪种编程语言呢?

看看您是否能自己决定,并且是否同意我们的结论,该结论是基于一些相关分析得出的。

Java vs. Python:竞争开始

在这个比较中,您可以考虑以下要点:

  • 学习:学习Java是否比学习Python更容易?还是反之?
  • 运行代码:哪种编程语言更容易编译和运行您的代码?
  • 游戏开发:Java是否比Python更适合游戏开发?
  • 衡量需求:哪种编程语言能够战胜竞争,赢得市场?
  • Web应用程序:Python是否比Java更擅长构建动态网站和应用程序?
  • 数据科学:哪种编程语言是每个数据科学家最喜欢的?

Python vs. Java:学习细节

Python对于初学者来说非常简单:所见即所得。它的语法简单,是一种很好的通用语言。Python持续吸引那些刚开始编程、希望尽可能轻松入门的人。

尽管有着广泛且有力的社区支持,但Java更适合具有多年编程经验的高级用户。简单来说,尽管该语言拥有众多用户,但不适合心志薄弱者。

Java vs. Python:解释代码

这两种语言继续吸引人们的注意,因为它们用途广泛。每种语言都使用不同的语法,都旨在易于阅读,因此您会发现相似之处和不同之处。

Python 配备了一个交互式 Shell,也称为REPL(Read-Eval-Print-Loop),它允许您尝试使用该语言。您可以使用它来运行代码片段,并直接从命令行中了解Python语法是如何工作的。

例如,您可以输入以下命令:

a = 9
b = 3
a + b

并可以即时看到效果:

Python 交互式 Shell 显示基本加法的示例

Java不提供命令行解释器,因为它是一种编译语言。您需要编写代码、编译它,然后运行它才能看到其效果,这可能是一个耗时的过程。

而且,即使是最简单的Java程序也需要大量样板代码:

public class linuxmi {
    public static void main(String[] args) {
        System.out.println("9+3=" + (Integer.toString(9 + 3)));
    }
}

输出如下:

Python vs. Java:游戏开发导引

Python是一种高级语言,易于使用,但它不能生成运行速度最快的代码。游戏开发需要快速的处理和高速的图形处理。

Python可以通过使用第三方库的包装和绑定来克服这种延迟。然而,这是实现游戏速度的一种困难方式,从长远来看并不用户友好。

如果您仍然热衷于使用Python进行游戏开发,可以考虑使用Arcade库作为动画游戏对象的适当选择。

在此轮比较中,Java获胜,因为它提供了多线程,而Python则没有。Java还具有出色的网络支持,提供了在创建多人游戏时非常方便的套接字。在Java中,JMonkeyEngine和OpenGL仍然是受欢迎的开源游戏引擎,尽管它们无法与C和C++等一些其他更快的语言竞争。

最终,无论哪种语言都不是最适合游戏开发的。尽管Java是更好的选择,但市场上有更适合游戏开发的编程语言。

Python vs. Java:哪个更受欢迎?

Python的编程需求在后疫情时代急剧上升,这个备受喜爱的语言已经不可逆转。在2023年,它在TIOBE的编程社区指数中获得了第一名,这充分说明了它在编程领域的重要性。

Python是否比Java更受欢迎?答案是”是”,因为尽管出现了更新的替代品,但这种语言仍然具有合适的市场份额。

Java的多功能性和开发选项使其保持在Stack Overflow最受欢迎的编程语言之列,尽管这可能会在未来几年内下降。尽管地位逐渐下降,但在2023年,它仍然是一种值得学习的编程语言。

Python vs. Java:拥抱Web开发的框架

Python的Web开发框架包括Django和Flask,它们提供了基本的功能,而没有太多的路由请求和过多的开销。

另一方面,Java的Spring是最知名的后端框架之一,主导着Web应用程序开发。Java的开发生态系统庞大,具备社区支持,使开发过程更加简便和实用。

无论如何,Java和Python之间的竞争是激烈的,因为这两种语言都提供了许多竞争性的选项,为优秀的Web应用程序构建铺平了道路。

Python vs. Java:数据科学适用性

在数据科学领域,支持的编程语言不胜枚举。当比较Python和Java时,前者仍然居于优势地位。您可以使用Java进行数据科学编程,因为它支持大数据处理。然而,Python的数据科学工具在数据科学家中非常流行。

Python为数据科学提供了许多有用的功能,无论是在其标准库中还是通过第三方库。Pandas和NumPy库非常广为人知和使用。

另一方面,Java更倾向于支持Web开发和通用编程,没有太多专注于数据科学的特点。

Java vs. Python:未来哪个更适合

考虑到上面列出的所有排名因素,毫无疑问,Python 是我们在 2023 年的首选语言。如果您想深入研究一种定制、易于学习且能够带来良好回报的语言,那么您应该选择 Python。

该语言的多功能性、可定制选项和简单的语法将使其成为您现有的编程技能库中的绝佳补充。

相关:

探索 Python 3.12:让你的调试技能翻倍提升!  https://www.linuxmi.com/python-3-12-debugging.html

10 个 Python Itertools,让你的代码如虎添翼  https://www.linuxmi.com/python-itertools.html

15 个强大的日常使用的 Python 单行代码  https://www.linuxmi.com/python-one-line-code.html

了解 Java 21 的最新增强功能  https://www.linuxmi.com/java-21.html

Java 中的 Hello World 示例程序  https://www.linuxmi.com/java-hello-world.html

The post Python vs. Java: 2023 年最佳编程语言 first appeared on Linux迷.

]]>
https://www.linuxmi.com/python-vs-java.html/feed 0
如何使用 Python 生成和读取条形码 https://www.linuxmi.com/python-barcodes-read-generate.html?utm_source=rss&utm_medium=rss&utm_campaign=python-barcodes-read-generate https://www.linuxmi.com/python-barcodes-read-generate.html#respond Tue, 15 Aug 2023 02:25:58 +0000 https://www.linuxmi.com/?p=22511 条形码在我们的日常生活中很常见。只需几个简单的步骤,您就可以使用 Python 轻松生成和扫描条形码 …

The post 如何使用 Python 生成和读取条形码 first appeared on Linux迷.

]]>
条形码在我们的日常生活中很常见。只需几个简单的步骤,您就可以使用 Python 轻松生成和扫描条形码。

当您从商店购买商品时,您所购买的物品上的平行黑条纹,具有不同宽度,被称为条形码。条形码是一种将数据以视觉、机器可读的方式表示的方法。条形码被用于存储有关产品的信息,以便进行方便的识别和追踪。各个行业都使用条形码进行库存管理。

使用Python,您可以生成条形码,扫描并读取条形码的内容。

如何生成和自定义条形码 以下步骤展示了如何使用python-barcode库生成条形码。

1、安装所需库

打开您的终端或命令提示符,运行以下pip命令来安装所需的库。确保您的机器上已安装了pip。

linuxmi@linuxmi ~/www.linuxmi.com
 % pip install python-barcode

2、导入所需模块

在您的脚本中,包含以下导入语句,以导入生成条形码所需的模块。

import barcode
from the barcode.writer import ImageWriter

编写器负责在不同格式中生成和保存条形码图像。python-barcode 库提供了不同的条形码编写器。在这里,您将使用ImageWriter 类,该类将条形码渲染为图像。

3、生成条形码的代码

python-barcode库提供了各种条形码格式,例如Code39、Code128、EAN13和ISBN-10,用于生成条形码。

def generate_barcode(data, barcode_format, options=None):
    # 获取与指定格式对应的条形码类
    barcode_class = barcode.get_barcode_class(barcode_format)
    # 使用提供的数据和格式创建条形码图像
    barcode_image = barcode_class(data, writer=ImageWriter())
    # 将条形码图像保存到名为"linuxmi"的文件中,带有指定的选项 
    barcode_image.save("linuxmi", options=options)

generate_barcode函数根据给定的数据和格式(barcode_format)生成条形码,并将条形码图像保存到文件linuxmi.png中。文件扩展名取决于您使用的写入器类别。

4、生成和自定义条形码

要生成条形码,调用 generate_barcode 函数并传递所需的参数。

generate_barcode("www.linuxmi.com", "code128")

生成的条形码

编写器接受多个选项,使您能够自定义条形码。自定义选项包括修改条形码的大小、字体、颜色等。您可以参考python-barcode文档,以获得完整的常见编写器选项列表。

generate_barcode("www.linuxmi.com", "code128", options={"foreground":"red", 
                                                  "center_text": False, 
                                                  "module_width":0.4, 
                                                  "module_height":20})

在自定义选项中,您可以调整前景颜色、背景颜色,甚至可以选择是否在条形码上显示文本。

如何扫描和解码条形码

以下步骤介绍了如何使用Python的pyzbar库扫描和解码条形码。

1、安装所需的库

要扫描和解码条形码,您需要安装以下库:

brew install zbar # Mac OS X
sudo apt-get install libzbar0 # Linux OS
pip install pyzbar opencv-python

2、导入所需的模块

安装完库后,在脚本中添加以下导入语句以导入必要的模块。

import cv2
from pyzbar import pyzbar

3、从图像中扫描条形码

从图像文件中扫描条形码的方法如下:

使用OpenCV的imread函数加载图像。这将返回一个numpy.ndarray实例。

将输出数组传递给pyzbar.decode以进行检测和解码。您还可以传递PIL.Image的实例。

def scan_barcode_from_image(image_path):
    # 从提供的文件路径读取图像
    image = cv2.imread(image_path)
    # 使用pyzbar从图像中解码条形码
    barcodes = pyzbar.decode(image)
    # 遍历检测到的条形码并从中提取数据
    for barcode in barcodes:
        # 使用UTF-8编码
        barcode_data = barcode.data.decode("utf-8")
        barcode_type = barcode.type
        print("Barcode Data:", barcode_data)
        print("Barcode Type:", barcode_type)

该函数接受image_path参数,读取图像,解码图像中存在的任何条形码,并打印每个检测到的条形码的解码数据和类型。

scan_barcode_from_image("linuxmi.png")

从网络摄像头流中扫描条形码

您还可以借助Python OpenCV库从网络摄像头流中实时扫描和读取条形码。

def scan_barcode_from_webcam():
    # 初始化默认网络摄像头 (index 0) 视频捕获
    video_capture = cv2.VideoCapture(0)

    while True:
        # 从网络摄像头流中获取一帧
        _, frame = video_capture.read()

        # 解码帧中的条形码
        barcodes = pyzbar.decode(frame)

        # 处理检测到的条形码
        for barcode in barcodes:
            # 提取条形码数据和类型并打印
            barcode_data = barcode.data.decode("utf-8")
            barcode_type = barcode.type
            print("Barcode Data:", barcode_data)
            print("Barcode Type:", barcode_type)

        # 检查退出条件:按下'q'退出循环
        if cv2.waitKey(1) & 0xFF == ord("q"):
            break

    # 释放视频捕获并关闭OpenCV窗口
    video_capture.release()
    cv2.destroyAllWindows()


scan_barcode_from_webcam()

scan_barcode_from_webcam函数连续捕获网络摄像头的帧,解码帧中存在的任何条形码,提取条形码的信息并打印出来。按键盘上的字母q键可以退出。

通过Python生成和读取条形码和二维码

使用Python,生成和读取条形码变得轻松高效。按照上述步骤,您可以生成各种适合您需求的条形码。

QR码(Quick Response codes)是一种二维码,可以通过配备摄像头和QR码阅读器应用程序的智能手机、平板电脑或其他设备进行扫描和阅读。使用Python的qrcode库,您可以高效地生成、扫描和阅读QR码。

The post 如何使用 Python 生成和读取条形码 first appeared on Linux迷.

]]>
https://www.linuxmi.com/python-barcodes-read-generate.html/feed 0
Marble:适用于 Linux 的开源 Google 地球替代方案 https://www.linuxmi.com/marble-linux-google-earth.html?utm_source=rss&utm_medium=rss&utm_campaign=marble-linux-google-earth https://www.linuxmi.com/marble-linux-google-earth.html#respond Mon, 07 Aug 2023 23:12:44 +0000 https://www.linuxmi.com/?p=22441 Marble,一个开源的虚拟地球仪,适用于桌面版的 Linux,让您可以探索地球,规划路线,甚至可以 …

The post Marble:适用于 Linux 的开源 Google 地球替代方案 first appeared on Linux迷.

]]>
Marble,一个开源的虚拟地球仪,适用于桌面版的 Linux,让您可以探索地球,规划路线,甚至可以看到数百年前人们的视角。

为什么使用 Marble?

在地图和地球可视化领域,谷歌地球(Google 地球,Google Earth)是最知名的工具,您甚至可以将谷歌地球用作网络演示工具。作为 Linux 用户,您可能不太愿意在您的桌面上安装来自一个臭名昭著的侵犯隐私的公司的软件,尤其是当该软件是在中央情报局的资金支持下开发的时候。

如果您关心隐私但仍然想探索地球及其周边,那么由 KDE 开发的 Marble 是一个很好的替代选择,它提供导航、卫星图像、街景地图以及各种与气候有关的叠加图层。您不仅限于地球,还可以浏览月球上的无人海域和撞击坑。

如何在 Linux 上安装 Marble

Marble 在大多数主要发行版的默认软件库中都有提供,但这些版本通常比最新版本落后几个版本。

获取 Marble 的最新版本最简单的方法是使用 Flatpak,因此如果您的发行版尚未安装 Flatpak,请先安装 Flatpak。相关教程见:https://www.linuxmi.com/linux-flatpak.html

现在您可以使用以下命令安装 Marble:

linuxmi@linuxmi ~/www.linuxmi.com
 % flatpak install flathub org.kde.marble

或者,如果您的发行版安装了 Snap,您可以使用以下命令安装 Marble:

linuxmi@linuxmi ~/www.linuxmi.com 
% sudo snap install marble

您现在可以从系统菜单中启动Marble。

用Marble探索世界吧!

第一次打开Marble,您将看到一个以丹麦为中心的地球表示。默认视图类似于传统的地图集视图,显示了显著的地理特征,如山脉和海洋沟槽,以及代表国家之间政治边界的彩色线条。

您还将看到人工划分,如赤道、回归线和本初子午线。

与谷歌地球类似,您可以使用鼠标左键抓住虚拟地球,围绕任何轴旋转,或使用鼠标滚轮放大和缩小景观。默认的地图集视图不会提供太多细节。标记了首都城市和主要特征,但无论您缩放多远,都看不到较小的定居点或更精细的特征。

幸运的是,Marble默认提供了15种不同的地图视图。它们的实用性各不相同,但各自都很有趣。

对于大多数使用情况来说,最实用的地图视图是OpenStreetMap。这是一个由OpenStreetMap项目创建的全球街道地图,该项目使用航空影像、GPS设备和现场地图来确保信息的准确性。

在 OSM 视图中,您将获得类似于谷歌地图的视图。最小的定居点是可见的,与谷歌的服务不同,您甚至可以查看人行道、骑马道和其他小型公共通道。

卫星视图基于NASA 的 beautiful Blue Marble Next Generation 图片,展示了从太空中看到的地球。然而,分辨率并不是很高,放大时往往会让人失望。

如果你正在考虑度假,或者只是对气象学有一时的兴趣,你可以使用七月和十二月的降水和温度视图。这可以让你了解世界其他地区的气候状况,如果你正在计划下一次跨洲的冒险,也可以帮助你避免或寻找过于炎热、潮湿、寒冷或干燥的地点。

大多数时候,你可能只是因为无事可做而启动 Marble,而在我们看来,其中最吸引人的特点之一就是历史地图视图。

这张1689年的地图是由荷兰地理学家杰拉德·范·斯哈亲(Gerard van Schagen)创作的,而Behaim Globe则基于Erdapfel——最古老的现存地球仪,由马丁·贝海姆(Martin Behaim)于1492年创作。你不应该指望这些地图是准确的,这是由欧洲人创作的,因为当时的他们对世界的了解有限且往往不准确。

例如,在上面的1689年世界地图截图中,你可以看到加利福尼亚被描绘成了一个岛屿。虽然我们不希望过于依赖这些历史地图,但它们仍然是窥视不同时代和世界观的迷人窗口。

除了地图类型,你还可以选择它的显示方式。你可能已经熟悉传统的地球仪和平面地图视图,但这些可能并不适合你的目的。在地图视图的缩略图上方,你可以选择包括立体投影、切比雪夫投影、方位等距投影视图等非常规的地图和地球仪渲染方式。

从”视图”菜单中,你可以选择查看星星和云彩,浏览日食,以及虚拟控制时间和太阳。

通过配置Marble虚拟地球仪,你可以获得大量的选项,包括许多插件。

使用Marble规划您的下一次旅行

除了作为一个帮助您打发时间、提高地理和历史知识的虚拟玩具外,Marble还是一个实用工具,可以帮助您真正地探索世界。

“路径规划”选项卡允许您通过搜索起点和终点位置以及指定交通方式来规划旅程。您可以设置途经点,反转路线,并通过点击扳手图标来进一步定制旅行计划,选择路径提供者,以及是选择最快还是最短的路线,以及道路类型。

如果您步行旅行,路线还可以包括前面提到的人行道、小径、轨迹和隐秘通道。

Marble还可以与GPS设备配合使用。虽然外部GPS天线不再像过去那样常见,但它们仍然可用,甚至可以在树莓派上添加一个GPS帽子。如果您的Linux笔记本电脑有GPS天线,您可以选择“设置” > “面板” > “位置”来在地图上查看您的位置以及相关信息。

这些功能使得在Linux上使用Marble成为适合通过道路进行长途旅行的工具。导航在较大的屏幕上更加方便,特别是如果您远离主要高速公路。

您甚至可以记录您的GPS轨迹并分享它们。

Marble与Google Earth相比如何?

Marble具有许多功能,我们在这里无法一一列举,包括编辑地图的能力。我们发现桌面版的Google Earth(正式称为Google Earth Pro)的功能和可做的事情远不如Marble多。

默认视图是卫星视图,尽管您可以比使用Marble更远更快地放大,但它消耗了大量的CPU资源。

虽然Google Earth Pro支持图层,但没有特别有趣的地图样式或显示方式。

路线规划也让人失望,界面笨拙缓慢,视图杂乱。与我们近年来期望的Google产品的精致产品不符。

这可能是因为Google希望您使用Google Earth和Google Maps的Web版本,它有菜单栏按钮,方便您轻松使用。

总的来说,与Marble相比,Google Earth的桌面版和Web版都显得被忽视和不完整。

毫不奇怪,谷歌使用Google Maps,这相当不错,并提供了3D建筑等新颖功能,以及非常有用的Google街景,可以让您看到道路的街道级视图,如果您更喜欢谷歌的产品,也有一些提示可以帮助您像专业人士一样使用Google Maps。然而,您在OSM地图中找到的地图细节明显不足。

相关:Ubuntu 22.04 中安装谷歌地球 Google Earth 专业版/企业版客户端  https://www.linuxmi.com/ubuntu-22-04-google-earth.html

如果您喜欢徒步旅行,真正探索一个地区,而不仅仅是停留在主要、次要和第三级道路上,您将错过在Marble中用于规划路线的小路和小径。

您还必须欣赏Google Earth所需的强大计算能力。它是一个重量级应用程序,即使使用浏览器版本,也会使您的电脑风扇快速旋转。相比之下,Marble相对轻量级,不会过分占用我们的图形卡、CPU或内存。

就像它的名字所示,Marble就像一个打磨过的玻璃球,简单而有趣。

Marble 关注的是旅程,而不是目的地!

谷歌的产品往往关注于最终结果,Google Earth也不例外。与KDE的Marble相比,它缺乏冒险和探索的精神,以及大部分功能和自定义选项。

如果您有GPS天线,并且将Linux笔记本电脑带在汽车上是切实可行的,那么Marble是适合越野旅行的工具。如果您更喜欢适合越野冒险的移动应用程序,那么有很多选项可供选择。

The post Marble:适用于 Linux 的开源 Google 地球替代方案 first appeared on Linux迷.

]]>
https://www.linuxmi.com/marble-linux-google-earth.html/feed 0
探索 Python 3.12:让你的调试技能翻倍提升! https://www.linuxmi.com/python-3-12-debugging.html?utm_source=rss&utm_medium=rss&utm_campaign=python-3-12-debugging https://www.linuxmi.com/python-3-12-debugging.html#respond Fri, 16 Jun 2023 11:07:49 +0000 https://www.linuxmi.com/?p=21854 Python计划于2023年10月发布3.12版本。这个版本带来了一系列令人激动的功能和改进。它的目 …

The post 探索 Python 3.12:让你的调试技能翻倍提升! first appeared on Linux迷.

]]>
Python计划于2023年10月发布3.12版本。这个版本带来了一系列令人激动的功能和改进。它的目标是通过提供一个更高效、功能更强大的平台来改善你的编码体验,从而提升你的编程技能。

1、增强的错误信息

Python在最近的版本中不断改进其错误信息。3.11版本通过指示在行中的确切位置,提供了更准确的错误信息。

Python 3.12将这些增强功能提升到了一个新的水平,具体包括以下内容:

  • 对于缺少模块的建议(”你是否忘记导入X?”),现在包括了来自标准库的模块。
  • 对于与导入相关的常见语法错误,改进了错误建议。例如,如果你的代码中有import p from m,将会提示一个错误,询问是否打算写成from m import p。
  • 对于给定模块的导入错误,现在还包括来自导入模块的命名空间的建议。
  • NameError的建议现在在类实例中抛出时也会包含self。例如,如果名称speed未定义,错误消息将提出self.speed作为潜在的修正建议。这特别有用,因为在类实例中忽略self而导致实例变量错误是一个常见的错误源。

2、对Linux Perf Profiler的支持

广泛使用的Linux性能分析工具perf现在可以与Python 3.12程序一起使用。在过去,它只专注于跟踪Python运行时内的C级操作。

通过Python 3.12,你现在可以激活perf来收集有关Python程序的详细信息。你可以在环境级别或者在Python程序中使用sys.activate_stack_trampoline函数来激活它。

3、类型提示的改进

自从Python 3.5引入类型提示语法以来,Python的类型提示语法使得代码检查工具能够提前检测出各种错误。随着每个版本的发布,Python的类型系统不断发展,涵盖了更广泛的用例,并提供了增强的类型提示功能。

TypedDict Python 3.12引入了TypedDict作为函数关键字参数类型提示的来源。这利用了版本3.11引入的Unpack可变泛型。

下面是一个示例,演示了这个功能:

class Movie(TypedDict):
    name: str
    year: int

def foo(**kwargs: Unpack[Movie]) -> None: ...

在这种情况下,函数foo可以接收与Movie TypedDict的内容相符的名称和类型的关键字参数:类型为str的name和类型为int的year。

这个增强在为接受没有默认值的可选关键字参数的函数进行类型提示时非常有用。

类型参数语法 Python 3.12引入了一种更简洁的语法,用于指定泛型类、函数或类型别名中的类型。

考虑以下示例:

# 旧方法
from typing import TypeVar
_T = TypeVar("_T")
def func(a: _T, b: _T) -> _T:
    ...
# 新型参数法
def func[T](a: T, b: T) -> T:
    ...

使用新的语法,无需显式导入TypeVar。相反,您可以使用func[T]语法表示泛型类型引用。还可以定义类型的边界,例如指定类型必须是一组类型中的其中一个。但是,这些类型本身不能是泛型的。此语法的一个示例是func[T: (str, int)]。

4、垃圾回收

在Python 3.12中,垃圾回收(GC)机制发生了改变。以前,垃圾回收会在分配对象时运行。

然而,从Python 3.12开始,垃圾回收仅在Python字节码循环中的eval断点机制内运行。换句话说,它在执行一个字节码和下一个字节码之间运行。

此外,当CPython的信号处理程序检查机制被调用时,垃圾回收也会触发。这个调整使得在运行时外长时间运行的C扩展调用期间可以进行定期的垃圾回收。

揭开Python 3.12的面纱

Python 3.12引入了一系列令人激动的功能和改进,为您的编码体验带来革命性的变化。通过改进的错误信息、增强的类型能力、对Linux Perf Profiler的支持以及优化的垃圾回收,Python 3.12为您提供了编写高质量、高效的代码所需的工具。拥抱Python的力量,将您的编码技能提升到新的高度。

The post 探索 Python 3.12:让你的调试技能翻倍提升! first appeared on Linux迷.

]]>
https://www.linuxmi.com/python-3-12-debugging.html/feed 0
Bash vs. Python:现代 Shell 脚本编程的巅峰较量 https://www.linuxmi.com/bash-vs-python-shell-scripting.html?utm_source=rss&utm_medium=rss&utm_campaign=bash-vs-python-shell-scripting https://www.linuxmi.com/bash-vs-python-shell-scripting.html#respond Sun, 28 May 2023 00:47:38 +0000 https://www.linuxmi.com/?p=21639 一台计算机是一种只能理解特定二进制指令的数字设备。在没有操作系统的情况下,我们只能使用一些内置的固件 …

The post Bash vs. Python:现代 Shell 脚本编程的巅峰较量 first appeared on Linux迷.

]]>
一台计算机是一种只能理解特定二进制指令的数字设备。在没有操作系统的情况下,我们只能使用一些内置的固件,比如计算机中的BIOS实用程序。操作系统通过提供执行预开发程序(例如文字处理器、网络浏览器和实用工具)的方式,使计算机对人们可用。现今的大多数操作系统允许用户同时使用图形用户界面(GUI)和命令行界面(CLI)。

程序员通常喜欢使用命令行界面,因为与图形用户界面相比,使用命令行界面更贴近日常的编程活动。他们经常通过命令行界面部署软件、进行文件系统操作和配置计算机系统。命令行界面是一种高效完成所有任务的方式,但我们经常需要运行稍作修改的相同命令。

因此,命令行界面解释器提供了一种从文件中运行预先编写的命令的shell脚本概念。Bash是一种着名的传统的内置(在大多数操作系统中)命令语言,用于运行shell脚本。另一方面,许多程序员使用Python作为shell脚本的替代方案,它提供了Bash所没有的内置功能。

在本文中,我将从shell脚本的角度比较Bash和Python,并解释一些较少为人所知的shell脚本技巧,以帮助您提高使用Bash和Python进行自动化的技能。

Bash:最自然的shell脚本方式

Shell脚本的主要思想是使用shell解释器运行预先编写的命令序列。Bash将每个输入/语句都视为一个命令,并提供了一种高效的自动化方式。还记得第一次使用基于Bash的终端(也许是在大学时?)而没有阅读文档或跟随教程的经历吗?

回想起您第一次使用基于Bash的终端的经历,作者提供的截图 Bash并不作为一种通用的通用编程语言,它总是鼓励您使用其他程序。例如,您可以在上述情况下使用”expr 10 + 15″。然而,现代的Bash支持内置功能,用于满足一般编程需求,因此在某些情况下,您无需调用其他程序。

例如,它通过算术扩展功能让您执行基本的算术运算:

在终端中使用算术扩展,作者提供的截图 Bash可以原生地执行命令,无需专用的扩展语法,并为通用编程需求提供了简洁的语法。

Python: 一种现代化的方式,解决了Bash中的一个缺失功能

如果Bash可以原生执行命令并支持许多通用编程功能,那为什么程序员要使用Python进行自动化呢?看一下下面来自早期版本Python文档的历史资料:

用LaTeX编写的Python文档的早期版本

根据这份文档,Python最初的开发目标是将shell脚本与本地操作系统级编程结合起来。Bash无法原生访问操作系统级API(也称为C API)。因此,如果自动化脚本需要访问C API,程序员必须使用其他编程语言创建一个可执行文件来实现。Python通过提供一个友好的、简洁的语言并具备C API访问权限来解决了这个问题,甚至还提供了一种跨平台的访问操作系统级API的方式。

Python从通用编程的角度评估源代码,因此它不能原生执行其他程序,但提供了一个开发者友好的子进程API。

我们已经对这两种语言的目标和基础知识进行了检查。现在让我们开始进行比较吧!

Bash vs. Python: 哪个更适合自动化?

程序员编写各种各样的shell脚本。有时候,他们编写的shell脚本执行一些POSIX命令(例如mv,cp等)。在某些情况下,他们需要在shell脚本中包含数据处理和操作系统级操作。此外,有时候他们需要编写跨平台的自动化脚本。

和几乎所有现代编程语言的比较总结一样,这里没有赢家——最佳的shell脚本选项取决于我们的开发场景。

Bash适用于以下情况:

  • 自动化涉及较少数据处理的POSIX命令行操作,例如系统管理脚本
  • 通过其他CLI程序执行配置、处理或其他操作的shell脚本,例如通过CLI工具编写Git提交信息和进行应用部署
  • 如果您希望脚本在Unix系统上具有更好的可移植性,Bash是一个不错的选择,因为Bash解释器的预安装范围比Python更广泛

Python适用于以下情况:

  • 自动化涉及更多数据处理(算法操作)和访问低级API,而不仅仅是执行其他CLI程序
  • 编写跨平台自动化脚本,在GNU/Linux、Windows、macOS和其他Python支持的操作系统上执行命令、使用低级API并进行通用数据处理。以BuildZri项目为例。

总的来说,Bash是使用其他命令行程序编写自动化脚本的最简洁、自然、本地化和类似终端的方式。另一方面,Python是一种跨平台的通用编程语言,您可以将其作为Bash的替代方案,用于编写具有低级操作系统API访问和数据处理功能的shell脚本。

Bash和Python一起使用

Bash和Python之间并不存在极端的竞争,因为它们是两种不同的编程语言类型——Bash是一种命令语言,而Python是一种通用编程语言。我们可以根据需求选择其中一种选项,或者同时使用两种语言。

假设您使用bc来执行两个小数的加法,代码如下:

#!/bin/bash
# Linux迷 www.linuxmi.com

sum=$(bc <<< "1.65 + 2.91")
echo $sum

您也可以使用Python完成相同的任务,代码如下:

#!/bin/bash

sum=$(python3 <<< “print(1.5 + 2.51)”) echo $sum

与许多程序员在Python脚本中所做的一样,使用Bash在Python中也是比使用许多第三方Python包更方便的选择。例如,看看下面的脚本如何查找Gedit程序的进程标识符:

#!/usr/bin/env python3
# Linux迷 www.linuxmi.com

import subprocess

gedit_pid = subprocess \
              .getoutput("ps -ef | grep gedit | head -1 | awk '{print $2}'") \
              .strip()
print(gedit_pid)

解决现代自动化中的Bash和Python问题

正如我们讨论过的,Bash和Python在现代自动化需求中都存在一些缺点。使用Bash编写具有操作系统级API访问和复杂数据处理的shell脚本很困难。而使用Python的subprocess API执行最小化的命令行程序不具备与Shell语法相似的语法特性。

如果您需要在Bash中使用C API,可以使用ctypes.sh Bash扩展:https://github.com/taviso/ctypes.sh

甚至还有一个使用ctypes.sh外部函数接口以Bash编写的名为httpd.sh的HTTP Web服务器。

pysh 项目提供了一种在Python脚本中使用”>”字符执行Bash语句的简单方法,如下面的代码片段所示:

for i in xrange(100):
   index = "%02d" % i
   > mv from$index.txt to$index.txt

zxpy项目(受Google的zx启发)可以让您以以下方式在Python中高效执行命令行操作:

#! /usr/bin/env zxpy
# Linux迷 www.linuxmi.com

~'echo Hello world!Linux迷 www.linuxmi.com'

file_count = ~'ls -1 | wc -l'
print("file count is:", file_count)

总结

Shell脚本的概念始于20世纪70年代左右的Unix环境中的历史Thompson shell。传统Shell脚本的想法是从文件中执行命令行操作,用于自动化目的。现代DevOps运动通过在自动化脚本中包含RESTful API调用、数据处理和其他与DevOps相关的操作,扩展了传统的Shell脚本概念。

在现代自动化中,使用Bash作为Shell脚本选项并不过时,因为它允许您以本地方式执行命令,无需单独的子进程API(它已经内置)。如果程序员在自动化中需要执行的操作超出了本地命令行操作,他们通常会使用Python作为现代的Bash替代方案。

The post Bash vs. Python:现代 Shell 脚本编程的巅峰较量 first appeared on Linux迷.

]]>
https://www.linuxmi.com/bash-vs-python-shell-scripting.html/feed 0
10 个 Python Itertools,让你的代码如虎添翼 https://www.linuxmi.com/python-itertools.html?utm_source=rss&utm_medium=rss&utm_campaign=python-itertools https://www.linuxmi.com/python-itertools.html#respond Tue, 23 May 2023 14:10:26 +0000 https://www.linuxmi.com/?p=21595 Python的美丽在于它的简洁性。 不仅因为Python的语法优雅,还因为它有许多设计良好的内置模块 …

The post 10 个 Python Itertools,让你的代码如虎添翼 first appeared on Linux迷.

]]>
Python的美丽在于它的简洁性。

不仅因为Python的语法优雅,还因为它有许多设计良好的内置模块,能够高效地实现常见功能。

itertools模块就是一个很好的例子,它为我们提供了许多强大的工具,可以在更短的代码中操作Python的可迭代对象。

用更少的代码实现更多的功能,这就是你可以从itertools模块中获得的好处。让我们从本文中了解一下。

推荐:在 Python 中使用正则表达式的 9 个实例 https://www.linuxmi.com/python-regular-expressions.html

1、itertools.product(): 避免嵌套循环的巧妙方法

当程序变得越来越复杂时,你可能需要编写嵌套循环。同时,你的Python代码将变得丑陋和难以阅读:

list_a = [1, 2020, 70]
list_b = [2, 4, 7, 2000]
list_c = [3, 70, 7]

for a in list_a:
    for b in list_b:
        for c in list_c:
            if a + b + c == 2077:
                print(a, b, c)
# 70 2000 7

如何使上述代码再次具有 Python 风格?

那 itertools.product() 函数就是你的朋友:

from itertools import product

list_a = [1, 2020, 70]
list_b = [2, 4, 7, 2000]
list_c = [3, 70, 7]

for a, b, c in product(list_a, list_b, list_c):
    if a + b + c == 2077:
        print(a, b, c)
# 70 2000 7

如上所示,它返回输入可迭代对象的笛卡尔积,帮助我们将三个嵌套的for循环合并为一个。

2、itertools.compress(): 过滤数据的便捷方式

我们可以通过一个或多个循环来筛选列表中的项。

但有时候,我们可能不需要编写任何循环。因为有一个名为itertools.compress()的函数。

itertools.compress()函数返回一个迭代器,根据相应的布尔掩码对可迭代对象进行过滤。

例如,以下代码使用itertools.compress()函数选择出真正的领导者:

import itertools
leaders = ['Yang', 'Elon', 'Tim', 'Tom', 'Mark']
selector = [1, 1, 0, 0, 0]
print(list(itertools.compress(leaders, selector)))
# ['Yang', 'Elon']

第二个参数selector作为掩码起作用,我们也可以这样定义它:

selector = [True, True, False, False, False]

3、itertools.groupby(): 对可迭代对象进行分组

itertools.groupby()函数是一种方便的方式,用于将可迭代对象中相邻的重复项进行分组。

例如,我们可以将一个长字符串进行分组,如下所示:

from itertools import groupby

for key, group in groupby('LinnuxmiMi'):
    print(key, list(group))

此外,我们可以利用它的第二个参数告诉groupby()函数如何确定两个项是否相同:

from itertools import groupby

for key, group in groupby('LinnuxmiMi', lambda x: x.upper()):
    print(key, list(group))

4、itertools.combinations(): 从可迭代对象中获取给定长度的所有组合

对于初学者来说,编写一个无 bug 的函数来获取列表的所有可能组合可能需要一些时间。

事实上,如果她了解 itertools.combinations() 函数,她可以很容易地实现:

import itertools

author = ['L', 'i', 'n', 'u', 'x']

result = itertools.combinations(author, 2)

for a in result:
    print(a)

如上所示,itertools.combinations()函数有两个参数,一个是原始可迭代对象,另一个是函数生成的子序列的长度。

5、itertools.permutations(): 从可迭代对象中获取给定长度的所有排列

既然有一个函数可以获取所有组合,当然也有另一个名为itertools.permutations的函数来获取所有可能的排列:

import itertools

author = ['Y', 'a', 'n', 'g']

result = itertools.permutations(author, 2)

for x in result:
    print(x)

# ('Y', 'a')
# ('Y', 'n')
# ('Y', 'g')
# ('a', 'Y')
# ('a', 'n')
# ('a', 'g')
# ('n', 'Y')
# ('n', 'a')
# ('n', 'g')
# ('g', 'Y')
# ('g', 'a')
# ('g', 'n')

如上所示,itertools.permutations()函数的用法与itertools.combinations()类似。唯一的区别在于它们的结果。

6、itertools.accumulate(): 从可迭代对象生成累积的项

基于可迭代对象获取一系列累积值是一种常见需求。借助itertools.accumulate()函数的帮助,我们无需编写任何循环即可实现。

import itertools
import operator

nums = [1, 2, 3, 4, 5]
print(list(itertools.accumulate(nums, operator.mul)))
# [1, 2, 6, 24, 120]

如果我们不想使用operator.mul,上述程序可以改写如下:

import itertools

nums = [1, 2, 3, 4, 5]
print(list(itertools.accumulate(nums, lambda a, b: a * b)))
# [1, 2, 6, 24, 120]

7、itertools.repeat(), itertools.cycle(), itertools.count(): 生成无限迭代对象

在某些情况下,我们需要获得无限迭代。有 3 个有用的功能:

itertools.repeat():重复生成相同的项

例如,我们可以得到三个相同的“Yang”,如下所示:

import itertools
print(list(itertools.repeat('Yang', 3)))
# ['Yang', 'Yang', 'Yang']

itertools.cycle(): 通过循环获得无限迭代器

 itertools.cycle函数将不会停止,直到我们跳出循环:

import itertools

count = 0

for c in itertools.cycle('Yang'):
    if count >= 12:
        break
    else:
        print(c, end=',')
        count += 1
# Y,a,n,g,Y,a,n,g,Y,a,n,g,

itertools.count(): 生成一个无限的数字序列 如果我们只需要数字,可以使用itertools.count函数:

import itertools

for i in itertools.count(0, 2):
    if i == 20:
        break
    else:
        print(i, end=" ")
# 0 2 4 6 8 10 12 14 16 18

如上所示,它的第一个参数是起始数字,第二个参数是步长。

8、itertools.pairwise(): 轻松获取成对的元组

自从Python 3.10版本开始,itertools模块新增了一个名为pairwise的函数。它是一个简洁而方便的工具,用于从可迭代对象中生成连续的重叠对。

import itertools

letters = ['a', 'b', 'c', 'd', 'e']

result = itertools.pairwise(letters)

print(list(result))
# [('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'e')]

9、itertools.takewhile(): 以不同的方式过滤元素

itertools.takewhile()返回一个迭代器,只要给定的谓词函数评估为True,就会从可迭代对象中生成元素。

import itertools

nums = [1, 61, 7, 9, 2077]

print(list(itertools.takewhile(lambda x: x < 100, nums)))
# [1, 61, 7, 9]

该函数与内置的filter()函数不同。

filter函数将遍历整个列表:

nums = [1, 61, 7, 9, 2077]

print(list(filter(lambda x: x < 10, nums)))
# [1, 7, 9]

然而,itertools.takewhile函数如其名称所示,当评估函数为False时会停止迭代:

import itertools

nums = [1, 61, 7, 9, 2077]

print(list(itertools.takewhile(lambda x: x < 10, nums)))
# [1]

10、itertools.dropwhile(): itertools.takewhile的反向操作

这个函数似乎是前面那个函数的相反思路。

itertools.takewhile()函数在谓词函数为True时返回可迭代对象的元素,而itertools.dropwhile()函数在谓词函数为True时丢弃可迭代对象的元素,然后返回剩下的元素。

import itertools

nums = [1, 61, 7, 9, 2077]

print(list(itertools.dropwhile(lambda x: x < 100, nums)))
# [2077]

感谢阅读。❤️

如果你喜欢,请关注我,以享受更多关于编程和技术的文章。

The post 10 个 Python Itertools,让你的代码如虎添翼 first appeared on Linux迷.

]]>
https://www.linuxmi.com/python-itertools.html/feed 0