在Perl中是否有任何本地方式可以知道访问哈希的密钥是什么? 像某些语言或代理对象中存在的魔术方法?
答案 0 :(得分:5)
是的,有。它被称为“绑定”变量。
tie
是实例化代理对象(来自指定类)并将其绑定到变量的组合。
有关详细信息,请参阅perldoc perltie
。
简短版本是:
"prettier.printWidth": 180
然后访问tie %hash, 'Some::Class';
将触发%hash
中的方法调用(前提是它实现了Some::Class
构造函数和接口的其余部分)。
答案 1 :(得分:1)
Perl允许您tie
变量到类。这提供了一种机制,可以将自定义代码(绑定类的代码)注入到可以在绑定变量上执行的各种操作中。对于哈希,这些操作包括TIEHASH
,STORE
,FIRSTKEY
,FETCH
,NEXTKEY
,EXISTS
,DELETE
,{ {1}}和CLEAR
。
因此,绑定哈希的完整实现将实现这些方法中的每一个。为了简化这一过程,核心Perl发行版提供了模块Tie::Hash
,该模块还提供了SCALAR
。
Tie::StdHash
可能是向其他典型的哈希实现添加某些功能的最短路径,因为它提供了上述每种哈希方法的标准实现。要添加自己的功能,您可以覆盖那些有意义的方法。然后调用Tie::StdHash
(其中*表示重写操作的名称)或在重写方法中完整地提供所需的哈希功能。一个例子可能比单词更简单:
SUPER::*
在此示例中,package NoisyHash;
use strict;
use warnings;
require Tie::Hash;
our @ISA = q(Tie::StdHash);
sub STORE {
my ($self, $key, $value) = @_;
warn "\tSet $key to $value\n";
return $self->SUPER::STORE($key, $value);
}
sub FETCH {
my ($self, $key) = @_;
warn "\tFetch from $key\n";
return $self->SUPER::FETCH($key);
}
1;
package main;
use strict;
use warnings;
tie my %hash, 'NoisyHash';
$hash{A} = 1;
$hash{B} = 'foo';
print "\$hash{A} = $hash{A}\n";
print "\$hash{B} = $hash{B}\n";
和FETCH
方法被代码覆盖,导致它们向STORE
吐出一些诊断信息。然后我们通过最终调用STDERR
来保留这些方法的常规哈希语义。我们可以简单地实现我们自己的该功能版本,而不是调用SUPER,但利用现有的实现更不容易出错。
前面例子的输出是:
SUPER::*
如示例所示, Set A to 1
Set B to foo
Fetch from A
$hash{A} = 1
Fetch from B
$hash{B} = foo
函数用于将tie
绑定到NoisyHash
。事实证明,%hash
也返回一个不经常使用的对象,但是可以用来提供可以针对哈希调用的其他方法,这些哈希不是默认集合的一部分。上面列出的哈希操作。
tie
此代码的示例输出为:
package SumHash;
use strict;
use warnings;
require Tie::Hash;
our @ISA = q(Tie::StdHash);
use List::Util;
sub sum {
my $self = shift;
return List::Util::sum(values %$self);
}
1;
package main;
use strict;
use warnings;
my $hash_obj = tie my %hash, 'SumHash';
@hash{qw(a b c d e)} = (1, 2, 3, 4, 5);
my $sum = $hash_obj->sum;
print "Sum of (",
join(', ', values %hash),
") is $sum.\n",
所以我们在这里调用了Sum of (3, 4, 1, 5, 2) is 15.
类sum
类的SumHash
方法。该类仍继承自Tie::StdHash
,并且不会覆盖任何标准方法,因此它仍保留标准哈希功能。但它确实增加了计算哈希值的能力。但是,这不是计算哈希值的最简单方法。人们可以这样做,而不是经历将哈希绑定到它的所有麻烦,只需要这样做:
use List::Util qw(sum);
print "Sum of (", join(', ', values %hash), ") is ", sum(values %hash), "\n";
这说明了为什么Perl社区普遍认为绑定变量很少是解决典型问题的最佳方法。绑定变量会导致难以理解,并推断远距离的行动。绑定变量的性能相当差。但这种做法确实偶尔会有合理的用途,Perl提供了一种手段。
有关该模块的说明,请参阅perldoc Tie::Hash
。请注意,tie
可用于绑定任何Perl的常见容器:标量,数组,散列或文件句柄。
有关使用tie
的Perl文档中最详尽的解释,请访问perldoc perltie