分类 软件开发 下的文章

无论你使用的是 while 循环、do/while 循环,还是无限循环,了解循环的工作原理对 Java 编程至关重要。

只要某些预定的条件为真,一个 while 循环就会执行一组任务。这被认为是一个控制结构,可以指导程序的流程。它是一种你可以通过定义一个条件来告诉你的代码要做什么的方法,它可以测试它,并根据它发现的情况采取行动。Java 中的两种 while 循环是 whiledo/while

Java while 循环

while 循环的目的是对数据进行迭代,直到某个条件得到满足。要创建一个 while 循环,你需要提供一个可以测试的条件,然后是你想要运行的代码。Java 有几个内置的测试函数,其中最简单的是数学运算符(<, >, ==, 等等):

package com.opensource.example;

public class Example {
  public static void main(String[] args) {

  int count = 0;
  while (count < 5) {
    System.out.printf("%d ", count);
    count++;
    }
  }
}

在这个简单的例子中,条件是变量 count 小于 5。因为 count 被实例化为 0,然后在 while 循环的代码中增加 1,所以程序总共迭代了 5 次:

$ java ./while.java
0 1 2 3 4

在它进行第六次迭代之前,条件不再是真的,所以循环结束。

while 循环的条件语句是至关重要的。弄错了可能意味着你的循环永远不会执行。例如,假设你把 count == 5 作为条件:

while (count == 5) {
    System.out.printf("%d ", count);
    count++;

当你运行这段代码时,它的构建和运行都很成功,但什么也没有发生:

$ java ./while.java
$

循环被跳过了,因为 count 被设置为 0,而且在第一次遇到 while 循环的时候,它还是 0。循环从未开始,count 也从未被递增。

与此相反的是,当一个条件开始为真,并且永远不会为假时,这将导致一个无限循环。

Java do while 循环

while 循环相似,do/while 循环在每次迭代结束时测试条件,而不是在开始时测试条件。有了这个循环,循环中的代码至少运行一次,因为没有进入的入口,只有退出的出口:

package com.opensource.example;

public class Example {
  public static void main(String[] args) {

  int count = 9;
  do {
      System.out.printf("%d ", count);
      count++;
    } while(count == 5);
  }
}

在这个示例代码中,count 被设置为 9。循环重复的条件是 count 等于 5,但是 9 不等于 5。不过,这个检查要到第一次迭代结束时才进行:

$ java ./do.java
9

Java 无限循环

无限循环,正如它的名字所示,永远不会结束。有时它们是被错误地创建的,但无限循环确实有一个有效的场景。有时你想让一个进程无限地继续下去(在功能上是无限的,因为你不能保证你需要它什么时候停止),因此你可能会把你的条件设置为不可能满足的东西。

假设你写了一个应用程序,在僵尸天启期间计算留在你附近的僵尸的数量。为了模拟需要多少个循环才能达到 0 个僵尸的不确定性,我的演示代码从操作系统中检索了一个时间戳,并将计数器(c)的值设置为从该时间戳得出的某个数字。因为这是一个简单的例子,你不会真的想陷入一个无限循环,这段代码倒数到 0,并使用 break 函数来强制结束循环:

package com.opensource.example;

public class Example {
  public static void main(String[] args) {

  long myTime = System.currentTimeMillis();

  int c;

  if ( myTime%2 == 0 ) {
      c = 128;
  } else {
      c = 1024;
  }

  while(true) {
    System.out.printf("%d Zombies\n", c);

    // break for convenience
    if ( c <= 0 ) { break; }
    c--;
    }
  }
}

你可能要运行几次才能触发不同的僵尸总数,但有时你的程序会迭代 128 次,有时会迭代 1024 次:

$ java ./zcount.java
1024 Zombies
1023 Zombies
[...]
0 Zombies

你能说出为什么循环的终点是 0 而不是 -1 吗?

Java 循环

循环使你能够控制程序的执行流程。迭代在编程中很常见,无论你使用 while 循环、do/while 循环还是无限循环,了解循环的工作原理都是至关重要的。


via: https://opensource.com/article/23/1/java-loops

作者:Seth Kenlon 选题:lkxed 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

只要你遵循这些通用流程,代码评审并不可怕。

你是否需要在你还没有完全理解整个项目时就对代码进行评审?抑或你避开了评审,以免让你看起来不知道如何进行。

本篇文章想要告诉你一个更好的方法。 代码评审 code review 并不需要你知道所有事情。实际上,就我个人经验而言,这种情况非常普遍。

我还记得作为实习生加入 红帽 Red Hat 的时候,被要求参与代码评审。我们当时采取的是 +1 或 -1 的投票系统,而我在一开始的时候常常踌躇于该如何评审。我发现我会问自己,如果我对于一处改动给予了 +1,而别人却投了 -1,我是不是看起来很蠢?

如果你对一处改动投了 +1,而别人投了 -1,这又意味着什么呢?答案是不意味任何事!你可能只是漏掉了一处别人注意到的细节。这不意味着世界末日。这也是为什么我们会用投票系统。正如同所有开源项目一样,代码合并是一项协同工作。

最近,我接到了太多的代码评审工作,以至于我几乎做不过来。我同时也注意到,参与评审的贡献者数量正在稳步减少。

出于这个原因,我想要写一篇文章阐述我对代码评审的个人观点。在这篇文章里,我会分享一些诀窍与技巧。我将会向你展示几个用来问自己的问题,以及在评审代码时需要注意的一些地方。

代码评审的目的是什么?

你是否曾写过一个非常简单的补丁?你认为它是如此微不足道,不需要审查。或许你直接就合并了它。直到晚些时候,你意识到你犯了个错误,一个明显的或是愚蠢的错误,比如错误的缩进,比如几行重复的代码而不是调用函数(是的,这些都是经验之谈!)。

如果有其他人来审查代码,就会发现这些东西。

代码评审的一个目的便是为你带来一双新的眼睛,从新的视角看待你要尝试解决的问题。这种新的背景也正是为什么代码评审至关重要。

你可能认为你必须是一个语言专家,才能审查别人的代码、项目,或两者。让我来告诉你一个所有代码评审者都想跟你说的秘密吧:大错特错!你并不需要完全理解该项目或者编程语言,就可以为一个改动提供全新的视角。下面,我将向你展示代码评审的通用流程。

代码评审的通用流程

这是我的代码评审流程,拆分成了几个要点。这个流程包含了我会问自己的一些问题,以帮助我专注于代码的变化以及其后果。你不需要严格依照这个顺序来进行评审。如果有任何原因导致你无法执行其中的某一步,跳过那一步就好。

1、理解改动,它想要解决的问题,以及为什么要这么做

为什么需要改动的解释以及任何相关背景都应该被放在 提交 commit 信息里。如果没有,请要求提供,并请投 -1 直到相关信息被提供。

改动想解决的问题需要被解决吗?它是项目应当关注的问题,还是与项目完全无关?

2、你会如何实现解决方案?它会不一样吗?

在这个时候,你应该已经知道代码改动是为了什么。换做是你会怎么做?在进一步对改动进行细节评审前,先思考这个问题。如果你想出了一个不一样的解决方案,并且你认为你的方案更好,在评审中提出来。你不需要投 -1;去问问作者为什么没有往那个方向走,看看这次讨论会把你们带向何方。

3、运行有改动和没有改动的代码

我通常会在代码中设置几个断点,运行代码并检查新代码是如何与其余部分互动的。

如果你无法运行整个代码,试着将带有新代码的函数复制到一个新的本地文件,模拟输入数据,然后运行。这在你不知道怎么运行整个项目,或者无法接触到运行所需的特殊环境时很有帮助。

4、新代码会破坏任何东西吗?

我是说,任何东西。想一想可能的后果。

以一个新的命令行选项为例,它会总是被目标所接受吗?

是否存在这样一种情况,使得新选项无法被接受或是会与其他东西起冲突?

或许新代码是导入了新的东西。那么这个新的库,以及可能的新的依赖关系,能够在老版本或者项目的运行系统中被找到吗?

安全方面呢?新的依赖足够安全吗?你至少可以在网上快速地搜索一下。还有,注意一下控制台日志里的警告。有的时候在同一个库里也可以找到更安全的函数。

5、新代码是否有效?

你刚刚确认了被提出的解决方案大概是正确的。现在该检查代码本身了。你需要关注代码的有效性和必要性。

检查新代码的风格。它与项目的代码风格相匹配吗?任何开源项目都(应该)有一份文档告知(新)贡献者项目所遵循的风格和优秀实践。

比如说,OpenStack 社区的所有项目都有一份 HACKING.rst 文件。你经常也能找到一份新贡献者指南包含所有必须知道的信息。

6、确认所有新增的变量和导入都被使用

你正在评审的代码常常已经过多次迭代,有的时候代码的最终版本与初始版已迥然不同。所以我们很容易忘记一些在历史版本中加入的变量与引用。自动化检测通常会用到 lint 工具,类似 Python 中的 flake8。

(LCTT 译注:lint 指编程中用来发现代码潜在错误和约束代码风格的工具,起源于 C 语言编程中的静态分析工具 lint。“lint” 本意为衣服上积累的绒毛与灰尘,“lint” 的取名寓意则在于捕捉编程时产生的“绒毛与灰尘”)

(LCTT 校注:我建议,“Lint” 工具可以翻译为 “代码清理” 或 “代码清洁” 工具。)

你可以在不声明新变量的情况下重写代码吗?通常情况下你可以,但问题是这样是否更好。这会带来什么益处吗?我们的目标不是要创造尽可能多的单行代码,而是写出高效且易读的代码。

7、新的函数和方法是否必要?

项目里的别的地方是否存在可以被复用的功能类似的函数?确保避免重新发明轮子以及重新实现已经被定义的逻辑永远都是值得的。

8、有单元测试吗?

如果补丁增加了新的函数或者在函数内添加了新的逻辑,它也应该附带对应的单元测试。新函数的作者总是比别人更适合写该函数的单元测试。

9. 验证重构

如果这次提交对现有代码进行了重构(它可能重命名了某个变量,或者是改变了的变量的作用域,或者是通过加减参数来改变函数的足迹,又或者是删去了某个东西),问一问你自己:

  • 这个可以被删除吗?它会影响到稳定分支吗?
  • 所有出现的地方都删掉了吗?

你可以利用 grep 命令 来查找。你不会相信有多少次我投 -1 就是因为这个。这是一个任何人都会犯的简单错误,也正因如此任何人都可以发现它。

提交的所有者很容易忽略这些事情,这完全可以理解。我也犯过很多次这种错误。我最终发现问题的根源在于我太急于提出评审,以至于我忘记了对仓库进行整体检查。

除了对项目仓库的检查外,检查其他代码用户也十分必要。如果有别的项目导入了这个项目,它们可能也需要进行重构。在 OpenStack 社区中,我们有对应的工具来查询别的社区项目。

10、项目文档是否需要做出更改?

你可以再一次使用 grep 命令 来检查在项目文档中是否提到了相关的代码改动。用常识来判断这次改动是否需要被收入文档以告知最终用户,还是只是一个不会影响用户体验的内部变化。

额外提示:考虑周到

当你在评审完新代码后提出建议或评论时,要考虑周到,反馈准确,描述详尽。如果有你不理解的地方就发出提问。如果你认为代码存在错误,解释你的理由。记住,如果作者不知道什么地方出了问题,他们就无法修复它。

最后几句

唯一的坏评审是没有评审。通过评审和投票,你提供了你的观点并为此投票。没有人指望你来做出最终决定(除非你是核心维护者),但是投票系统允许你提供你的观点和意见。相信我,补丁所有者会很高兴你这么做了的。

你能想到别的要点来给出好的评审吗?你是否有我不知道的特殊技巧?在评论中分享它们吧!


via: https://opensource.com/article/22/10/code-review

作者:Martin Kopec 选题:lkxed 译者:yzuowei 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

Pandas 是一个十分流行的 Python 第三方库。本文介绍了 Pandas 库中的一些特性和函数,并且我们鼓励读者亲手使用 Pandas 库,来解决实际的业务问题。

Pandas 为 Python 中数据分析提供了基础和高级的构建组件。Pandas 库是用于数据分析与数据操作的最强大和最灵活的开源分析工具之一,并且它还提供了用于建模和操作表格数据(以行和列组织的数据)的数据结构

Pandas 库有两个主要的数据结构:第一个是 “ 系列 Series ”,该数据结构能够很方便地从 Python 数组或字典中按位置或指定的索引名称来检索数据;第二个是“ 数据帧 DataFrames ”,该数据结构将数据存储在行和列中。列可以通过列名访问,行通过索引访问。列可以有不同类型的数据,包括列表、字典、序列、数据帧、NumPy 数组等。

Pandas 库可以处理各种文件格式

有各种各样的文件格式。用于数据分析的工具必须能够提供处理各种文件格式的方法。

Pandas 可以读取各种文件格式,例如 CSV 文件、JSON 文件、XML 文件、Parquet 文件、SQL 文件,详见下表。

写入读取
CSV 文件to_csv 函数read_csv 函数
JSON 文件to_json 函数read_json 函数
Parquet 文件to_parquet 函数read_parquet 函数
SQL 文件to_sql 函数read_sql 函数,read_sql_query 函数,read_sql_table 函数
XML 文件to_xml 函数read_xml 函数

使用 Pandas 进行数据清理

在现实场景中,很多数据集存在数据缺失、数据格式错误、错误数据或重复数据的情况,如果要对使数据分析更加准确,就需要对这些没有用的数据进行处理。此外,数据还会有需要 屏蔽 mask 的敏感和机密信息。接下来,Pandas 提供了清理、丢弃、替换、屏蔽等方法,来处理这些坏数据。

Pandas 清洗空值:

a. 空行可以使用 df.dropna(inplace=True) 方法来删除。

b. 空值可以使用 df.fillna(<value>, inplace=True) 方法来替换。还可以指定某一个列来替换该列的空数据。

Pandas 屏蔽数据:

c. 要屏蔽所有不满足条件 my_list.where(my_list < 5) 的敏感数据的值,可以使用 my_list.mask(my_list < 5)

Pandas 清洗重复数据:

d. 要删除重复数据,可以使用 drop_duplicates() 方法:

df.drop_duplicates(‘<column>’, keep = False)
df.drop_duplicates(‘<column>’, keep = ‘first’)
df.drop_duplicates(‘<column>’, keep = ‘last’)

使用 Pandas 进行数据分析

下面的表格列出了 Pandas 中进行数据分析的各种函数,以及其语法。(请注意:df 代表一个 数据帧 DataFrame 数据结构的实例。)

语法描述
df.head(x)head() 函数用于读取前面的 x 行,如果不填参数 x,默认返回 5 行
df.tail(x)tail() 函数用于读取尾部的 x 行,如果不填参数 x ,默认返回最后 5 行,空行各个字段的值返回 NaN
loc(x:y)Loc 函数返回指定行的数据,也可以对数据进行切片
groupby('<column>')对指定列的数据进行分组
df['column'].sum()计算指定列数据的总和
df['column']. mean()计算指定列数据的算术平均值
df['column'].min()计算指定列数据的最小值
df['column'].max()计算指定列数据的最大值
df.sort_values(['column'])在指定列上根据数值进行排序,默认升序
df.size返回元素的个数,即为行数 * 列数
df.describe返回对各列的统计汇总
pd.crosstab(df['column1'], df['column2'], margins = True)创建 column1column2 的交叉表
df.duplicated([column1, 'column2'])根据 column1column2 中的重复值,返回 TrueFalse

Pandas 的优点

  • 支持多索引(层次索引),方便分析多维数据。
  • 支持数据透视表的创建,堆栈和取消堆栈操作。
  • 可以使用 Pandas 处理有限值的分类数据。
  • 支持分组和聚合运算。
  • 可以禁用排序。
  • 支持行级过滤(获取满足过滤条件的行)和列级过滤(只选择需要的列)。
  • 有助于重塑数据集(数组的维度变换)。还可以转置数组的值,并转换为列表。当你使用 Python 处理数据时,可以将 Pandas 数据帧转换为多维 NumPy 数组。
  • 支持面向标签的数据切片。

Pandas 的不足

Pandas 的代码和语法与 Python 不同,所以人们需要额外再学习 Pandas。此外,相较于 Pandas,像三维数据这样的高维数据会在 NumPy 等其他库有更好的处理。

总结

Pandas 能够大幅提升数据分析的效率。它与其他库的兼容性使它在其他 Python 库中都能有效地使用。


via: https://www.opensourceforu.com/2022/08/pandas-the-popular-python-library-for-data-analysis-and-data-science/

作者:Phani Kiran 选题:lkxed 译者:chai001125 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

InfluxData 是一个开源的时间序列数据库平台。下面介绍了它是如何被用于边缘应用案例的。

收集到的随时间变化的数据称为时间序列数据。今天,它已经成为每个行业和生态系统的一部分。它是不断增长的物联网行业的一大组成部分,将成为人们日常生活的重要部分。但时间序列数据及其需求很难处理。这是因为没有专门为处理时间序列数据而构建的工具。在这篇文章中,我将详细介绍这些问题,以及过去 10 年来 InfluxData 如何解决这些问题。

InfluxData

InfluxData 是一个开源的时间序列数据库平台。你可能通过 InfluxDB 了解该公司,但你可能不知道它专门从事时间序列数据库开发。这很重要,因为在管理时间序列数据时,你要处理两个问题:存储生命周期和查询。

在存储生命周期中,开发人员通常首先收集和分析非常详细的数据。但开发人员希望存储较小的、降低采样率的数据集,以描述其趋势,而不占用太多的存储空间。

查询数据库时,你不希望基于 ID 查询数据,而是希望基于时间范围进行查询。使用时间序列数据最常见的一件事是在一段时间内对其进行汇总。在典型的关系型数据库中存储数据时,这种查询是很慢的,这种数据库使用行和列来描述不同数据点的关系。专门为处理时间序列数据而设计的数据库可以更快地处理这类查询。InfluxDB 有自己的内置查询语言:Flux,这是专门为查询时间序列数据集而构建的。

Telegraf 如何工作的图像

数据采集

数据采集和数据处理都有一些很棒的工具。InfluxData 有 12 个以上的客户端库,允许你使用自己选择的编程语言编写和查询数据。这是自定义用法的一个很好的工具。开源摄取代理 Telegraf 包括 300 多个输入和输出插件。如果你是一个开发者,你也可以贡献自己的插件。

InfluxDB 还可以接受上传小体积历史数据集的 CSV 文件,以及大数据集的批量导入。

import math
bicycles3 = from(bucket: "smartcity")
    |> range(start:2021-03-01T00:00:00z, stop: 2021-04-01T00:00:00z)
    |> filter(fn: (r) => r._measurement == "city_IoT")
    |> filter(fn: (r) => r._field == "counter")
    |> filter(fn: (r) => r.source == "bicycle")
    |> filter(fn: (r) => r.neighborhood_id == "3")
    |> aggregateWindow(every: 1h, fn: mean, createEmpty:false)
bicycles4 = from(bucket: "smartcity")
    |> range(start:2021-03-01T00:00:00z, stop: 2021-04-01T00:00:00z)
    |> filter(fn: (r) => r._measurement == "city_IoT")
    |> filter(fn: (r) => r._field == "counter")
    |> filter(fn: (r) => r.source == "bicycle")
    |> filter(fn: (r) => r.neighborhood_id == "4")
    |> aggregateWindow(every: 1h, fn: mean, createEmpty:false)join(tables: {neighborhood_3: bicycles3, neighborhood_4: bicycles4}, on ["_time"], method: "inner")
    |> keep(columns: ["_time", "_value_neighborhood_3","_value_neighborhood_4"])
    |> map(fn: (r) => ({
        r with
        difference_value : math.abs(x: (r._value_neighborhood_3 - r._value_neighborhood_4))
    }))

Flux

Flux 是我们的内部查询语言,从零开始建立,用于处理时间序列数据。它也是我们一些工具的基础动力,包括 任务 task 警报 alert 通知 notification 。要剖析上面的 Flux 查询,需要定义一些东西。首先,“ bucket ”就是我们所说的数据库。你可以配置存储桶,然后将数据流添加到其中。查询会调用 smartcity 存储桶,其范围为特定的一天(准确地说是 24 小时)。你可以从存储桶中获取所有数据,但大多数用户都包含一个数据范围。这是你能做的最基本的 Flux 查询。

接下来,我添加过滤器,将数据过滤到更精确、更易于管理的地方。例如,我过滤分配给 id 为 3 的社区中的自行车数量。从那里,我使用 aggregateWindow 获取每小时的平均值。这意味着我希望收到一个包含 24 列的表,每小时一列。我也对 id 为 4 的社区进行同样的查询。最后,我将这两张表相叠加,得出这两个社区自行车使用量的差异。

如果你想知道什么时候是交通高峰,这是不错的选择。显然,这只是 Flux 查询功能的一个小例子。但它提供了一个很好的例子,使用了 Flux 附带的一些工具。我还有很多的数据分析和统计功能。但对于这一点,我建议查看 Flux 文档。

import "influxdata/influxdb/tasks"
option task = {name: PB_downsample, every: 1h, offset: 10s}
from(bucket: "plantbuddy")
    |>range(start: tasks.lastSuccess(orTime: -task.every))
    |>filter(fn: (r) => r["_measurement"] == "sensor_data")
    |>aggregateWindow(every: 10m, fn:last, createEmpty:false)
    |>yield(name: "last")
    |>to(bucket: "downsampled")

任务

InfluxDB 任务 task 是一个定时 Flux 脚本,它接收输入数据流并以某种方式修改或分析它。然后,它将修改后的数据存储在新的存储桶中或执行其他操作。将较小的数据集存储到新的存储桶中,称为“ 降采样 downsampling ”,这是数据库的核心功能,也是时间序列数据生命周期的核心部分。

你可以在当前任务示例中看到,我已经对数据进行了降采样。我得到每 10 分钟增量的最后一个值,并将该值存储在降采样桶中。原始数据集在这 10 分钟内可能有数千个数据点,但现在降采样桶只有 60 个新值。需要注意的一点是,我还使用了范围内的 lastSuccess 函数。这会告诉 InfluxDB 从上次成功运行的时间开始运行此任务,以防它在过去 2 小时内失败,在这种情况下,它可以追溯 3 个小时内的最后一次成功运行。这对于内置错误处理非常有用。

检查和警报通知系统的图像

检查和警报

InfluxDB 包含一个 警报 Alert 检查 Check 通知 notification 系统。这个系统非常简单直白。首先进行检查,定期查看数据以查找你定义的异常。通常,这是用阈值定义的。例如,任何低于 32°F 的温度值都被指定为“WARN”值,高于 32°F 都被分配为“OK”值,低于 0°F 都被赋予“CRITICAL”值。从那开始,你的检查可以按你认为必要的频率运行。你的检查以及每个检查的当前状态都有历史记录。在不需要的时候,你不需要设置通知。你可以根据需要参考你的警报历史记录。

许多人选择设置通知。为此,你需要定义一个 通知端点 notification endpoint 。例如,聊天应用程序可以进行 HTTP 调用以接收通知。然后你定义何时接收通知,例如,你可以每小时运行一次检查。你可以每 24 小时运行一次通知。你可以让通知响应值更改,例如,“WARN”更改为“CRITICAL”,或者当值为“CRITICAL”时,无论如何都从“OK”更改为“WARN”。这是一个高度可定制的系统。从这个系统创建的 Flux 代码也可以编辑。

新 Edge 功能的图像

边缘

最后,我想把所有的核心功能放在一起,包括最近发布的一个非常特别的新功能。“Edge to cloud” 是一个非常强大的工具,允许你运行开源 InfluxDB,并在出现连接问题时在本地存储数据。连接修复后,它会将数据流传输到 InfluxData 云平台。

这对于边缘设备和重要数据非常重要,因为任何数据丢失都是有害的。你定义一个要复制到云的存储桶,然后该存储桶有一个磁盘支持的队列来本地存储数据。然后定义云存储桶应该复制到的内容。在连接到云端之前,数据都存储在本地。

InfluxDB 和物联网边缘

假设你有一个项目,你想使用连接到植物上的物联网传感器 监测家里植物的健康状况。该项目是使用你的笔记本电脑作为边缘设备设置的。当你的笔记本电脑合上或关闭时,它会在本地存储数据,然后在重新连接时将数据流传到我的云存储桶。

图片展示了 Plant buddy 的工作方式

需要注意的一点是,在将数据存储到复制桶之前,这会对本地设备上的数据进行降采样。你的植物传感器每秒提供一个数据点。但它将数据压缩为一分钟的平均数,因此存储的数据更少了。在云账户中,你可以添加一些警报和通知,让你知道植物的水分何时低于某个水平,需要浇水。也可以在网站上使用视觉效果来告诉用户植物的健康状况。

数据库是许多应用程序的主干。在像 InfluxDB 的时间序列数据库平台中使用带有时间戳的数据可以节省开发人员的时间,并使他们能够访问各种工具和服务。InfluxDB 的维护者喜欢看到人们在我们的开源社区中构建什么,所以请与我们联系,并与其他人共享你的项目和代码!


via: https://opensource.com/article/23/1/time-series-data-edge-open-source-tools

作者:Zoe Steinkamp 选题:lkxed 译者:ZhangZhanhaoxiang 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

这个简单的指南演示了如何在 Windows 上下载和安装 Python。

这篇文章是用最新的 Python 3.11 稳定版测试的。

在学习如何在 Windows 上安装 Python 之前,你可能想看看如何在 Linux 发行版(如 Ubuntu)上轻松安装 Python。如果你打算成为一名开发者,最好在 Linux 中尝试 Python。那么,你可能想看看 如何在 Windows 之外安装 Linux(如 Ubuntu)

Python 是一种流行的通用编程语言,在过去十年中成为开发者的选择。而且它的受欢迎程度与日俱增。它被广泛用于网络开发、复杂系统、数据科学、机器学习和所有科学领域。

你可能遇到的 Python 有两个版本。Python2 目前已经不支持了。而 Python3 系列是持续支持的版本。

检查 Python 是否已经安装

在 Windows 上安装它之前,你应该检查它是否已经安装。一般来说,它应该没有安装,不像在 Ubuntu (和其他 Linux 发行版)中,Python 是预先安装的。

从开始菜单中,打开“命令提示符”。

并输入以下内容:

python --version

如果 Python 是可用的,它将显示一个包含版本细节的信息。

下载并安装 Python

打开下面的 Python 官方下载页面。

下载 Python

如何找到要安装的 Python

在顶部,你应该看到当前的稳定版本。点击下载链接。如果你正在寻找任何特定的版本,在这个页面上向下滚动,在 “Python releases by version number:” 的标签下下载特定的版本。

下载后,进入下载文件夹,运行安装程序。

按照屏幕上的指示进行安装。

安装 Python 第 1 步

安装 Python 第 2 步

安装完成后,验证 Python 的版本。

验证 Python 版本

从开始菜单,打开“命令提示符”,运行以下命令。

python --version

Windows 上的 Python 版本

你应该看到你的系统当前安装的 Python 包的版本。另外,你也可以运行下面的程序来获得一个 Python 交互式 shell。

python

你可以用 CTRL+Z 和回车键退出这个交互界面。

检查 PATH 变量

你应该检查系统变量 PATH,看看 Python 的可执行位置是否存在。这应该是使用安装程序自动更新的。

从开始菜单中,搜索“ 系统变量 system variables ”并打开它。

打开环境变量设置

在“系统属性”对话框中,点击“ 高级 Advanced > 环境变量 Environment Variables ”。在用户变量部分,对照路径变量,检查 Python 的安装位置是否存在。请参考下面的图片作为指导。

如果你看到所有的路径都存在,你就可以运行你的 Python 项目了。

检查 Windows 中的 Python 环境 PATH 值

创建并运行你的第一个 Python 程序

一个额外的步骤,这里是你如何编码和运行你的第一个 Python 程序。你可以使用任意 推荐的 Python 编辑器 来编写你的程序。

下面是一个简单的程序,它在控制台中输出文本 debugpoint.com

# Sample Python program
print("debugpoint.com")

用任意名字保存文件。这里我把它保存为 hello.py,放在 E 盘。.py 是 Python 源码的扩展名。

要运行这个程序,请打开命令提示符,在 E 盘中执行以下内容。

python hello.py

输出:

在 Windows 中运行一个简单的 Python 程序

结束语

我希望这个简单的初学者指南能够帮助你在 Windows 中安装 Python,验证安装并运行你的第一个程序。

如果你遇到问题,请在下面的评论栏中告诉我。


via: https://www.debugpoint.com/install-python-windows/

作者:Arindam 选题:lkxed 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

在这个简便的教程中,我们可以了解到 Java 中方法的定义,如何使用方法,以及何时使用方法。

Java 中的方法(在许多其他编程语言中称为“函数”)是被组合在一起并标记为可重用的一块代码。方法很有用,因为它们允许你在不重写相同代码的情况下,执行相同的操作或一系列操作,这不仅意味着你的工作量减少,还意味着出现问题时需要维护和调试的代码减少。

方法存在于类中,因此标准 Java 样板代码适用:

package com.opensource.example;

public class Example {
  // 在此写代码
}

在这样一个简单的单文件应用程序中,包定义并不是绝对必要的,但它是一个很好的习惯,而且大多数 IDE 都强制执行它。

默认情况下,Java 会寻找在类中运行的 main 方法。方法可以是公有的或私有的,也可以是静态的或非静态的,但 main 方法必须是公有的、静态的,Java 编译器才能识别和使用它。当方法是公有的时,它可以从类外部执行。要在程序启动时调用 Example 类,其 main 方法必须是可访问的,因此将其设置为 public

下面是两个方法的简单演示:一个 main 方法在调用 Example 类时默认执行,另一个 report 方法接受 main 的输入并执行简单操作。

为了模拟任意数据输入,我使用了 if-then 语句,该语句根据你启动应用程序的时间在两个字符串之间进行选择。换句话说,main 方法首先设置一些数据(在现实生活中,这些数据可以来自用户输入,也可以来自应用程序其他地方的其他方法),然后 “调用” report方法,将处理后的数据作为输入提供:

package com.opensource.example;

public class Example {
  public static void main(String[] args) {
    // 生成一些数据
    long myTime = System.currentTimeMillis();
    String weather;

    if ( myTime%2 == 0 ) {
      weather = "party";
    } else {
      weather = "apocalypse";
    }

    // 调用其他方法
    report(weather);
  }

  private static void report(String day) {
    System.out.printf("Welcome to the zombie %s\n", day);
  }
}

运行代码:

$ java ./Example.java
Welcome to the zombie apocalypse
$ java ./Example.java
Welcome to the zombie party

请注意,同一 report 方法有两个不同的结果。当然,在这个简单的演示中,不需要第二种方法。模拟数据生成的 if-then 语句可能生成了相同的结果。但是,当一个方法执行一项复杂的任务时,比如将图像调整为缩略图,然后使用调整后的图像在屏幕上生成小部件,那么附加组件的“费用”就很有意义了。

何时使用 Java 方法

很难知道何时使用方法,何时只将数据发送到 Java 流 或循环中。如果你面临这个决定,答案通常是使用一种方法。原因如下:

  • 方法开销少。它们不会给代码增加处理开销。
  • 方法减少代码的行数。
  • 方法是特定的。查找名为 resizeImage 的方法通常比查找隐藏在从驱动器加载图像的函数中某个循环中的代码更容易。
  • 方法是可重用的。当你第一次编写方法时,你可能会 认为 它只对应用程序中的一个任务有用。然而,随着应用程序的编写,你可能会发现自己正在使用一种你认为“已完成”的方法。

函数式编程与面向对象编程

函数式编程利用方法作为执行任务的主要构造。创建一个方法,该方法接受一种数据,处理该数据,并输出新数据。将许多方法串在一起,你就拥有了一个动态且功能强大的应用程序。像 C 和 Lua 这样的编程语言就是这种编码风格的例子。

用代码完成任务的另一种方式是 Java 使用的面向对象模型。在面向对象编程中,方法是模板的组成部分。你可以创建对象,而不是将数据从一个方法发送到另一个方法,并可以通过使用它们的方法来更改它们。

从面向对象的角度来看,这是一个简单的 “僵尸末日” 演示程序。在函数方法中,我使用一种方法生成数据,另一种方法使用该数据执行操作。面向对象的等价物是具有表示工作单元的类。这个示例应用程序向用户显示一条当天的消息,宣布这一天会有僵尸派对或是僵尸末日。编写一个“天”对象,然后查询该对象以了解其特性是有意义的。作为演示面向对象构造的不同方面的借口,新的示例应用程序还将统计有多少僵尸出现在派对上(或末日)。

Java 为每个类使用一个文件,因此要创建的第一个文件是 Day.Java,它用作 Day 对象:

package com.opensource.example;

import java.util.Random;

// 类
public class Day {
    public static String weather;
    public int count;

// 构造方法
  public Day() {
    long myTime = System.currentTimeMillis();

    if ( myTime%2 == 0 ) {
      weather = "paradise";
    } else {
      weather = "apocalypse";
    }
  }

// 方法
  public String report() {
      return weather;
  }

  public int counter() {
    Random rand = new Random();
    count = count + rand.nextInt(100);

    return(count);
    }
}

在“类”部分中,创建了两个域:天象 weather 和计数 countweather 是静态的。在一天的过程中(在这种假想的情况下),weather 不会改变。要么是派对 paradise,要么是末日 apocalypse,持续了一整天。然而,僵尸的数量在一天中会增加。

在“构造方法”部分,确定当天的天象。它是作为一个 构造方法 完成的,因为它只在类最初被调用时发生一次。

在“方法”部分,report 方法只返回由构造方法确定和设置的天象报告。然而,counter 方法生成一个随机数,并将其添加到当前僵尸计数中。

换句话说,这个类做了三件不同的事情:

  • 表示应用程序定义的“天”。
  • 设置当天不变的天气报告。
  • 设置一天中不断增加的僵尸数量。

要使用这所有,请创建第二个文件:

package com.opensource.example;

public class Example {
  public static void main(String[] args) {
    Day myDay = new Day();
    String foo = myDay.report();
    String bar = myDay.report();

    System.out.printf("Welcome to a zombie %s\n", foo);
    System.out.printf("Welcome to a zombie %s\n", bar);
    System.out.printf("There are %d zombies out today.\n", myDay.counter());
    System.out.printf("UPDATE: %d zombies. ", myDay.counter());
    System.out.printf("UPDATE: %d zombies. ", myDay.counter());
  }
}

因为现在有两个文件,所以使用 Java IDE 运行代码是最简单的,但是如果不想使用 IDE,可以创建自己的 JAR 文件。运行代码以查看结果:

Welcome to a zombie apocalypse
Welcome to a zombie apocalypse
There are 35 zombies out today.
UPDATE: 67 zombies. UPDATE: 149 zombies.

无论调用 report 方法多少次,weather 都保持不变,但调用 counter 方法的次数越多,僵尸的数量就会增加。

Java 方法

方法(或函数)是编程中的重要组成。在 Java 中,你可以将它们作为函数式编程的单个类的一部分使用,也可以在面向对象编程的类之间使用它们。两种类型的编程对于解决同一个问题有不同的视角,因此没有对与错之分。通过反复尝试,积累一点经验,你会知道哪一个最适合某个特定的问题。


via: https://opensource.com/article/23/1/java-methods

作者:Seth Kenlon 选题:lkxed 译者:ZhangZhanhaoxiang 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出