Вам нужно связать d для каждой созданной функции. Один из способов сделать это - передать его как параметр со значением по умолчанию:
lambda d=d: self.root.change_directory(d)
Теперь функция внутри функции использует этот параметр, хотя он имеет то же имя, и значение по умолчанию для который вычисляется при создании функции. Чтобы помочь вам увидеть это:
lambda bound_d=d: self.root.change_directory(bound_d)
Помните, как работают значения по умолчанию, например, для изменяемых объектов, таких как списки и dicts, потому что вы привязываете объект.
Эта идиома параметров с значениями по умолчанию достаточно распространены, но может быть неудачным, если вы исследуете параметры функции и определяете, что делать в зависимости от их присутствия. Вы можете избежать параметра с другим закрытием:
(lambda d=d: lambda: self.root.change_directory(d))()
# or
(lambda d: lambda: self.root.change_directory(d))(d)
. Еще лучше, редизайн того, как вы обрабатываете «команды», поможет здесь и должен помочь в другом месте.
grep
возвраты те элементы исходного списка, которые соответствуют выражению, в то время как map
возвращается результат выражения относился к каждому элементу исходного списка.
$ perl -le 'print join " ", grep $_ & 1, (1, 2, 3, 4, 5)'
1 3 5
$ perl -le 'print join " ", map $_ & 1, (1, 2, 3, 4, 5)'
1 0 1 0 1
Первый пример печатает все нечетные элементы списка, в то время как второй пример печатает 0 или 1 в зависимости от того, нечетен ли соответствующий элемент или нет.
Я нахожу, что полезно думать, думают приблизительно grep()
и map()
в их самой общей форме:
grep {BLOCK} LIST
map {BLOCK} LIST
grep()
фильтр: это возвращает подмножество объектов из СПИСКА, для которого БЛОК возвращает true.
map()
отображающаяся функция: отправьте значение от СПИСКА в БЛОК, и БЛОК возвращает список 0 или больше значений; объединенный набор всех тех вызовов для БЛОКИРОВАНИЯ будет окончательным списком, возвращенным map()
.
map
применяет функцию ко всем элементам в списке и возвращает результат.
grep
возвраты все элементы в списке, которые оценивают к истинному, когда функция применяется к ним.
my %fruits = (
banana => {
color => 'yellow',
price => 0.79,
grams => 200
},
cherry => {
color => 'red',
price => 0.02,
grams => 10
},
orange => {
color => 'orange',
price => 1.00,
grams => 225
}
);
my %red_fruits = map { $_ => $fruits{$_} }
grep { $fruits{$_}->{color} eq 'red' }
keys(%fruits);
my @prices = map { $fruits{$_}->{price} } keys(%fruits);
my @colors = map { $fruits{$_}->{color} } keys(%fruits);
my @grams = map { $fruits{$_}->{grams} } keys(%fruits);
# Print each fruit's name sorted by price lowest to highest:
foreach( sort { $fruits{$a}->{price} <=> $fruits{$b}->{price}} keys(%fruits) )
{
print "$_ costs $fruits{$_}->{price} each\n";
}# end foreach()
Еще одна вещь о grep
: в скалярном контексте это говорит Вам, сколько объектов это нашло. Это может быть полезно, если Вы действительно не хотите второй список, но Вы действительно хотите знать сколько объектов определенного вида существует.
my @numbers = qw/1 2 3 4 5 6/;
my @odd_numbers = grep { $_ & 1 } @numbers; # grep returns (1, 3, 5)
my $how_many_odd = grep { $_ & 1 } @numbers; # grep returns 3
Править: Начиная с OP, который спрашивают в комментарии, я должен сказать, что можно использовать map
в скалярном контексте таким же образом. Точка не была этим grep
единственный из двух, которые могут сделать это, но что он иногда пригождается, чтобы сделать это с grep
.
Думайте о grep как о карте с фильтром. карта выполняет итерации и обеспечивает возможность сделать что-то с каждым объектом. Например, эти две строки эквивалентны:
my @copy = @original;
my @copy = map {$_} @original;
Точно так же эти два эквивалентны:
my @copy = grep {-f $_} @original;
@copy = ();
for (@original)
{
push @copy, $_ if -f $_;
}
grep обеспечивает способность вставить условное выражение и поэтому становится фильтром.