Вещь № 1 IMO: Внимание на потокобезопасность . GIL CPYTHON делает пишущий ориентированный на многопотоковое исполнение код легким, потому что только один поток может получить доступ к интерпретатору за один раз. IronPython и Jython являются немного меньшим количеством содержания руки все же.
Это то же самое, что и
while (<STUFF>) {
print "Line $. is : $_";
}
Он написан так, как есть, потому что он проще и более компактный. В общем, это известная форма Perl (in) «модификатор оператора» для условных выражений и циклов.
В других ответах объясняется форма модификатора оператора , а
петля. Однако здесь происходит много другого волшебства. В частности, сценарий полагается на три специальные переменные Perl. Два из них ( $ _
и $!
) очень распространены; другой ( $.
) довольно распространен. Но все они заслуживают внимания.
Когда вы запускаете , а <$ fh>
на открытом дескрипторе файла, Perl автоматически запускает файл, строка за строкой, пока не достигнет EOF
]. В каждом цикле текущая строка установлена на $ _
без каких-либо действий. Итак, это одно и то же:
while (<$fh>) { # something }
while (defined($_ = <$fh>)) { # something }
См. perldoc perlop
, раздел об операторах ввода-вывода. (Некоторые люди находят это тоже волшебным, поэтому они используют вместо него while (my $ line = <$ fh>)
. Это дает вам $ line
для каждой строки а не $ _
, которое является более понятным именем переменной, но требует большего набора текста. Каждому свое.)
$!
содержит значение системной ошибки (если она установлено). См. perldoc perlvar
, раздел $ OS_ERROR
, чтобы узнать, как и когда это использовать.
$.
содержит номер строки. См. perldoc perlvar
, раздел $ NR
. Эта переменная может быть на удивление сложной. Это победило t обязательно иметь номер строки файла, который вы сейчас читаете. Пример:
#!/usr/bin/env perl
use strict;
use warnings;
while (<>) {
print "$ARGV: $.\n";
}
Если вы сохраните это как lines
и запустите как perl lines file1 file2 file3
, то Perl будет считать строки прямо через file1, file2 и file3. Вы можете видеть, что Perl знает, из какого файла он читает (он находится в $ ARGV; имена файлов будут правильными), но он не автоматически сбрасывает нумерацию строк в конце каждого файла. Я упоминаю об этом, поскольку меня это поведение не раз кусало, пока я наконец не прошел через свой (толстый) череп. Вы можете сбросить нумерацию для отслеживания отдельных файлов следующим образом:
#!/usr/bin/env perl
use strict;
use warnings;
while (<>) {
print "$ARGV: $.\n";
}
continue {
close ARGV if eof;
}
Вы также должны проверить прагмы strict
и warnings
и взглянуть на новую форму с тремя аргументами открытый
. Я только что заметил, что ты "
Я взял на себя смелость переписать ваш фрагмент, как и сделал бы.
Ниже предложенный мной код представляет собой галерею неоптимальных методов, которые вы можете встретить в реальной жизни.
use strict;
use warnings;
my $stuff_path = 'c:/scripts/stuff.txt';
open (my $stuff, '<', $stuff_path)
or die "Cannot open'$stuff_path' for read : $!\n";
# My preferred method to loop over a file line by line:
# while loop with explicit variable
while( my $line = <$stuff> ) {
print "Line $. is : $line\n";
}
Вот и другие методы, которые вы можете увидеть. Каждый из них может быть заменен на цикл while в моем примере выше.
# while statement modifier
# - OK, but less clear than explicit code above.
print "Line $. is : $_" while <$stuff>;
# while loop
# - OK, but if I am operating on $_ explicitly, I prefer to use an explicit variable.
while( <$stuff> ) {
print "Line $. is : $_";
}
# for statement modifier
# - inefficient
# - loads whole file into memory
print "Line $. is : $_" for <$stuff>;
# for loop - inefficient
# - loads whole file into memory;
for( <$stuff> ) {
print "Line $. is : $_\n";
}
# for loop with explicit variable
# - inefficient
# - loads whole file into memory;
for my $line ( <$stuff> ) {
print "Line $. is : $line\n";
}
# Exotica -
# map and print
# - inefficient
# - loads whole file into memory
# - stores complete output in memory
print map "Line $. is : $_\n", <$stuff>;
# Using readline rather than <>
# - Alright, but overly verbose
while( defined (my $line = readline($stuff) ) {
print "Line $. is : $line\n";
}
# Using IO::Handle methods on a lexical filehandle
# - Alright, but overly verbose
use IO::Handle;
while( defined (my $line = $stuff->readline) ) {
print "Line $. is : $line\n";
}
Следующие ниже фрагменты полностью эквивалентны, просто разные способы написания одного и того же:
print "Line $. is : $_" while (<STUFF>);
while (<STUFF>) {
print "Line $. is : $_";
}
Что это происходит на каждой итерации цикла, Perl считывает одну строку текста из файла STUFF
и помещает ее в специальную переменную $ _
(это то, что делают угловые скобки). Затем тело цикла выводит такие строки, как:
Line 1 is : test Line 2 is : file
Специальная переменная $.
- это номер последней строки, прочитанной из файла, а $ _
- это содержимое этой строки, заданное оператором угловой скобки.
Размещение и
после печати делает строку читаемой почти как обычный английский.
Это также делает акцент на печати
вместо и
. И вам не нужны фигурные скобки: {...}
Их также можно использовать с if
и , если
, например,
print "Debug: foobar=$foobar\n" if $DEBUG;
print "Load file...\n" unless $QUIET;
Обратите внимание, что оператор while
может следовать за телом вашего цикла, только если он однострочный. Если тело вашего цикла занимает несколько строк, то перед ним должен стоять , а
.
Это то же самое, что и:
while (<STUFF>) { print "Line $. is: $_"; }