perl 翻译为 python

Python033

perl 翻译为 python,第1张

1. Perl 中的标量

a. Perl 中的标量在Python 中对应为数字类型和字符串类型

Perl 的标量是字符串还是数值会根据上下文自动判断,但是Python 不会这样做。

下面的代码是你在Perl 中习以为常的操作

[plain] view plaincopy在CODE上查看代码片派生到我的代码片

my ($string, $number) = ("1", )

$number = $string + "1" # $string 和"1" 都被解释为数值

say $number

$string = $number.1 # $number 和1 都被解释为字符串

say $string

但是Python 中你必须显式的指定数据类型

[python] view plaincopy在CODE上查看代码片派生到我的代码片string = "1" number = int (string) + 1 # 必须显式转换为数值类型

print (number)

string = str (number) + "1" # 同样必须显式转换为字符串

print (string)

b. Perl 的标量不支持下标运算,但是Python 的字符串可以

Python 中你可以很方便的用下标索引字符串(而且和Perl 中的列表一样也支持用负数做反向索引)

[python] view plaincopy在CODE上查看代码片派生到我的代码片

s = "A string" print (s[2:])

但是Perl 的标量就无法这样操作,相同的操作必须用列表切片完成

[plain] view plaincopy在CODE上查看代码片派生到我的代码片

$_ = "A string"

say ((split //)[2..split //])

c. Perl 中的heredoc 式标量赋值在Python 中可以使用三引号运算符完成

[plain] view plaincopy在CODE上查看代码片派生到我的代码片

@_ = <Everthing is

in

the array

END

say "@_"

下面是等价的Python 代码,注意第一行是紧跟三引号运算符之后的

[python] view plaincopy在CODE上查看代码片派生到我的代码片string = '''''Everthing is

in

the array

'''

print (string)

2. Perl 中的列表

a. Perl 中的列表Python 中对应为列表和元组

下面是Python 中倒序排序一个列表的操作

[python] view plaincopy在CODE上查看代码片派生到我的代码片

my_list = ["Hello", "Python"]

my_list.append ("World")

my_list += ["!"]

print (my_list)

my_list.sort ()

my_list.reverse ()

for string in my_list:

print (string)

对应的Perl 同性质操作的版本

[plain] view plaincopy在CODE上查看代码片派生到我的代码片

@_ = qw/Hello Perl/

push @_, 'World'

@_ = (@_, '!')

print "@_\n"

@_ = reverse sort @_

say for @_

b. 常用的splice 操作在Python 中可以用过index () 方法和del 操作完成

下面是Perl 中常用的splice 操作

[plain] view plaincopy在CODE上查看代码片派生到我的代码片

@_ = qw/Hello Perl !/

splice @_, 2, 0, "World" # 插入元素

say "@_"

my @removed = splice @_, 1, 2 # 提取一段元素并在原列表删除

print "@_\n@removed\n"

Python 中对应的操作

[python] view plaincopy在CODE上查看代码片派生到我的代码片

my_list = ["Hello", "Python", "!"]

my_list.insert (2, "World") # 插入元素

print (my_list)

removed = my_list[1:2] # 提取一段元素

del my_list[1:2]# 并在原列表删除

print (my_list)

print (removed)

注意:Python 中元组和列表的区别

元组创建后是只读的,但是列表随时都可以被修改。3. Perl 中的哈希

a. Perl 中的哈希Python 中对应为字典和集合

一个Perl 哈希按照键值升序遍历的操作如下

[plain] view plaincopy在CODE上查看代码片派生到我的代码片

my %hash = (

"first" =>1,

"second" =>2,

"third" =>3 )

say "$_ =>$hash{$_}" for sort keys %hash

Python 中代码如下(注意定义变为花括号)

[python] view plaincopy在CODE上查看代码片派生到我的代码片

my_hash = {

"first" : 1,

"second" : 2,

"third" : 3 }

items = sorted (my_hash.items (), key=lambda e:e[1], reverse=False)

for item in items:

print (item[0], ':', item[1])

注意:Python 中集合与字典的不同之处

(a) 仅包含键,但是没有值

(b) set 可变,但是frozenset 不可变(如其名)4. Python 强类型的判断和赋值

一个非常大的不同之处:Perl 中赋值号默认的行为是拷贝,但是Python 中赋值号会创建一个对象的引用。

另外,因为和弱类型的Perl 不同,Python 是一门强类型语言,所以也有判断对象类型的必要。

下面代码演示了这些区别,首先是一段Python 代码

[python] view plaincopy在CODE上查看代码片派生到我的代码片

lst = [1, 2, 3]

lst2 = lst # lst2 是lst 的一个引用

print (lst)

lst2[1] = 2.5 # 所以修改lst2 也会引起lst 的变化

print (lst)

lst3 = copy.deepcopy (lst) # lst3 是lst 的一个深拷贝

lst3[1] = 2 print (lst) # 修改lst3 不会引起lst 的变化

# 因为Python 是强类型语言,所以需要类型判断操作

if lst == lst2: # 如果s 和s2 值相同

print ("lst equal to lst2")

if lst is lst2: # 如果s 和s2 是指向同一个对象的引用

print ("lst and lst2 is the same")

if type (lst) is type (lst3): # 如果s 和s3 类型相同

print ("lst and lst3 has same type")

下面是与之完全等价的Perl 代码,对比一下你就会很快了解其中的差别

[plain] view plaincopy在CODE上查看代码片派生到我的代码片

my @lst = (1..3)

my $lst2 = \@lst # lst2 是lst 的一个引用

say "@$lst2"

$lst2->[1] = 2.5 # 所以修改lst2 也会引起lst 的变化

say "@$lst2"

my @lst3 = @lst # lst3 是lst 的一个深拷贝

$lst3[1] = 2

say "@lst"# 修改lst3 不会引起lst 的变化

=pod

因为Perl 是弱类型语言,所以不需要类型判断操作

但是Perl 中仍然可以做这样的操作——虽然没什么意义

=cut

say "lst equal to lst2"

if @lst == @$lst2 # 如果s 和s2 值相同

say "lst and lst2 is the same"

if \@lst == $lst2 # 如果s 和s2 是指向同一个对象的引用

say "lst and lst3 has same type"

if ref \@lst eq ref \@lst3# 如果s 和s3 类型相同

5. Perl 中的“上下文”

上下文的判断几乎已经成了一名Perl 用户不可或缺的第六感,一个显而易见的例子是当你定义一个列表

[plain] view plaincopy在CODE上查看代码片派生到我的代码片

my @lst = (1..3)

当你循环遍历的时候,你深知把for 循环

[plain] view plaincopy在CODE上查看代码片派生到我的代码片

say for @lst # 列表上下文

替换为While 循环

[plain] view plaincopy在CODE上查看代码片派生到我的代码片

say while @lst# 标量上下文

究竟会得到什么灾难性的后果。

但是在Python 中你不必担心这个:Python 对于数据类型的解释很明确,不会因为上下文环境不同而改变,当你定义一个列表

[python] view plaincopy在CODE上查看代码片派生到我的代码片

lst = [1, 2, 3]

之后,你永远不必担心在什么特殊的上下文中lst 会被Python 解释为数值3。

面向对象编程1. 几点明显的异同

Perl 和Python 的面向对象给人的感觉是后者明显比前者更加规范,下面是自己感受最明显的几点异同。

a. 真的是面向对象么?1). Perl 中的“面向对象”更像是“面向过程”的文字游戏:类通过包实现、方法通过包中定义的函数实现、类的继承和方法的重载通过@ISA 列表查找循序实现、私有方法通过指向匿名函数的my 引用实现(因为my变量是本文件可见的)、运算符重载通过指向函数的引用实现、对象中成员变量的访问通过bless 到类名的引用实现……这样如果说有好处,那就是编程可以非常灵活——你可以用一个父类的多个子类共同继承出一个类(例如从哺乳动物中人类和猫类继承出一种新生物),Perl 完全对这种行为不在意,只要你确信这种近亲结婚的方式真的是你需要达到的目的。当然坏处显而易见——你可以轻而易举把代码写的糟糕透顶。所以Perl 的“面向对象”给人的感觉只是“面向过程”的另一种玩法——面向过程的本质没变,但是面向对象的效果达到了。2). Python 中的“面向对象”比Perl 要严谨和规范许多,非常类似于Java,如果你熟悉Java 或者C++,那么你会很好理解Python 的面向对象编程。

b. 包和类1). Perl 中两者完全等价,一个包就是一个类(pm 是Perl 模块的意思,但是它又被叫做包,而包就是类的意思 ← ←)。2). Python 中一个包可以包含多个模块,一个模块可以包含多个类。

c. 静态方法

Perl 和Python 中静态方法都是第一个参数不是类的引用的方法,但是稍有不同:1). Perl 中静态方法第一个参数是类名,可以通过bless 新的引用到类名来操作对象类型(例如你在构造方法里做的那样)。2). Python 中静态方法完全无法操作对象类型。

d. 私有方法:1). Perl 中的私有方法通过my 变量只有当前文件可见的性质,用保存匿名函数的my 引用来达到“私有”的目的(“面向对象”的文字游戏)。2). Python 中吧以“__”开头的方法都当作私有方法,通过方法名会变成"_类名__方法名" 的形式来避免其他类调用该方法,但是你仍然可以通过手动变换后的方法名直接调用私有方法。

e. 方法的传参:1). Perl 中一般将散列的引用bless 到类名,所以传参可以十分灵活,如果构造函数允许,参数个数和位置根本无关紧要,但是随之造成的问题就是可能引发混乱。2). Python 中方法声明无法把无默认值的参数放在有默认值的参数后面,但是因为实参可以通过给出参数名手动显式指定,所以次序也可以无关紧要。

f. 运算符重载:1). Perl 通过use overload 模块指定方法的引用来达到重载运算符的目的。2). Python 中通过一组特殊名称的方法来重载运算符。

g. 父类方法重载:1). Perl 中通过@ISA 列表的搜索顺序来达到重载父类方法的目的(子类的同名方法会被优先搜索到),并且可以显式SUPER 伪类访问被覆盖的基类方法(就如你经常在析构方法中做的一样)。2). Python 的重载更加正式,形式非常类似于C++。

h. 继承:1). Perl 的继承只是操作了@ISA 列表,子类中没有的方法会在@ISA 中寻找方法名,因此这种行为得到的结果和面向对象编程的继承相同。UNIVERSAL 是所有类的祖先类,提供了isa 方法用来测试继承关系。2). Python 的继承类似于C++,显式指定了要继承的父类,object 类是所有类的祖先类,提供issubclass 方法用来测试继承关系。2. 一个演示异同的例子

下面的两个例子都会有相同的输出,演示了Perl 和Python 中类的构造、析构、公有方法、私有方法、运算符重载、继承、父类方法重载等。

下面是预期的输出

[plain] view plaincopy在CODE上查看代码片派生到我的代码片=My name's Lucy, 2 years old. Adoption me please.

+I am hungry offen.

-My name's Leia, 1 years old. My host is iSpeller.

+I hate milk but my host give me offen.

-My name's Lucy, 2 years old. My host is iSpeller.

+I hate milk but my host give me offen.

#!/usr/bin/perl

use strict

our (@input,%files, # 定义一个包全局数组和哈希

)

foreach (@ARGV) # 循环输入参数

{

push(@input,@ARGV) # 将输入参数push到@input

}

die "Usage: $0 <xxxxx.cmd>...\n" unless @input# 如果@input为空,则退出并显示错误信息

foreach my $cmd (@input) # 循环@input,并将每一项赋值给$cmd

{

open(CMD,$cmd) || die "Cannot open $cmd\n" # 使用CMD文件句柄打开文件$cmd,如果打开失败则退出并显示错误信息

while (<CMD>) # 循环读取文件句柄,并将每一行赋值给内置变量$_

{

chop # 删除$_的最后一个字符(应该是换行符)

next unless /-o\s/ # 如果$_不匹配/-o\s/,则跳过本次循环

$_=$' # 上个匹配信息后的字符串赋值给$_

s/\s.*$// # 将$_中的"\s.*$"替换成空(相当于删除)

s/\.o$/.D/ # 将$_中的".o"结尾的替换成".D"

my $depFile=$_ # 赋值

open (D,$depFile) # 使用文件句柄D打开$depFile文件

my $dir=<D># 读取一行数据

chop($dir) # 去除最后一个字符

$dir=~s/\#// # 替换#号

while (<D>) # 循环读取每一行,并赋值给$_

{

chop # 去除$_的最后一个字符

s/\\$// # 替换

s/.*:\s// # 替换

foreach my $file (split) # 将$_以" "(空格)拆分成数组,并循环

{

$file=$dir."/".$file unless $file=~m/^\// # 如果$file的第一个字符不是"/",则在$file的前面添加$dir."/",PS: perl中"."(点号)用来拼接字符串

$files{$file}++ # 给哈希变量赋值,这句相当于$files{$file} = 1

}

}

}

}

foreach my $file (keys %files) # 循环%files的key

{

print $file,"\n" # 输出

}

如有不懂的地方继续追问