Perl:如何使所需脚本中的变量在所需脚本中可用

发布于 2024-12-06 05:53:44 字数 212 浏览 2 评论 0原文

示例

out.pl:

(my|our|local|global|whatever???) var = "test";
require("inside.pm");

inside.pm:

print $var;

我不想使用包 - 它超出了我的需求:) 谢谢!

example

out.pl:

(my|our|local|global|whatever???) var = "test";
require("inside.pm");

inside.pm:

print $var;

I don't want to use packages - it's overwhelming my needs :)
thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

末蓝 2024-12-13 05:53:44

即使您不使用package声明,您总是使用包。默认情况下,您正在包 main 中工作。

您使用 our 声明的所有变量都是包变量,并且应该在包范围内可用。下面是一个例子:

#! /usr/bin/env perl
# test2.pl

use strict;
use warnings;

our $foo = "bar";
1;

由于 $foo 被声明为包变量,因此它将在其他程序中可用:

#! /usr/bin/env perl
use strict;
use warnings;

require "test2.pl";

our $foo;
print "The value of \$foo is $foo\n";

现在我已经给了你足够的绳索,我要告诉你不要用它来吊死自己它。

这是一个非常非常糟糕的想法。请注意,$foo 从某种几乎无法弄清楚的神秘机制中获取了一个值?

太复杂?真的吗?这并不难!看这个例子:

#! /usr/bin/env perl
# test2.pm

package test2;
use strict;
use warnings;

our $foo = "bar";
1;

与之前没有太大不同,只是我添加了 package 声明,现在调用我的程序 test2.pm 而不是 test2.pl

以下是我访问它的方法:

#! /usr/bin/env perl
use strict;
use warnings;

use test2;

print "The value of \$foo from package test2 is $test2::foo\n";

我所要做的就是使用变量中的包名称。这是一个糟糕的想法,但它比上面显示的非常非常糟糕的想法要好得多。

至少,你知道价值从何而来。它来自 test2.pm。而且,如果您在子例程中设置该变量,则可以访问该变量。

#! /usr/bin/env perl
# test2.pm

package test2;
use strict;
use warnings;

sub fooloader {
    our $foo = "bar";
}
1;

请注意,$foo 是在子例程 fooloader 中设置的。而且,这是我访问它的另一个程序:

#! /usr/bin/env perl
use strict;
use warnings;

use test2;

&test2::fooloader();
print "The value of \$foo from package test2 is $test2::foo\n";

现在,您可以使用导出器导出您的子例程(甚至变量),但这不再是您看到的太多。主要是因为这是一个非常糟糕的想法。不像原来的非常糟糕的想法那么糟糕,但比上面的糟糕的想法更糟糕:

#! /usr/bin/env perl
# test2.pm

package test2;
use base qw(Exporter);

our @EXPORT = qw(fooloader);
use strict;
use warnings;

sub fooloader {
    our $foo = "bar";
}
1;

现在,我可以使用不带包名的子例程 fooloader

#! /usr/bin/env perl
use strict;
use warnings;

use test2;

fooloader();
print "The value of \$foo from package test2 is $test2::foo\n";

当然,问题是您并不真正知道子例程 fooloader 来自哪里。如果您使用 @EXPORT_OK 而不是 @EXPORT,则可以使用 use test2 qw(fooloader); 并记录 fooloader 函数来自。它还将帮助您了解不要在自己的程序中创建自己的 fooloader 函数并覆盖您导入的函数。然后,想知道为什么你的程序不再起作用。

顺便说一句,您还可以导出变量而不仅仅是函数。然而,这变成了一个真的、真的、真的很糟糕——不是一个可怕的想法,因为它违背了你首先使用包的所有原因。如果你打算这样做,为什么还要费心去打包呢?为什么不直接拿起枪搬起石头砸自己的脚呢?

最好和首选的方法是使用面向对象的 Perl 并以完全正确的方式进行操作。一种让您确切知道发生了什么以及为什么发生的方法。而且,可以很容易地弄清楚你的代码在做什么。一种将错误降至最低的方法。

看一下完全面向对象的 Test2 类:

#! /usr/bin/env perl
# Test2.pm

package Test2;

sub new {
    my $class = shift;

    my $self = {};
    bless $self, $class;

    return $self;
}

sub FooValue {
    return "bar";
}
1;

并使用该 Test2 类:

#! /usr/bin/env perl
use strict;
use warnings;

use Test2;

my $tester = Test2->new;

print "The value of foo from package test2 is " . $tester->FooValue . "\n";

这是最好的方法,因为即使您使用包,您也可以操纵 $test2 的值::foo 并且它将在您的整个程序中更改。想象一下,如果是 $constants::pi 并且在某处将其从 3.14159 更改为 3。从那时起,使用 $constants::pi 会给你错误的值。如果使用面向对象的方法,则无法更改方法 Constant->Pi 的值。它将始终是 3.14159。

那么,今天我们学到了什么?

我们了解到,在 Perl 中很容易做一些非常非常糟糕的想法,但是使用包并不需要做太多的工作,所以它只会变成一个坏主意。而且,如果您开始学习一些面向对象的 Perl,实际上您无需付出太多努力,就能以完全正确的方式完成这一切。

选择权在于您。请记住,您拍摄的脚可能是您自己的。

You are always using a package, even if you don't use the package declaration. By default, you're working in package main.

All variables you declare with our are package variables and should be available package wide. Here's an example:

#! /usr/bin/env perl
# test2.pl

use strict;
use warnings;

our $foo = "bar";
1;

Since $foo is declared as a package variable, it will be available in other programs:

#! /usr/bin/env perl
use strict;
use warnings;

require "test2.pl";

our $foo;
print "The value of \$foo is $foo\n";

Now I've given you enough rope, I'm going to tell you not to hang yourself with it.

This is a REALLY, REALLY BAD IDEA. Notice that $foo gets a value from some sort of mysterious mechanism that's almost impossible to figure out?

Packages are too complex? Really? It's not that hard! Look at this example:

#! /usr/bin/env perl
# test2.pm

package test2;
use strict;
use warnings;

our $foo = "bar";
1;

Not much different than before except I added the package declaration and now call my program test2.pm instead of test2.pl.

Here's how I access it:

#! /usr/bin/env perl
use strict;
use warnings;

use test2;

print "The value of \$foo from package test2 is $test2::foo\n";

All I had to do was use the package name in the variable. This is a BAD IDEA, but it's way better than the REALLY, REALLY BAD IDEA shown above.

At least, you know where the value came from. It came from test2.pm. And, you could access the variable if you set it in a subroutine.

#! /usr/bin/env perl
# test2.pm

package test2;
use strict;
use warnings;

sub fooloader {
    our $foo = "bar";
}
1;

Notice that $foo is set in the subroutine fooloader. And, here's my other program to access it:

#! /usr/bin/env perl
use strict;
use warnings;

use test2;

&test2::fooloader();
print "The value of \$foo from package test2 is $test2::foo\n";

Now, you could use the Exporter to export your subroutines (and even variables), but that's not something you see too much anymore. Mainly because it is a REALLY BAD IDEA. Not as bad as the original REALLY REALLY BAD IDEA, but worse than the BAD IDEA above:

#! /usr/bin/env perl
# test2.pm

package test2;
use base qw(Exporter);

our @EXPORT = qw(fooloader);
use strict;
use warnings;

sub fooloader {
    our $foo = "bar";
}
1;

Now, I can use subroutine fooloader without the package name:

#! /usr/bin/env perl
use strict;
use warnings;

use test2;

fooloader();
print "The value of \$foo from package test2 is $test2::foo\n";

The problem, of course, is that you have no real idea where the subroutine fooloader is coming from. If you used @EXPORT_OK instead of @EXPORT, you could have then use use test2 qw(fooloader); and document where the fooloader function was coming from. It'll also help you to know not to create your own fooloader function in your own program and override the one you imported. Then, wonder why your program no longer works.

By the way, you could also export variables and not just functions. However, that becomes a REALLY, REALLY, REALLY BAD -- NO TERRIBLE IDEA because it violates every reason why you use packages in the first place. If you're going to do that, why bother with packages? Why not simple take a gun and shoot yourself in the foot?

The best and preferred way is to use object oriented Perl and do it in the THOROUGHLY CORRECT WAY. A way where you know exactly what's going on and why. And, makes it easy to figure out what your code is doing. A way that keeps errors at a minimum.

Behold the thoroughly object oriented Test2 class:

#! /usr/bin/env perl
# Test2.pm

package Test2;

sub new {
    my $class = shift;

    my $self = {};
    bless $self, $class;

    return $self;
}

sub FooValue {
    return "bar";
}
1;

And using that Test2 class:

#! /usr/bin/env perl
use strict;
use warnings;

use Test2;

my $tester = Test2->new;

print "The value of foo from package test2 is " . $tester->FooValue . "\n";

The reason this is the best way to do it is because even if you use packages, you could manipulate the value of $test2::foo and it will be changed in your entire program. Imagine if this was say $constants::pi and somewhere you changed it from 3.14159 to 3. From then on, using $constants::pi would give you the wrong value. If you use the object oriented method, you couldn't change the value of the method Constant->Pi. It will always be 3.14159.

So, what did we learn today?

We learned that it is very easy in Perl to do something that's a REALLY, REALLY BAD IDEA, but it doesn't take all that much work to use packages, so it merely becomes a BAD IDEA. And, if you start learning a bit of object oriented Perl, you can actually, without too much effort, do it all in the THOROUGHLY CORRECT WAY.

The choice is yours to make. Just remember the foot you're shooting will probably be your own.

西瑶 2024-12-13 05:53:44

它将与我们的一起使用。

$ cat out.pl
our $var = "test";
require("inside.pm");

$ cat inside.pm 
print "Testing...\n";
print "$var\n";

$ perl out.pl
Testing...
test

这是有效的,因为 our 使 $var 成为全局的,并且 inside.pm 正在 $var 的作用域中执行定义的。不确定这是推荐的技术,但这仍然是一个有趣的问题!

编辑:需要根据评论澄清(好的补丁)答案:

来自 关于 Perl 函数我们的的文档:

our 将一个简单名称与当前包中的包(读取:全局)变量关联起来,以便在当前词法范围内使用。换句话说,ourmystate 具有相同的作用域规则,但不一定创建变量。

因此,使用our,我们得到当前包(这里可能是main)的$var,并且我们可以在其范围内使用它。实际上,它对于您需要的文件中的代码来说是“全局”的。

引入真正的全局时没有our,因为变量默认为全局。但我不知道有谁会推荐他们。

It will work with our.

$ cat out.pl
our $var = "test";
require("inside.pm");

$ cat inside.pm 
print "Testing...\n";
print "$var\n";

$ perl out.pl
Testing...
test

This works because our makes $var global, and inside.pm is being executed in the scope with $var defined. Not sure it is recommended technique, but it is an interesting question nevertheless!

EDIT: Need to clarify (okay patch) the answer based on a comment:

From the documentation on the Perl function our:

our associates a simple name with a package (read: global) variable in the current package, for use within the current lexical scope. In other words, our has the same scoping rules as my or state, but does not necessarily create a variable.

So using our, we get $var with the current package (here probably main) and we can use it in its scope. In effect it is then "global" to the code in the file you are requiring-in.

A true global is introduced without the our, because variables default to global. But I don't know anyone that would recommend them.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文