如何实现Perl与Python混合编程
1个回答
展开全部
推荐方案 Inline::Python,以Perl作为母体调用Python。
这货没什么依赖,CPAN安装或者自己编译都很容易。
边举栗子便说明:
1. Perl 使用 Python 中定义的变量
#!/usr/bin/perl -wuse strict;use Inline 'Python' => <<'END';a = 1ENDprint $a;
首先从这个栗子我们可以学习Inline::Python的程序布局:一个典型的用法是把Python代码以
use Inline 'Python' => <<'END';END
这样的Perl多行字符串的形式包裹。当然包裹Python代码的方法还有很多种,详见Inline::Python的文档。
然而不幸的是,这个栗子是行不通的。我们继续往下看。
2 Perl 使用 Python 中定义的函数
代码:
#!/usr/bin/perl -wuse strict;use Inline 'Python' => <<'END';def Foo(*args): print "==Python Def==" for a in args: print type(a) print aENDFoo(1); #[1]Foo('Hello'); #[2]Foo('Hello','World'); #[3]Foo(('Hello','World')); #[4]Foo(['Hello','World']); #[5]Foo({'Hello' => 1,'World' => 2}); #[6]
这段代码可以正常运行。在Python区块中定义的函数在Perl中可见。最为关心的是参数传递问题,逐条分析:
#[1] Perl 传入数字,Python也会理解为数字。
#[2] Perl 传入STRING类型,Python会理解为str类型。
#[3] 函数支持多个参数。
#[4] Perl 传入ARRAY值(即@)类型,Python会理解为多个参数。由于在Perl中,HASH值类型(即%)实际上是一种特殊的ARRAY,Python的处理方式应相同。
#[5] Perl 传入ARRAY的引用,Python会理解为list。
#[6] Perl 传入HASH的引用,Python会理解为dict。
返回值的问题同理。
3 传递function引用
有时候需要向Python传递“函数指针”以实现回调。Inline::Python已经照顾到了这种需求:
#!/usr/bin/perl -wuse strict;use Inline 'Python' => <<'END';def Foo(func): print type(func) func({'Hello' : 1,'World' : 2})ENDuse Data::Dumper;sub Bar {
print Dumper shift;}Foo(\&Bar);
它的运行结果:
<type '_perl_sub'>
$VAR1 = {
'World' => 2,
'Hello' => 1
};
Inline::Python为函数引用建立了一个类型_perl_sub。在Python中,这个类型的值可以当成函数对象来使用。
顺便这个例子验证了Python的dict会被Perl理解为HASH引用。
能再复杂一点么?找个对象怎么样?
4 例化Python中定义的类
作为面向对象的语言,Python中很多功能都是以提供类的方式实现的。
看代码:
#!/usr/bin/perl -wuse strict;use Inline 'Python' => <<'END';class Bar: def __init__(self,p): self.p = p def foo(self,q): print self.p + qENDmy $bar = Bar->new(1);$bar->foo(2);
这个例子说明,如果在Python区块中定义了类Bar,那么在Perl环境中就相当于有了一个package Bar。Inline::Python会自动提供一个构造函数new。
说到这里基本的问题差不多都解决了。小伙伴们可以利用Inline::Python,足不出户,在Perl中就可以调用各种稀奇古怪的第三方Python库了。
能不能再复杂点,都OO了……
5 继承Python中定义的类
写这样的代码也不难:
#!/usr/bin/perl -wuse strict;use Inline 'Python' => <<'END';class Bar: def __init__(self,p): self.p = p def foo(self,q): print self.p + qENDpackage Foo;our @ISA = ('Bar');sub new {
my $class = shift;
my $p = shift;
my $self = $class->SUPER::new($p);
return bless $self,$class;}sub bar {
my $self = shift;
my $q = shift;
print $self->{p} - $q; }1;package main;my $foo = Foo->new(1);$foo->foo(2);$foo->bar(3);
几个要点需要注意:
1) 用Perl内置的@ISA继承Python提供的类。
2) 用SUPER保留字访问父对象,别忘了和类名bless在一起。
3) 如果父对象定义了变量,用HASH key的方法能访问到。也就是说,Python里的 self.p 相当于 Perl中的 $self->{p}
能不能再复杂一点……比如让Perl的类或者对象在Python里可见?
6 使Perl定义的对象在Python中可见
实验表明,“使Perl定义的类在Python中可见” 是行不通的。但对象可以。
#!/usr/bin/perl -wuse strict;use Inline 'Python' => <<'END';def Bar(cls): print type(cls) cls.bar(2)ENDpackage Foo;sub new {
my $class = shift;
my $p = shift;
my $self = {'p' => $p};
return bless $self,$class;}sub bar {
my $self = shift;
my $q = shift;
print $self->{p} - $q;}1;package main;my $foo = Foo->new(1);Bar($foo);
代码来了。我们发现Inline::Python很贴心的定义了_perl_obj这个类型,使得Python可以调用Perl package定义的函数。
总结
由于基本数据结构设计的相似性,以Perl作为母体与Python互动是很容易的事情。当然,由于OO层面的巨大差别,某些重要的细节不能做到尽善尽美,但总之,Inline::Python的出现多少能给小伙伴们带来福音,减少语言大战引起的撕逼。
这货没什么依赖,CPAN安装或者自己编译都很容易。
边举栗子便说明:
1. Perl 使用 Python 中定义的变量
#!/usr/bin/perl -wuse strict;use Inline 'Python' => <<'END';a = 1ENDprint $a;
首先从这个栗子我们可以学习Inline::Python的程序布局:一个典型的用法是把Python代码以
use Inline 'Python' => <<'END';END
这样的Perl多行字符串的形式包裹。当然包裹Python代码的方法还有很多种,详见Inline::Python的文档。
然而不幸的是,这个栗子是行不通的。我们继续往下看。
2 Perl 使用 Python 中定义的函数
代码:
#!/usr/bin/perl -wuse strict;use Inline 'Python' => <<'END';def Foo(*args): print "==Python Def==" for a in args: print type(a) print aENDFoo(1); #[1]Foo('Hello'); #[2]Foo('Hello','World'); #[3]Foo(('Hello','World')); #[4]Foo(['Hello','World']); #[5]Foo({'Hello' => 1,'World' => 2}); #[6]
这段代码可以正常运行。在Python区块中定义的函数在Perl中可见。最为关心的是参数传递问题,逐条分析:
#[1] Perl 传入数字,Python也会理解为数字。
#[2] Perl 传入STRING类型,Python会理解为str类型。
#[3] 函数支持多个参数。
#[4] Perl 传入ARRAY值(即@)类型,Python会理解为多个参数。由于在Perl中,HASH值类型(即%)实际上是一种特殊的ARRAY,Python的处理方式应相同。
#[5] Perl 传入ARRAY的引用,Python会理解为list。
#[6] Perl 传入HASH的引用,Python会理解为dict。
返回值的问题同理。
3 传递function引用
有时候需要向Python传递“函数指针”以实现回调。Inline::Python已经照顾到了这种需求:
#!/usr/bin/perl -wuse strict;use Inline 'Python' => <<'END';def Foo(func): print type(func) func({'Hello' : 1,'World' : 2})ENDuse Data::Dumper;sub Bar {
print Dumper shift;}Foo(\&Bar);
它的运行结果:
<type '_perl_sub'>
$VAR1 = {
'World' => 2,
'Hello' => 1
};
Inline::Python为函数引用建立了一个类型_perl_sub。在Python中,这个类型的值可以当成函数对象来使用。
顺便这个例子验证了Python的dict会被Perl理解为HASH引用。
能再复杂一点么?找个对象怎么样?
4 例化Python中定义的类
作为面向对象的语言,Python中很多功能都是以提供类的方式实现的。
看代码:
#!/usr/bin/perl -wuse strict;use Inline 'Python' => <<'END';class Bar: def __init__(self,p): self.p = p def foo(self,q): print self.p + qENDmy $bar = Bar->new(1);$bar->foo(2);
这个例子说明,如果在Python区块中定义了类Bar,那么在Perl环境中就相当于有了一个package Bar。Inline::Python会自动提供一个构造函数new。
说到这里基本的问题差不多都解决了。小伙伴们可以利用Inline::Python,足不出户,在Perl中就可以调用各种稀奇古怪的第三方Python库了。
能不能再复杂点,都OO了……
5 继承Python中定义的类
写这样的代码也不难:
#!/usr/bin/perl -wuse strict;use Inline 'Python' => <<'END';class Bar: def __init__(self,p): self.p = p def foo(self,q): print self.p + qENDpackage Foo;our @ISA = ('Bar');sub new {
my $class = shift;
my $p = shift;
my $self = $class->SUPER::new($p);
return bless $self,$class;}sub bar {
my $self = shift;
my $q = shift;
print $self->{p} - $q; }1;package main;my $foo = Foo->new(1);$foo->foo(2);$foo->bar(3);
几个要点需要注意:
1) 用Perl内置的@ISA继承Python提供的类。
2) 用SUPER保留字访问父对象,别忘了和类名bless在一起。
3) 如果父对象定义了变量,用HASH key的方法能访问到。也就是说,Python里的 self.p 相当于 Perl中的 $self->{p}
能不能再复杂一点……比如让Perl的类或者对象在Python里可见?
6 使Perl定义的对象在Python中可见
实验表明,“使Perl定义的类在Python中可见” 是行不通的。但对象可以。
#!/usr/bin/perl -wuse strict;use Inline 'Python' => <<'END';def Bar(cls): print type(cls) cls.bar(2)ENDpackage Foo;sub new {
my $class = shift;
my $p = shift;
my $self = {'p' => $p};
return bless $self,$class;}sub bar {
my $self = shift;
my $q = shift;
print $self->{p} - $q;}1;package main;my $foo = Foo->new(1);Bar($foo);
代码来了。我们发现Inline::Python很贴心的定义了_perl_obj这个类型,使得Python可以调用Perl package定义的函数。
总结
由于基本数据结构设计的相似性,以Perl作为母体与Python互动是很容易的事情。当然,由于OO层面的巨大差别,某些重要的细节不能做到尽善尽美,但总之,Inline::Python的出现多少能给小伙伴们带来福音,减少语言大战引起的撕逼。
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询