57

我正在学习 perl 和 python ......同时,不是我的设计,但它必须完成。

问题:

在一个 perl 脚本中,我在 txt 的开头使用(见下文)。

#!/usr/bin/env perl

use strict;
use warnings;

我应该为我的 python 脚本做一些常规的事情吗?

4

6 回答 6

56

为了提供一个可能避免这里出现一些评论噪音的答案,我将尝试另一个答案。

您原始问题中的两个语用实际上扩展到:

use strict "vars";
use strict "refs";
use strict "subs";
use warnings;

依次回答每个:

  • 的效果use strict "vars"是导致编译时错误引用变量而不首先声明它存在(例如在 C、C++ 和 Java 等更多静态语言中是默认值)。因为 Python 没有特定的语法来声明变量存在,所以它没有等价物。如果它首先不存在,则在 Python 中分配一个名称总是会创建它。此功能strict没有 Python 等效功能,并且无法重新创建它提供的安全性。

例如:

$ perl -c -e 'use strict "vars"; $foo = 1'
Global symbol "$foo" requires explicit package name at -e line 1.
-e had compilation errors.

$ perl -c -e 'no strict "vars"; $foo = 1'
-e syntax OK
  • 的效果use strict "refs"是禁止使用包含(现有或新)变量名称的纯字符串作为对变量本身的引用。Python 不这样做,因此无需禁用它。

例如:

$ perl -e 'use strict "refs"; ${"message"} = "hello"; print $message'
Can't use string ("message") as a SCALAR ref while "strict refs" in use at -e line 1.

$ perl -e 'no strict "refs"; ${"message"} = "hello"; print $message'
hello
  • 的效果use strict "subs"是导致编译时任何尝试调用已知不存在的函数。Python 不执行任何此类检查,也无法启用此类功能。

例如:

$ perl -c -e 'use strict "subs"; foo'
Bareword "foo" not allowed while "strict subs" in use at -e line 1.
-e had compilation errors.

$ perl -c -e 'no strict "subs"; foo'
-e syntax OK
  • 的效果use warnings是在早期版本中默认的各种行为类别的编译和运行时启用更多警告,有时可能需要,或者从来都不是一个好主意,但严格来说不是错误。例如,使用未初始化的值作为数字通常应该给出警告,但最初它没有这样做。

例如:

$ perl -e 'use warnings; my $u; print 2 + $u'
Use of uninitialized value $u in addition (+) at -e line 1.
2

$ perl -e 'no warnings; my $u; print 2 + $u'
2

最后; 一些评论指出 Python 在__future__. 但是,这不应被视为类似于 Perl 的 pragmata,因为后者的大部分都是词法范围的,并且可以根据需要在小范围内启用或禁用;where's Python's__future__仅对整个源文件启用。

例如。

use strict;
use warnings;

my $total;

$total += count_things($_) for @list;

{
   no warnings 'uninitialized';
   printf "The total is %d\n", $total;
}

一个有点做作的例子,但这个例子演示了使用no warnings 'uninitialized'来禁用关于在printf语句中使用未初始化值的警告,同时仍然在其他任何地方保持启用其他警告。


综上所述:Pythonuse strict没有use warnings. 它确实提供的那些功能仅在文件级别启用,并且不能在每个范围内选择性地启用或禁用。


编辑:实际上我现在被告知 Python 确实有一些可控的警告标志,可以根据需要启用和禁用。

于 2012-11-20T12:28:07.010 回答
41

正如其他用户所发布的那样,Python 没有严格的编译指示。在我看来,这是它最大的缺陷之一。此外,对于严肃的编程项目,我仍然使用 Perl 也是原因之一。

毫无疑问,Python 爱好者会对这种说法感到不满。我听说有人说他们不需要严格。我发现那些说这种话的人通常不知道严格会带给你什么。考虑 Python 中的以下代码块:

def Main():
    print(GetPrice(100,"Alaska"))
    print(GetPrice(100,"Florida"))
    print(GetPrice(100,"Michigan"))
    print(GetPrice(100,"Wisconsin"))

def GetPrice(UnitPrice,State):
    StateSalesTaxRate = 0
    if State == "Alabama": StateSalesTaxRate = 0.04
    if State == "Alaska": StateSalesTaxRate = 0
    if State == "Arizona": StateSalesTaxRate = 0.056
    if State == "Arkansas": StateSalesTaxRate = 0.065
    if State == "California": StateSalesTaxRate = 0.075
    if State == "Colorado": StateSalesTaxRate = 0.029
    if State == "Connecticut": StateSalesTaxRate = 0.0635
    if State == "Delaware": StateSalesTaxRate = 0
    if State == "Florida": StateSalesTaxRate = 0.06
    if State == "Georgia": StateSalesTaxRate = 0.04
    if State == "Guam": StateSalesTaxRate = 0.04
    if State == "Hawaii": StateSalesTaxRate = 0.04
    if State == "Idaho": StateSalesTaxRate = 0.06
    if State == "Illinois": StateSalesTaxRate = 0.0625
    if State == "Indiana": StateSalesTaxRate = 0.07
    if State == "Iowa": StateSalesTaxRate = 0.06
    if State == "Kansas": StateSalesTaxRate = 0.0615
    if State == "Kentucky": StateSalesTaxRate = 0.06
    if State == "Louisiana": StateSalesTaxRate = 0.04
    if State == "Maine": StateSalesTaxRate = 0.055
    if State == "Maryland": StateSalesTaxRate = 0.06
    if State == "Massachusetts": StateSalesTaxRate = 0.0625
    if State == "Michigan": StateSalesTexRate = 0.06
    if State == "Minnesota": StateSalesTaxRate = 0.06875
    if State == "Mississippi": StateSalesTaxRate = 0.07
    if State == "Missouri": StateSalesTaxRate = 0.04225
    if State == "Montana": StateSalesTaxRate = 0
    if State == "Nebraska": StateSalesTaxRate = 0.055
    if State == "Nevada": StateSalesTaxRate = 0.0685
    if State == "New Hampshire": StateSalesTaxRate = 0
    if State == "New Jersey": StateSalesTaxRate = 0.07
    if State == "New Mexico": StateSalesTaxRate = 0.05125
    if State == "New York": StateSalesTaxRate = 0.04
    if State == "North Carolina": StateSalesTaxRate = 0.0475
    if State == "North Dakota": StateSalesTaxRate = 0.05
    if State == "Ohio": StateSalesTaxRate = 0.0575
    if State == "Oklahoma": StateSalesTaxRate = 0.045
    if State == "Oregon": StateSalesTaxRate = 0
    if State == "Pennsylvania": StateSalesTaxRate = 0.06
    if State == "Puerto Rico": StateSalesTaxRate = 0.105
    if State == "Rhode Island": StateSalesTaxRate = 0.07
    if State == "South Carolina": StateSalesTaxRate = 0.06
    if State == "South Dakota": StateSalesTaxRate = 0.04
    if State == "Tennessee": StateSalesTaxRate = 0.07
    if State == "Texas": StateSalesTaxRate = 0.0625
    if State == "Utah": StateSalesTaxRate = 0.0595
    if State == "Vermont": StateSalesTaxRate = 0.06
    if State == "Virginia": StateSalesTaxRate = 0.053
    if State == "Washington": StateSalesTaxRate = 0.065
    if State == "West Virginia": StateSalesTaxRate = 0.06
    if State == "Wisconsin": StateSalesTaxRate = 0.05
    if State == "Wyoming": StateSalesTaxRate = 0.04
    return(UnitPrice*(1+StateSalesTaxRate))

if __name__ == '__main__': Main()

此代码计算购买成本,包括销售税。当然有更有效的方法可以做到这一点,但这只是一个例子。

那么,您发现代码有什么问题吗?不?尝试运行它。当你这样做时,你会得到:

100
106.0
100
105.0

还是没看出问题?那么你有一个比你知道的更大的问题。下面是在 Perl 中呈现的等效代码:

use strict;

sub Main
{
    print GetPrice(100,"Alaska"), "\n";
    print GetPrice(100,"Florida"), "\n";
    print GetPrice(100,"Michigan"), "\n";
    print GetPrice(100,"Wisconsin"), "\n";    
}

sub GetPrice
{
    my($UnitPrice,$State) = @_;
    my $StateSalesTaxRate = 0;
    $StateSalesTaxRate = 0.04 if $State eq "Alabama";
    $StateSalesTaxRate = 0 if $State eq "Alaska";
    $StateSalesTaxRate = 0.056 if $State eq "Arizona";
    $StateSalesTaxRate = 0.065 if $State eq "Arkansas";
    $StateSalesTaxRate = 0.075 if $State eq "California";
    $StateSalesTaxRate = 0.029 if $State eq "Colorado";
    $StateSalesTaxRate = 0.0635 if $State eq "Connecticut";
    $StateSalesTaxRate = 0 if $State eq "Delaware";
    $StateSalesTaxRate = 0.06 if $State eq "Florida";
    $StateSalesTaxRate = 0.04 if $State eq "Georgia";
    $StateSalesTaxRate = 0.04 if $State eq "Guam";
    $StateSalesTaxRate = 0.04 if $State eq "Hawaii";
    $StateSalesTaxRate = 0.06 if $State eq "Idaho";
    $StateSalesTaxRate = 0.0625 if $State eq "Illinois";
    $StateSalesTaxRate = 0.07 if $State eq "Indiana";
    $StateSalesTaxRate = 0.06 if $State eq "Iowa";
    $StateSalesTaxRate = 0.0615 if $State eq "Kansas";
    $StateSalesTaxRate = 0.06 if $State eq "Kentucky";
    $StateSalesTaxRate = 0.04 if $State eq "Louisiana";
    $StateSalesTaxRate = 0.055 if $State eq "Maine";
    $StateSalesTaxRate = 0.06 if $State eq "Maryland";
    $StateSalesTaxRate = 0.0625 if $State eq "Massachusetts";
    $StateSalesTexRate = 0.06 if $State eq "Michigan";
    $StateSalesTaxRate = 0.06875 if $State eq "Minnesota";
    $StateSalesTaxRate = 0.07 if $State eq "Mississippi";
    $StateSalesTaxRate = 0.04225 if $State eq "Missouri";
    $StateSalesTaxRate = 0 if $State eq "Montana";
    $StateSalesTaxRate = 0.055 if $State eq "Nebraska";
    $StateSalesTaxRate = 0.0685 if $State eq "Nevada";
    $StateSalesTaxRate = 0 if $State eq "New Hampshire";
    $StateSalesTaxRate = 0.07 if $State eq "New Jersey";
    $StateSalesTaxRate = 0.05125 if $State eq "New Mexico";
    $StateSalesTaxRate = 0.04 if $State eq "New York";
    $StateSalesTaxRate = 0.0475 if $State eq "North Carolina";
    $StateSalesTaxRate = 0.05 if $State eq "North Dakota";
    $StateSalesTaxRate = 0.0575 if $State eq "Ohio";
    $StateSalesTaxRate = 0.045 if $State eq "Oklahoma";
    $StateSalesTaxRate = 0 if $State eq "Oregon";
    $StateSalesTaxRate = 0.06 if $State eq "Pennsylvania";
    $StateSalesTaxRate = 0.105 if $State eq "Puerto Rico";
    $StateSalesTaxRate = 0.07 if $State eq "Rhode Island";
    $StateSalesTaxRate = 0.06 if $State eq "South Carolina";
    $StateSalesTaxRate = 0.04 if $State eq "South Dakota";
    $StateSalesTaxRate = 0.07 if $State eq "Tennessee";
    $StateSalesTaxRate = 0.0625 if $State eq "Texas";
    $StateSalesTaxRate = 0.0595 if $State eq "Utah";
    $StateSalesTaxRate = 0.06 if $State eq "Vermont";
    $StateSalesTaxRate = 0.053 if $State eq "Virginia";
    $StateSalesTaxRate = 0.065 if $State eq "Washington";
    $StateSalesTaxRate = 0.06 if $State eq "West Virginia";
    $StateSalesTaxRate = 0.05 if $State eq "Wisconsin";
    $StateSalesTaxRate = 0.04 if $State eq "Wyoming";
    return($UnitPrice*(1+$StateSalesTaxRate));
}

Main();

如果不启用 Perl 的严格编译指示,您甚至会得到相同的输出:

100
106.0
100
105.0

但是在严格打开的情况下,当您运行这个 Perl 脚本时,您会收到以下错误消息:

Global symbol "$StateSalesTexRate" requires explicit package name at line 37.
Execution aborted due to compilation errors. 

这两个示例中的问题是其中一个计算行中存在拼写错误。对于密歇根州的计算销售税,我使用“StateSalesTexRate”而不是“StateSalesTaxRate”。Perl 明确地发现并消除了这个错误。与此同时,Python 转过头看向另一个方向。

这是一个大问题。想象一下,您的在线业务正在使用该软件来计算您从客户的信用卡中收取的费用。您需要多长时间才能意识到密歇根州的客户可以通过销售税?当你这样做时,你是回去找客户说“对不起,我们需要你更多的钱”还是你自己吃损失?

当然,任何使用这种编码算法来计算销售税的公司都可能存在更大的问题。但是您可以通过这个示例清楚地看到 Perl 中的 strict pragma 的作用以及为什么我和其他人认为它应该是任何脚本语言的基本特征。

Python 有很多我非常喜欢的地方。我明白为什么有些人更喜欢 Python 而不是 Perl。但是有几件事我真的很讨厌 Python。这是一。

于 2015-12-03T16:40:56.023 回答
11

要在打开警告的情况下运行 Python:

python -W all file.py

回应:

我应该为我的 python 脚本做一些常规的事情吗?

我认为确保您的代码符合PEP 8通常是一个好主意。正如另一个答案中提到的,您可以通过编程方式执行此操作:

pip install pep8 && pep8 file.py
于 2013-09-25T04:03:40.140 回答
7

LeoNerd 很好地解释了为什么 Python 中没有“使用严格”或“使用警告”。

回答:

我应该为我的 python 脚本做一些常规的事情吗?

您可能有兴趣通过静态代码分析器(如 pylint)和/或代码格式检查(如 pep8)运行代码。

它们可以帮助发现潜在问题并标记警告。他们对代码的格式也有很多话要说,你可能感兴趣也可能不感兴趣。

这是使用它们的合理理由。以及相关的 Stackoverflow 问题herehere

于 2013-02-28T10:08:19.787 回答
0

真的没有任何等价物。Python 的设计随着时间的推移而发展,并且进行了许多更改(特别是在 3.x 中)以确保语言中的默认值是开发人员默认需要的。一个特性很少存在,但它是一个可选标志。

这可能归结为Python 的禅宗 “应该有一种——最好只有一种——明显的方式来做到这一点。” Python 的设计侧重于可读性,并且有多种做事方式或改变语言的工作方式会使代码更难阅读。

我认为最接近的是从__future__旧版本的 Python 中导入,以将新版本的一些修复/新功能引入旧版本(例如默认情况下从整数除法到浮点除法的除法)。这在某种意义上是相似的,因为它正在改进默认行为,使其在标准情况下更加明智。

编辑:我似乎引起了 perl 用户的愤怒,他们认为这篇文章是对 Perl 的攻击——它从来没有这样的意图。Perl 是一门很好的语言,我原来的帖子只是用了很差的措辞,而且解释不清楚。我试图澄清。

于 2012-11-16T23:03:16.170 回答
0

不是编译时错误,但 Python 有许多 linter 可以识别与 Perl 的“use strict”相同类型的错误:

考虑一个名为的 Python 文件tmp.py

def foo():
    a = 1
    b = 2
    return a

flake8 tmp.py将返回:

tmp.py:13:5: F841 local variable 'b' is assigned to but never used

此外flake8,查看mypy更高级的类型检查并pylint强制执行某些编码样式。与任何编程语言一样,没有什么可以阻止您在代码库中使用多个 linter——事实上,这是鼓励的,因为每个 linter 都有不同的关注点。

于 2019-12-10T16:28:47.633 回答