【问题标题】:Python equivalent for perl referencesperl 引用的 Python 等效项
【发布时间】:2014-06-15 14:20:03
【问题描述】:

我是python初学者,到目前为止我已经读到python没有引用,如果这是真的,那么在python中跟随perl代码的等价物是什么?

#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;

my @grps = qw/grp1:1:2:3 grp2:1:2:3 grp3:1:2:3/;

# CREATES AN ARRAY OF REFERENCES TO ARRAYS - AoR2A
my @agrps;
foreach (@grps){
  push @agrps, [split(":")];
}

# CREATES AN HASH OF REFERENCES TO ARRAYS (REFERENCES ARE THE SAME AS THEY ARE IN AoR2A ABOVE)
my %hgrps;
foreach (@agrps){
   $hgrps{"$_->[0]"} = $_;
}

# THE ELEMENTS CAN BE THEN ACCESSED EITHER VIA ARRAY OR HASH SYNTAX
$hgrps{"grp3"}->[3] = "NEW VALUE 3rd INDEX";
$agrps[2]->[2] = "NEW VALUE 2nd INDEX";

print Dumper @agrps;
print "\n";
print Dumper %hgrps;

上述脚本的输出如下:

$VAR1 = [
          'grp1',
          '1',
          '2',
          '3'
        ];
$VAR2 = [
          'grp2',
          '1',
          '2',
          '3'
        ];
$VAR3 = [
          'grp3',
          '1',
          'NEW VALUE 2nd INDEX',
          'NEW VALUE 3rd INDEX'
        ];

$VAR1 = 'grp3';
$VAR2 = [
          'grp3',
          '1',
          'NEW VALUE 2nd INDEX',
          'NEW VALUE 3rd INDEX'
        ];
$VAR3 = 'grp1';
$VAR4 = [
          'grp1',
          '1',
          '2',
          '3'
        ];
$VAR5 = 'grp2';
$VAR6 = [
          'grp2',
          '1',
          '2',
          '3'
        ];

【问题讨论】:

  • @jmetz,“参考”和“通过参考”是两个不同的东西。

标签: python perl dictionary reference pass-by-reference


【解决方案1】:

Perl 需要引用有两个原因:

  1. 以向后兼容的方式复杂(即嵌套)数据结构。例如。 $hash{entry} = @array 必须继续为该条目分配数组大小,因此使用数组引用是使用嵌套数据结构的一种转义:$hash{entry} = \@array

    Python 中不存在这个问题。数组和其他数据结构已经是引用类型,而不是值类型。

  2. 间接。例如在 Perl 中我们可以这样做

    my $x = 1;
    my $ref = \$x; 
    $$ref = 42;
    # ($x == 42) is true
    

    这可以在一定程度上使用数组伪造,重要的部分是不要使用值类型。例如,我们需要两个级别来通过引用更改某些值。

    x = [1]
    ref = [x]
    ref[0][0] = 42
    # (x is [42]) is True
    

    如果我们只需要一个可以引用不同事物的指针,我们只需要一个级别。

    如果你使用 Ref 类,它可能更易读:

    class Ref(object):
        def __init__(self, val):
            self.val = val
    
    ref = Ref(1)
    ref.val = 42
    

由于您的问题集中在嵌套数据结构上,因此将代码转换为 Python 不需要任何“数组引用”。简单的列表就可以了。

grps = [...]
argps = list()
hrgps = dict()
for entry in grps:
    fields = entry.split(":") # split returns a list
    argps.append(fields)
    hrgps[fields[0]] = fields

【讨论】:

  • 更有趣的问题是 Perl 是否需要数组和哈希类型而不是数组和哈希引用(除了向后兼容性)?
  • @socketpuppet 不是真的。 Perl6 以添加更多上下文为代价摆脱了引用。 Perl5 有 void、标量和列表上下文。 Perl6 也有一个项上下文,其中数组的行为类似于 Perl5 的数组引用。从那时起,Perl5 也一直在朝着这个方向发展:许多内置函数现在可以在以前需要数组变量的地方获取数组引用,例如push $array_ref, $value.
  • @newacct:Python 是“按名称传递”,它既不是“按引用”也不是“按值”,例如,In Python, why can a function modify some arguments as perceived by the caller, but not others?
  • @J.F.Sebastian:不,你才是错的。与其让我读别人写的东西,不如自己为自己的主张辩护。必须以跨语言一致的方式定义术语。如果您在 StackOverflow 或 Internet 上查看任何地方,Java 都被称为按值传递。但是在 Java 和 Python 之间,变量以及赋值和传递的语义完全相同。所以必须用相同的术语来描述两者。
  • @newacct:维基百科称它为Call by sharing(这很好,因为我不知道还有谁使用这个词。所以没有错误的先入之见)。 pass-by-value 是 understood by many people as a process that involves a copy 并且 CPython 实现在这个意义上使用它,例如,参见 ctypes 源代码。但是 Python 对象及其值在函数调用期间不会被复制。 objects and values have well-defined meaning 在 Python 中。
猜你喜欢
  • 2014-06-15
  • 2014-11-06
  • 1970-01-01
  • 2012-02-08
  • 2011-01-21
  • 2011-09-27
  • 2013-05-12
  • 2017-02-26
  • 2013-05-26
相关资源
最近更新 更多