Ruby 学习笔记(和 Python3 语法进行对比)

我是先接触 Python3 的,如果我自己主动来选择,可能不会再去学 Ruby(可能先入为主的思想太根深蒂固了,不过最主要的还是太懒了),然鹅由于种种原因,我还是要来看一下Ruby(真是天理难容,/大哭/大哭/大哭),虽然大家都说 Ruby 和 Python 的语法差不多(好像确实如此——不过既然如此,为何要弄两个来折磨大家呢?),所以学习的时候我准备把这两种语言的语法对比一下(给自己找点看下去的动力),毕竟语言不过是解决问题的工具,没什么好坏之分(强行安慰一下自己)。至于开发工具嘛!JetBrains 的全家桶真香,Ruby 和 Python 分别用 RubyMine 和 PyCharm 就好。

 

Ruby on rails 是 Ruby 的 Web 应用程序框架,据说很牛掰,不过咱也不知道咱也不敢问,等我后面接触到了再说,目前的话,就先当个 surprise 期待着吧!好东西自然分享给大家了,下面的参考资料很不错的哟,也是本文的主要参考资料:

learn x in y minutes where x= Ruby :Learn ruby in Y Minutes

learn x in y minutes where x= Python :Learn Python in Y Minutes

Ruby 代码风格指南:Ruby Coding Style Guides · Ruby China

Ruby 源码安装

解压一个安装包,进入解压文件夹。

[root@master packages]# ll | grep ruby-2.7.1
drwxr-xr-x. 28 root    root         8192 Aug 23 14:52 ruby-2.7.1
-rw-r--r--.  1 root    root     16816471 Mar 31 21:12 ruby-2.7.1.tar.gz
[root@master packages]# cd ruby-2.7.1
[root@master ruby-2.7.1]# pwd
/root/packages/ruby-2.7.1

编译安装 :

[root@master ~]# ./configure --prefix=/usr/local/ruby-2.7.1
[root@master ~]# make && make install

添加以下软连接,否则可能提示找不到:

[root@master packages]# ln -fs /usr/local/ruby-2.7.1/bin/ruby /usr/bin/ruby
[root@master packages]# ln -fs /usr/local/ruby-2.7.1/bin/gem /usr/bin/gem
[root@master packages]# ln -fs /usr/local/ruby-2.7.1/bin/bundle /usr/bin/bundle

# ln -fs /usr/local/ruby-2.7.1/bin/irb /usr/local/bin/irb
# ln -fs /usr/local/ruby-2.7.1/bin/pry /usr/local/bin/pry

安装完成: 

[root@master ~]# ruby -v
ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-linux]
[root@master ~]# gem -v
3.1.2
[root@master ~]# bundle -v
Bundler version 2.1.4

 我是在 centOS 虚拟机安装的解释器,可以使用 yum install ruby 命令安装,但是安装的可能不是最新的:

Ruby 学习笔记(和 Python3 语法进行对比)_第1张图片

Ruby 依赖包安装

依赖包的话就使用 gem install 命令进行安装,有时候由于网络和墙的原因会一直卡住不动,不过也可以手动下载依赖包进行安装,比如说我安装 pry 的时候就碰到了这种情况,最后手动下载 .gem 文件安装成功(记得添加 --local 参数哟,表示你想使用本地文件进行安装,不然 gem 又会从源地址去下载去了):

[root@master packages]# gem install --local pry-0.13.1.gem 
Successfully installed method_source-1.0.0
Successfully installed coderay-1.1.3
Successfully installed pry-0.13.1
Parsing documentation for method_source-1.0.0
Installing ri documentation for method_source-1.0.0
invalid options: -SNw2
(invalid options are ignored)
Parsing documentation for coderay-1.1.3
Installing ri documentation for coderay-1.1.3
Parsing documentation for pry-0.13.1
Installing ri documentation for pry-0.13.1
Done installing documentation for method_source, coderay, pry after 3 seconds
3 gems installed

安装后版本如下:

[root@master ~]# ruby --version
ruby 2.0.0p648 (2015-12-16) [x86_64-linux]
[root@master ~]# python3 --version
Python 3.6.8

[root@master ~]# gem --version
2.0.14.1
[root@master ~]# pip3 --version
pip 9.0.3 from /usr/lib/python3.6/site-packages (python 3.6)


# 可以先用 wget 命令下载依赖文件
[root@master ~]# ll
-rw-r--r--.  1 root root     92672 May 30 15:24 coderay-1.1.3.gem
-rw-r--r--.  1 root root     13824 Mar 19 21:11 method_source-1.0.0.gem
-rw-r--r--.  1 root root    155136 Apr 12 15:35 pry-0.13.1.gem

[root@master ~]# gem install --local coderay-1.1.3.gem 
[root@master ~]# gem install --local method_source-1.0.0.gem 
[root@master ~]# gem install --local pry-0.13.1.gem 
[root@master ~]# pry --version
Pry version 0.13.1 on Ruby 2.0.0
[1] pry(main)> puts "Hello World"
Hello World
=> nil
[2] pry(main)> 

Hello World

pry(或者自带的 irb,pry 会更好用一些)可以打开 Ruby 控制台,就像在命令行输入 python3 会进入 Python 命令行一样。话不多说,先来个 Hello world 看看!哇,这俩货的 Hello world 用法都是一样的,你敢信?除了 Ruby 的输出多一个 => nil 之外,好像确实没什么区别,这儿的 nil 你可以把它当成 Python3 里边的 None,也就是箭头 => 右边的 nil 是它的返回值。毕竟这儿只是输出个字符串,自然没什么好返回的。还有一点,Ruby 使用 true 和 false 表示真和假,Python3 使用 True 和 False表示真和假,看起来 Ruby 确实更简化些,至少敲字符的时候省去了摁住 Shift 键的烦恼。

# Ruby
[root@master ~]# pry
[1] pry(main)> print "Hello World"
Hello World=> nil
[2] pry(main)> 
# Python3
[root@master ~]# python3
Python 3.6.8 (default, Aug  7 2019, 17:28:10) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-39)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> print("Hello World")
Hello World

先不要慌,咱们继续往下看,Ruby 的输出有 print ,puts,p,可见花样是玩出了新高度的,四则运算这块好像区别也不大,只不过涉及到除法的时候,Python3 输出的结果是 Float 型的,如果是 Python2,就和这儿的 Ruby 是一样的了:

# Ruby
irb(main):001:0> puts "Hello World"
Hello World
=> nil
# 注意输出的字符串和返回的 nil 没在同一行,相当于输出后换行了

irb(main):002:0> p "Hello World"
"Hello World"
=> "Hello World"
# 注意字符串给自动添加上了双引号,告诉你输出的是个 “字符串”,而且返回值不是 nil 了

Here Document

# test.rb

puts <<~EOF
  this is the first line
  this is the second line
EOF

[root@master ruby_learning]# ruby test.rb
this is the first line
this is the second line

------------------------------------------------------
# test.rb

puts <<-EOF
  this is the first line
  this is the second line
EOF

[root@master ruby_learning]# ruby test.rb
  this is the first line
  this is the second line

Proc (lambda)

Proc 和 lambda 的区别

# lambda 函数参数检查更为严格
[1] pry(main)> prc1 = Proc.new do |a, b, c|
[1] pry(main)*   puts [a, b, c].inspect
[1] pry(main)* end  
=> #
[2] pry(main)> prc1.call(1, 2)
[1, 2, nil]
=> nil
[3] pry(main)> prc2 = lambda do |a, b, c|
[3] pry(main)*   puts [a, b, c].inspect
[3] pry(main)* end  
=> #
[4] pry(main)> prc2.call(1, 2)
ArgumentError: wrong number of arguments (given 2, expected 3)
from (pry):5:in "block in __pry__"

------------------------------------------------------------
# lambda 可以用 return 返回值
[5] pry(main)> def power_of(n)
[5] pry(main)*   lambda do |x|
[5] pry(main)*     return x ** n
[5] pry(main)*   end  
[5] pry(main)* end  
=> :power_of
[6] pry(main)> cube = power_of(3)
=> #
[7] pry(main)> cube.call(5)
=> 125
[8] pry(main)> def power_of(n)
[8] pry(main)*   Proc.new do |x|
[8] pry(main)*     return x ** n
[8] pry(main)*   end  
[8] pry(main)* end  
=> :power_of
[9] pry(main)> cube = power_of(3)
=> #
[10] pry(main)> cube.call(5)
LocalJumpError: unexpected return
from (pry):18:in `block in power_of'

Proc 自定义带块函数

[11] pry(main)> def total(from, to, &block)
[11] pry(main)*   result = 0  
[11] pry(main)*   from.upto(to) do |num|  
[11] pry(main)*     if block    
[11] pry(main)*       result += block.call(num)      
[11] pry(main)*     else  
[11] pry(main)*       result += num
[11] pry(main)*     end  
[11] pry(main)*   end  
[11] pry(main)*   return result
[11] pry(main)* end  
=> :total
[12] pry(main)> total(1, 10)
=> 55
[13] pry(main)> total(1, 10) { |num| num ** 2 }
=> 385

%Q, %q, %W, %w, %x, %r, %s, %i

边界符号可以用如下其他符号替换

|...|, #...#, !...!, +...+, (...), [...], <...>, /.../
# Ruby
[8] pry(main)> name = "Ruby"
=> "Ruby"

[9] pry(main)> %Q{hello, my name is #{name}}
=> "hello, my name is Ruby"

[10] pry(main)> %q{hello, my name is #{name}}
=> "hello, my name is \#{name}"

[15] pry(main)> %W{hello world #{name}}
=> ["hello", "world", "Ruby"]

[16] pry(main)> %w{hello world #{name}}
=> ["hello", "world", "\#{name}"]

[17] pry(main)> %x{ls}
=> "debugtest.rb\ngrep.rb\ntest1.txt\ntest2.rb\ntest.py\ntest.rb\ntest.txt\n"

[18] pry(main)> what_ruby = 'this is ruby'
=> "this is ruby"

[19] pry(main)> %r{/home/#{what_ruby}}
=> /\/home\/this is ruby/

[20] pry(main)> %s{hello}
=> :hello

[21] pry(main)> %i{hello world}
=> [:hello, :world]

语法特点

括号

Ruby 语法特点是括号能去掉的它就去掉了(这种特点让他的语法更像是介于 Shell 和 Python之间),比如数组反转(print,puts, p之类),使用的时候可加可不加括号(不强制!如果你之前习惯了 Shell 的语法,你可能习惯性不加括号;如果你之前习惯了 Python3 的语法,你可能习惯性加上括号):

[136] pry(main)> names
=> ["I", "am", "Looking"]
[137] pry(main)> names.reverse
=> ["Looking", "am", "I"]
[138] pry(main)> names.reverse()
=> ["Looking", "am", "I"]
[139] pry(main)> names
=> ["I", "am", "Looking"]
[140] pry(main)> print "Hello World"
Hello World=> nil
[141] pry(main)> print("Hello World")
Hello World=> nil

就算括号实在不愿去掉或者实在没法去掉,也尽量让你少摁 ←键,比如就出现了下面这种 names.[]0 的骚操作:

[134] pry(main)> names
=> ["I", "am", "Looking"]
[142] pry(main)> names[0]
=> "I"
[135] pry(main)> names.[]0
=> "I"

而 Python 在 Python3 以后更加强调加括号表示调用,不加括号表示引用,所以在 Python3 以后的版本都不支持(不兼容) print "Hello World" 了,必须用 print("Hello World") 才可以。

[root@master ~]# python
Python 2.7.5 (default, Jun 20 2019, 20:27:34) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-36)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> print "Hello World"
Hello World
>>> 
[6]+  Stopped                 python
[root@master ~]# python3
Python 3.6.8 (default, Aug  7 2019, 17:28:10) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-39)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> print "Hello World"
  File "", line 1
    print "Hello World"
                      ^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print("Hello World")?
>>> 

end

Ruby另外一个特点应该就是那些个数不清的 end 了,当然 end 也不是Ruby独有的,像MATLAB之类的,语法也有这种特点(这样的话,代码是否能运行就不依赖于缩进了)。

! 和 ?

可以把它当做一种默认的约定的规范, 只是为了根据语意实现自释义,所以一般来说大家都愿意遵守这种规范。

“!”,这个符号通常情况下本身就有小心警告的意思。因此,方法调用如果使用没有叹号结尾的方法,你在调用它的时候会得到当前对象的一个拷贝而不会修改原始对象,而如果使用带有叹号的方法,你在调用它的时候会直接修改当前对象的值(这个时候要时刻提醒自己注意原对象的改变)。

[78] pry(main)> company_name = "Dunder Mifflin"
=> "Dunder Mifflin"
[79] pry(main)> company_name.upcase
=> "DUNDER MIFFLIN"
[80] pry(main)> company_name
=> "Dunder Mifflin"
[81] pry(main)> company_name.upcase!
=> "DUNDER MIFFLIN"
[82] pry(main)> company_name
=> "DUNDER MIFFLIN"

[31] pry(main)> names = ["I", "am", "Looking"]
=> ["I", "am", "Looking"]
[32] pry(main)> names.reverse
=> ["Looking", "am", "I"]
[33] pry(main)> names
=> ["I", "am", "Looking"]
[34] pry(main)> names.reverse!
=> ["Looking", "am", "I"]
[35] pry(main)> names
=> ["Looking", "am", "I"]

“?”,被用于标示谓词,即返回Boolean值的方法,如Array.empty?(判断数组中元素是否为空),当然自己定义方法的时候如果返回布尔类型的话也可以加上“?”。

[84] pry(main)> array = [1, 2, 3, 4, 5]
=> [1, 2, 3, 4, 5]
[86] pry(main)> array.empty?
=> false

# eg
[99] pry(main)> def success?(field)
[99] pry(main)*   field.size > 5 ? true : false  
[99] pry(main)* end  
=> nil
[100] pry(main)> success?([1, 2])
=> false
[101] pry(main)> success?([1, 2, 3, 4, 5, 6])
=> true
[103] pry(main)> 

return

更严谨的说,Ruby 的方法也是尽可能不用 return,除非迫不得已(比如要提前返回一些东西)。有点像用括号一样,一般默认返回方法里边最后一个表达式的值。

# Ruby
def return_test
  "hello world"
  "I am Looking"
end

return_result = return_test
puts return_result

D:\Ruby23-x64\bin\ruby.exe D:/MyProject/Ruby/workspace/test.rb
I am Looking

Process finished with exit code 0

--------------------------------------------------------------------------------
def return_test
  return "hello world"
  "I am Looking"
end

return_result = return_test
puts return_result

D:\Ruby23-x64\bin\ruby.exe D:/MyProject/Ruby/workspace/test.rb
hello world

Process finished with exit code 0

当然,Python 也可以不用 return,除非你不需要函数返回任何东西。 

# Python3
def return_test():
    "hello world"
    "I am Looking"


return_result = return_test()
print(return_result)

"D:\Program Files\Python36\python3.exe" D:/MyProject/Python/workspace/test.py
None

Process finished with exit code 0

--------------------------------------------------------------------------------
def return_test():
    return "hello world"
    "I am Looking"


return_result = return_test()
print(return_result)

"D:\Program Files\Python36\python3.exe" D:/MyProject/Python/workspace/test.py
hello world

Process finished with exit code 0

注释

单行注释都使用 # ,多行注释稍有差别

# Ruby
# This is a comment

=begin
This is a multi-line comment.
The beginning line must start with "=begin"
and the ending line must start with "=end".

You can do this, or start each line in
a multi-line comment with the # character.
=end

puts "Hello World"
# Python
# Single line comments start with a number symbol.

"""
Multiline strings can be written
using three "s, and are often used
as documentation.
"""
print("Hello World")

基本四则运算 

# Ruby
irb(main):011:0> 1
=> 1
irb(main):012:0> 100
=> 100
irb(main):013:0> 3.1415
=> 3.1415
irb(main):014:0> 1 + 1
=> 2
irb(main):015:0> 2 - 3
=> -1
irb(main):016:0> 5 * 10
=> 50
irb(main):017:0> 100 / 4
=> 25
irb(main):018:0> 20 + 8 / 2
=> 24
irb(main):019:0> (20 + 8) / 2
=> 14
irb(main):020:0> 2 ** 3
=> 8
irb(main):021:0> Math.sin(3.1415)
=> 9.265358966049026e-05
irb(main):022:0> Math.sqrt(10000)
=> 100.0
# Python3
>>> 1
1
>>> 100
100
>>> 3.1415
3.1415
>>> 1 + 1
2
>>> 2 - 3
-1
>>> 5 * 10
50
>>> 100 / 4
25.0
>>> 20 + 8 / 2
24.0
>>> (20 + 8) / 2
14.0
>>> 2 ** 3
8
>>> math.sin(3.1415)
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'math' is not defined
>>> import math
>>> math.sin(3.1415)
9.265358966049026e-05
>>> math.sqrt(10000)
100.0

变量和对象

# Ruby
[1] pry(main)> true
=> true
[2] pry(main)> false
=> false
[3] pry(main)> nil
=> nil
[4] pry(main)> true.class
=> TrueClass
[5] pry(main)> false.class
=> FalseClass
[6] pry(main)> nil.class
=> NilClass
[11] pry(main)> !false
=> true
[12] pry(main)> !!false
=> false
[13] pry(main)> !true
=> false
[14] pry(main)> !!true
=> true
[15] pry(main)> !nil
=> true
[16] pry(main)> !!nil
=> false
[17] pry(main)> !0
=> false
[18] pry(main)> !!0
=> true
[19] pry(main)> !""
(pry):19: warning: string literal in condition
=> false
[20] pry(main)> !!""
(pry):20: warning: string literal in condition
=> true
[23] pry(main)> "hello " << "world"
=> "hello world"
[24] pry(main)> "hello " + "world"
=> "hello world"

[11] pry(main)> # 变量的作用域通过我们对它的命名进行定义
[12] pry(main)> # 以 $ 开头的变量为全局变量
[13] pry(main)> $var = "I'm a global var"
=> "I'm a global var"
[14] pry(main)> defined? $var #=> "global-variable"
=> "global-variable"
[15] pry(main)> 
[16] pry(main)> # 以 @ 开头的变量为实例变量
[17] pry(main)> @var = "I'm an instance var"
=> "I'm an instance var"
[18] pry(main)> defined? @var #=> "instance-variable"
=> "instance-variable"
[19] pry(main)> 
[20] pry(main)> # 以 @@ 开头的变量为类变量 
[21] pry(main)> @@var = "I'm a class var"
=> "class variable"
[30] pry(main)> defined? @@var #=> "class variable"
=> "class variable"
[23] pry(main)> 
[24] pry(main)> # 以大写字母开头的为常量
[25] pry(main)> Var = "I'm a constant"
=> "I'm a constant"
[26] pry(main)> defined? Var
=> "constant"

# Python3
>>> True
True
>>> False
False
>>> None
>>> type(True)

>>> type(False)

>>> type(None)

>>> not False
True
>>> not not False
False
>>> not True
False
>>> not not True
True
>>> not None
True
>>> not not None
False
>>> "hello " + "world"
'hello world'

比较运算

# Ruby
irb(main):022:0> 2 == 2
=> true
irb(main):023:0> 1 == 2
=> false
irb(main):024:0> 3 > 1
=> true
irb(main):025:0> 3 > 3
=> false
irb(main):026:0> 3 >= 3
=> true
irb(main):027:0> 3 < 1
=> false
irb(main):028:0> 3 < 3
=> false
irb(main):029:0> 3 <= 3
=> true
irb(main):030:0> "Ruby" == "Ruby"
=> true
irb(main):031:0> "Ruby" == "Python"
=> false
irb(main):032:0> 1 != 1
=> false
# Python3
>>> 2 == 2
True
>>> 1 == 2
False
>>> 3 > 1
True
>>> 3 > 3
False
>>> 3 >= 3
True
>>> 3 < 1
False
>>> 3 < 3
False
>>> 3 <= 3
True
>>> "Python" == "Python"
True
>>> "Python" == "Ruby"
False
>>> 1 != 1
False

添加判断

# Ruby
[71] pry(main)> if true
[71] pry(main)*   'if statement'  
[71] pry(main)* elsif false  
[71] pry(main)*   'else if, optional'  
[71] pry(main)* else  
[71] pry(main)*   'else, also optional'  
[71] pry(main)* end  
=> "if statement"

irb(main):033:0> a = 20
=> 20
[22] pry(main)> if a >= 10
[22] pry(main)*   puts "bigger"
[22] pry(main)* else  
[22] pry(main)*   puts "smaller"
[22] pry(main)* end  
bigger
=> nil

# 当然,对Ruby来说,缩进不缩进都无所谓啦,毕竟人家又不靠缩进吃饭,即使你像下面这么些也还是可以正常执行
# 不过,为了可读性,最好不要这么做啦!
irb(main):039:0> if a >= 10
irb(main):040:1> print "bigger"
irb(main):041:1> else
irb(main):042:1* print "smaller"
irb(main):043:1> end
bigger=> nil
irb(main):044:0> 
# Python3
# 记得一定要缩进哟
>>> if True:
...     'if statement'
... elif False:
...     'else if, optional'
... else:
...     'else, also optional'
... 
'if statement'


>>> a = 20
>>> if a >= 10:
...     print("bigger")
... else:
...     print("smaller")
... 
bigger

循环比较

# Ruby
irb(main):044:0> i = 1
=> 1
irb(main):045:0> while i <= 10
irb(main):046:1>     puts i
irb(main):047:1>     i += 1
irb(main):048:1> end
1
2
3
4
5
6
7
8
9
10
=> nil
------------------------------------------------------------
irb(main):049:0> 10.times do 
irb(main):050:1*    puts "Hello World"
irb(main):051:1> end
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
=> 10
# Python3
>>> i = 1
>>> while i <= 10:
...     print(i)
...     i += 1
... 
1
2
3
4
5
6
7
8
9
10
------------------------------------------------------------
>>> i = 1
>>> while i <= 10:
...     print("Hello World")
...     i += 1
... 
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World
Hello World

数组(列表)比较及元素遍历

数组字面量通过[]中以逗号分隔定义,且支持range定义。

  • (1)数组通过[]索引访问
  • (2)通过赋值操作插入、删除、替换元素
  • (3)通过+,-号进行合并和删除元素,且集合做为新集合出现
  • (4)通过<<号向原数据追加元素
  • (5)通过*号重复数组元素
  • (6)通过|和&符号做并集和交集操作(注意顺序)
# Ruby
irb(main):052:0> names = ["I", "am", "Looking"]
=> ["I", "am", "Looking"]
irb(main):053:0> names[0]
=> "I"
[26] pry(main)> names.first
=> "I"
[64] pry(main)> names.[] 0  # 这个操作确实有点骚
=> "I"
irb(main):054:0> names[0] = "i"
=> "i"
irb(main):055:0> names
=> ["i", "am", "Looking"]
[27] pry(main)> names.last
=> "Looking"
[28] pry(main)> names[-1]
=> "Looking"
[66] pry(main)> names << "!"
=> ["I", "am", "Looking", "!"]
[67] pry(main)> names.push("!")
=> ["I", "am", "Looking", "!", "!"]
[70] pry(main)> names.include?("Looking")
=> true


irb(main):056:0> names.size
=> 3
irb(main):057:0> names.length
=> 3

[55] pry(main)> names
=> ["I", "am", "Looking"]
[56] pry(main)> names.reverse # 不会修改原数组
=> ["Looking", "am", "I"]
[57] pry(main)> names
=> ["I", "am", "Looking"]
[58] pry(main)> names.reverse! # 会修改原数组
=> ["Looking", "am", "I"]
[59] pry(main)> names
=> ["Looking", "am", "I"]


irb(main):058:0> names.each do |name|
irb(main):059:1*     puts name
irb(main):060:1> end
i
am
Looking
=> ["i", "am", "Looking"]

[85] pry(main)> names.each_with_index do |element, index|
[85] pry(main)*   puts "#{element} is number #{index} in the array"  
[85] pry(main)* end  
I is number 0 in the array
am is number 1 in the array
Looking is number 2 in the array
=> ["I", "am", "Looking"]

irb(main):064:0> names.each {
irb(main):065:1*     puts "Hello World"
irb(main):066:1> }
Hello World
Hello World
Hello World
=> ["i", "am", "Looking"]

irb(main):067:0> names.each do
irb(main):068:1*     puts "Hello World"
irb(main):069:1> end
Hello World
Hello World
Hello World
=> ["i", "am", "Looking"]
# Python3
>>> names = ["I", "am", "Looking"]
>>> names[0]
'I'
>>> names[0] = "i"
>>> names
['i', 'am', 'Looking']
>>> names[-1]
'Looking'
>>> len(names)
3

>>> names
['I', 'am', 'Looking']
>>> names.reverse() # 会修改原列表元素顺序
>>> names
['Looking', 'am', 'I']

>>> names = ["I", "am", "Looking"]
>>> names.append("!")
>>> names
['I', 'am', 'Looking', '!']
>>> "Looking" in names
True

>>> for name in names:
...     print(name)
... 
i
am
Looking

>>> for index, element in enumerate(names):
...     print(f"{element} is number {index} in the array")
... 
I is number 0 in the array
am is number 1 in the array
Looking is number 2 in the array

>>> for name in names:
...     print("Hello World")
... 
Hello World
Hello World
Hello World

散列(字典)比较

# Ruby
# Ruby当中符号也可以作为
irb(main):071:0> address = {name:"Looking", pinyin:"lukaiyi", postal:"405902"}
=> {:name=>"Looking", :pinyin=>"lukaiyi", :postal=>"405902"}
irb(main):074:0* address = {:name=>"Looking", :pinyin=>"lukaiyi", :postal=>"405902"}
=> {:name=>"Looking", :pinyin=>"lukaiyi", :postal=>"405902"}
irb(main):014:0> address[:name]
=> "Looking"
irb(main):015:0> address["name".to_sym]
=> "Looking"
irb(main):016:0> 

# Ruby在好些地方加括号和不加括号区别不大,就比如 print, puts, p
# Python则不一样,加括号表示调用,不加括号表示引用,指向函数代码所在的地址
[73] pry(main)> address.keys
=> ["name", "pinyin", "postal"]
[74] pry(main)> address.keys()
=> ["name", "pinyin", "postal"]
[75] pry(main)> address.values
=> ["Looking", "lukaiyi", "405902"]


irb(main):007:0> address = {"name"=>"Looking", "pinyin"=>"lukaiyi", "postal"=>"405902"}
=> {"name"=>"Looking", "pinyin"=>"lukaiyi", "postal"=>"405902"}
irb(main):011:0> address["name"]
=> "Looking"
irb(main):012:0> address[:name.to_s]
=> "Looking"

irb(main):016:0> sym = :foo
=> :foo
irb(main):017:0> sym.to_s
=> "foo"
irb(main):018:0> "foo"
=> "foo"
irb(main):019:0> "foo".to_sym
=> :foo

irb(main):021:0> address[:tel] = "123456789"
=> "123456789"
irb(main):022:0> address
=> {:name=>"Looking", :pinyin=>"lukaiyi", :postal=>"405902", :tel=>"123456789"}

irb(main):023:0> address.each do |key, value|
irb(main):024:1*    puts "#{key}: #{value}"
irb(main):025:1> end
name: Looking
pinyin: lukaiyi
postal: 405902
tel: 123456789
=> {:name=>"Looking", :pinyin=>"lukaiyi", :postal=>"405902", :tel=>"123456789"}
# Python3
# Python3 字典的 key 需要可哈希化
>>> address = {"name": "Looking", "pinyin":"lukaiyi", "postal":"405902"}
>>> address
{'name': 'Looking', 'pinyin': 'lukaiyi', 'postal': '405902'}
>>> address = dict(name="Looking", pinyin="lukaiyi", postal="405902")
>>> address
{'name': 'Looking', 'pinyin': 'lukaiyi', 'postal': '405902'}

# Ruby在好些地方加括号和不加括号区别不大,但是Python对这块倒是区分得很严格的
# Python加括号表示调用,不加括号表示引用,指向函数代码所在的地址
>>> address.keys()
dict_keys(['name', 'pinyin', 'postal'])
>>> address.keys

>>> address.values()
dict_values(['Looking', 'lukaiyi', '405902'])
>>> address.values


>>> address["tel"] = "123456789"
>>> address
{'name': 'Looking', 'pinyin': 'lukaiyi', 'postal': '405902', 'tel': '123456789'}

>>> for key, value in address.items():
...     print(key, ":", value)
... 
name : Looking
pinyin : lukaiyi
postal : 405902
tel : 123456789

字符串与模式匹配

# Ruby
irb(main):026:0> /cde/ =~ "abcdefgh"
=> 2
irb(main):027:0> /Cde/ =~ "abcdefgh"
=> nil
irb(main):028:0> /Cde/i =~ "abcdefgh"
=> 2
irb(main):029:0> /Cde/i =~ "abcdEfgh"
=> 2


irb(main):031:0> names = ["Looking", "Luck", "John"]
=> ["Looking", "Luck", "John"]
irb(main):032:0> names.each do |name|
irb(main):033:1*   if /o/ =~ name
irb(main):034:2>     puts name
irb(main):035:2>   end
irb(main):036:1> end
Looking
John
=> ["Looking", "Luck", "John"]
# Python3
>>> "abcdefgh".find("cde")
2
>>> "abcdefgh".find("Cde")
-1
>>> "abcdefgh".find("Cde".lower())
2
>>> "abcdefgh".lower().find("Cde".lower())
2

>>> names = ["Looking", "Luck", "John"]
>>> for name in names:
...     if 'o' in name:
...             print(name)
... 
Looking
John

变量比较

变量在使用之前都需要先赋值,这应该是它们的相同点了。

# Ruby

sub.rb
$x = 1 #对全局变量赋值
x = 1 #对本地量赋值

test.rb
$x = 0
x = 0
require './sub'
p $x
p x

D:\Ruby23-x64\bin\ruby.exe D:/MyProject/Ruby/workspace/test.rb
1
0

Process finished with exit code 0

------------------------------------------------------------
irb(main):037:0> x + 1
NameError: undefined local variable or method `x' for main:Object
	from (irb):37
	from /usr/bin/irb:12:in `
' # Ruby使用全大写来表示常量,常量重新赋值的话还会报警告消息。 irb(main):038:0> TEST = 1 => 1 irb(main):039:0> TEST = 2 (irb):39: warning: already initialized constant TEST (irb):38: warning: previous definition of TEST was here => 2 ------------------------------------------------------------ # 保留字重新赋值会提示语法错误,Python3也不例外 irb(main):041:0> if = 1 SyntaxError: (irb):41: syntax error, unexpected '=' if = 1 ^ from /usr/bin/irb:12:in `
' ------------------------------------------------------------ irb(main):043:0> a, b, c = 1, 2, 3 => [1, 2, 3] irb(main):044:0> a, b, c = 1, 2, 3, 4 => [1, 2, 3, 4] irb(main):045:0> c => 3 irb(main):046:0> a, b, *c = 1, 2, 3, 4 => [1, 2, 3, 4] irb(main):047:0> a, b = b, a => [2, 1] irb(main):048:0> c => [3, 4]
# Python3
>>> x + 1
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'x' is not defined
------------------------------------------------------------
# Python3一般也使用全大写来表示常量,但是你要改的话就该,反正不关我们Python的事儿,我就当你知道你在做什么就是了。
>>> TEST = 1
>>> TEST = 2
------------------------------------------------------------
>>> if = 1
  File "", line 1
    if = 1
       ^
SyntaxError: invalid syntax
------------------------------------------------------------
>>> a, b, c = 1, 2, 3
>>> a, b, c = 1, 2, 3, 4
Traceback (most recent call last):
  File "", line 1, in 
ValueError: too many values to unpack (expected 3)
>>> a, b, *c = 1, 2, 3, 4
>>> a, b
(1, 2)
>>> a, b = b, a
>>> a, b
(2, 1)
>>> c
[3, 4]

常用循环函数 

# Ruby
[87] pry(main)> doubled = array.map do |element|
[87] pry(main)*   element * 2
[87] pry(main)* end  
=> [2, 4, 6, 8, 10]
[91] pry(main)> array.map {|s| s. * 2}
=> [2, 4, 6, 8, 10]
[93] pry(main)> array.inject(0) {|sum, n| sum + n } # 括号的0表示sum的初始值,可不写,不写的时候括号也可以去掉
=> 15
[92] pry(main)> array.reduce(:+)
=> 15

[98] pry(main)> a = ["FOO", "BAR", "BAZ"]
=> ["FOO", "BAR", "BAZ"]
[99] pry(main)> a.map{|s| s.downcase}
=> ["foo", "bar", "baz"]
[100] pry(main)> a.map(&:downcase)
=> ["foo", "bar", "baz"]
[101] pry(main)> a
=> ["FOO", "BAR", "BAZ"]
# Python3
>>> [ 2*x for x in array]
[2, 4, 6, 8, 10]
>>> array = [1, 2, 3, 4, 5]
>>> list(map(lambda x: 2*x, array))
[2, 4, 6, 8, 10]
>>> list(filter(lambda x: x>3, array))
[4, 5]
>>> from functools import reduce
>>> reduce(lambda x, y: x + y, array)
15
>>> a = ["FOO", "BAR", "BAZ"]
>>> [x.lower() for x in a]
['foo', 'bar', 'baz']
>>> list(map(lambda x:x.lower(), a))
['foo', 'bar', 'baz']
>>> a
['FOO', 'BAR', 'BAZ']

 unless,case,until 结构

对不起,Python 表示我没这些花里胡哨的东东,直接用 not 它不香吗?多出的这些单词大家不认识怎么办?(/哈哈)

# Ruby
[102] pry(main)> a = 10
=> 10
[103] pry(main)> b = 20
=> 20
[104] pry(main)> unless a > b
[104] pry(main)*   puts "a not greater than b"
[104] pry(main)* else  
[104] pry(main)*   puts "a greater than b"
[104] pry(main)* end  
a not greater than b
=> nil
------------------------------------------------------------
[105] pry(main)> grade = 82
=> 82
[106] pry(main)> case grade
[106] pry(main)* when 90..100  
[106] pry(main)*   puts 'Hooray!'  
[106] pry(main)* when 80...90  
[106] pry(main)*   puts 'OK job'  
[106] pry(main)* else  
[106] pry(main)*   puts 'You failed!'  
[106] pry(main)* end  
OK job
=> nil

# 注意 m..n 语法的细节哟!中间两个点表示包含左右两端的数,三个点的话不包含右边的数哟!
[113] pry(main)> (80..90).include?(80)
=> true
[114] pry(main)> (80..90).include?(90)
=> true
[119] pry(main)> (80...90).include?(80)
=> true
[120] pry(main)> (80...90).include?(90)
=> false
------------------------------------------------------------
[121] pry(main)> sum = 0
=> 0
[122] pry(main)> i = 1
=> 1
[123] pry(main)> while sum < 50
[123] pry(main)*   sum += i
[123] pry(main)*   i += 1
[123] pry(main)* end  
=> nil
[124] pry(main)> puts sum
55
=> nil

[125] pry(main)> sum = 0
=> 0
[126] pry(main)> i = 1
=> 1
[127] pry(main)> until sum >= 50
[127] pry(main)*   sum += i
[127] pry(main)*   i += 1
[127] pry(main)* end  
=> nil
[128] pry(main)> puts sum
55
=> nil

# Python3
>>> if not a > b:
...     print("a not greater than b")
... else:
...     print("a greater than b")
... 
a not greater than b
------------------------------------------------------------
>>> grade = 82
>>> if 90 <= grade <= 100:
...     print('Hooray!')
... elif 80 <= grade < 90:
...     print('OK job')
... else:
...     print('You failed!')
... 
OK job

------------------------------------------------------------
# Ruby 里边有的说用 not 不直观,反正我真的没看出来哪点不直观
>>> sum = 0
>>> i = 1
>>> while not sum >= 50:
...     sum += i
...     i += 1
... 
>>> print(sum)
55

异常处理

两种语言异常处理的对应关系大家自己慢慢看哟,除了名字意外,其实也差不错的。

# Ruby
[148] pry(main)> begin
[148] pry(main)*   # Code here that might raise an exception  
[148] pry(main)*   raise NoMemoryError, 'You ran out of memory.'  
[148] pry(main)* rescue NoMemoryError => exception_variable  
[148] pry(main)*   puts 'NoMemoryError was raised', exception_variable  
[148] pry(main)* rescue RuntimeError => other_exception_variable  
[148] pry(main)*   puts 'RuntimeError was raised now'  
[148] pry(main)* else  
[148] pry(main)*   puts 'This runs if no exceptions were thrown at all'  
[148] pry(main)* ensure  
[148] pry(main)*   puts 'This code always runs no matter what'  
[148] pry(main)* end  
NoMemoryError was raised
You ran out of memory.
This code always runs no matter what
=> nil
# Python3
>>> try:
...     # Code here that might raise an exception
...     raise MemoryError('Your ran out of memory.')
... except MemoryError as exception_variable:
...     print("MemoryError was raised", exception_variable, sep='\n')
... except RuntimeError as other_exception_variable:
...     print("RuntimeError was raised now")
... else:
...     print("This runs if no exceptions were thrown at all")
... finally:
...     print("This code always runs no matter what")
... 
MemoryError was raised
Your ran out of memory.
This code always runs no matter what

方法(函数)

# Ruby
[1] pry(main)> def double(x)    
[1] pry(main)*   x * 2                                                                 
[1] pry(main)* end 
=> nil                                                                                         
[2] pry(main)> double(2)                                                                       
=> 4                                                                                           
[3] pry(main)> double 3                                                                         
=> 6                                                    
[4] pry(main)> double double 3
=> 12 

[1] pry(main)> def sum(x, y)
[1] pry(main)*   x + y
[1] pry(main)* end  
=> nil
[2] pry(main)> sum 3, 4
=> 7
[3] pry(main)> sum sum(3, 4), 5
=> 12

[4] pry(main)> def surround
[4] pry(main)*   puts '{'  
[4] pry(main)*   yield  
[4] pry(main)*   puts '}'  
[4] pry(main)* end  
=> nil
[5] pry(main)> 
[6] pry(main)> surround { puts 'hello world' }
{
hello world
}
=> nil
# 这儿对块简单的理解就是在原来 yield 的地方执行了块里边的语句
# yield 后边如果有参数的话,也可以传递到块里边去
[34] pry(main)> def guests
[34] pry(main)*   yield 4
[34] pry(main)* end  
=> nil
[35] pry(main)> guests{|n| "You have #{n} guests."}
=> "You have 4 guests."


# 但是如果方法的最后一个参数前带有 &,那么您可以向该方法传递一个块。
# 而且这个块可被赋给最后一个参数。如果 * 和 & 同时出现在参数列表中,& 应放在后面。
[23] pry(main)> def guests(&block)
[23] pry(main)*   block.call(4)  
[23] pry(main)* end  
=> nil
[24] pry(main)> guests{|n| "You have #{n} guests."}
=> "You have 4 guests."
# Python3
>>> def double(x):
...     return x * 2
... 
>>> double(2)
4
>>> double(3)
6
>>> double(double(3))
12

>>> def sum(x, y):
...     return x + y
... 
>>> sum(3, 4)
7
>>> sum(sum(3, 4), 5)
12

参数的匹配和解包 

这块这两种语言用法是类似的

# Ruby
# 当 * 和 ** 符号出现在函数定义的参数中时,表示任意数目参数收集
[39] pry(main)> def guests(*array)
[39] pry(main)*   array.each { |guest| puts guest }  
[39] pry(main)* end  
=> nil

[42] pry(main)> guests('hello', 'world')
hello
world
=> ["hello", "world"]

# * 和 ** 符号出现在函数调用的参数中时,表示会解包参数的集合
[44] pry(main)> def guests(a, b, c, d)
[44] pry(main)*   puts a, b, c, d
[44] pry(main)* end  
=> nil

[46] pry(main)> guests(*['hello', 'world', 'ruby', 'python'])
hello
world
ruby
python
=> nil

# 解包和匹配合体示例
[1] pry(main)> def best(first, second, third, *others)
[1] pry(main)*   puts "Winners are #{first}, #{second}, and #{third}."  
[1] pry(main)*   puts "There were #{others.count} other participants."  
[1] pry(main)* end  
=> nil
[2] pry(main)> ranked_competitors = ["John", "Sally", "Dingus", "Moe", "Marcy"]
=> ["John", "Sally", "Dingus", "Moe", "Marcy"]
[3] pry(main)> best *ranked_competitors 
Winners are John, Sally, and Dingus.
There were 2 other participants.
=> nil
# Python3
>>> def guests(*array):
...     for guest in array:
...             print(guest)
... 

# 当 * 和 ** 符号出现在函数定义的参数中时,表示任意数目参数收集
>>> guests('hello', 'world')
hello
world

>>> def guests(a, b, c, d):
...     print(a, b, c, d, sep='\n')
... 

# * 和 ** 符号出现在函数调用的参数中时,表示会解包参数的集合
>>> guests(*['hello', 'world', 'ruby', 'python'])
hello
world
ruby
python

# 解包和匹配合体示例
>>> def best(first, second, third, *others):
...     print(f"Winners are, {first}, {second} and {third}.")
...     print(f"There were {len(others)} other participants.")
... 
>>> best(*ranked_competitors)
Winners are, John, Sally and Dingus.
There were 2 other participants.

map,reduce 和 select(filter)

# Ruby
[50] pry(main)> array  = ['Watch', 'these', 'words', 'get', 'upcased']
=> ["Watch", "these", "words", "get", "upcased"]
[51] pry(main)> array.map(&:upcase)
=> ["WATCH", "THESE", "WORDS", "GET", "UPCASED"]
[52] pry(main)> array.map do |item|
[52] pry(main)*   item.upcase!  
[52] pry(main)* end  
=> ["WATCH", "THESE", "WORDS", "GET", "UPCASED"]


[57] pry(main)> array = [1, 2, 3, 4, 5]
=> [1, 2, 3, 4, 5]
[59] pry(main)> sum = array.reduce(&:+)
=> 15
[60] pry(main)> multiplication = array.reduce(&:*)
=> 120
[61] pry(main)> 

[67] pry(main)> array = [1, 2, 3, 4, 5]
=> [1, 2, 3, 4, 5]
[68] pry(main)> array.select{|x| x < 4}
=> [1, 2, 3]
# Python3
>>> array  = ['Watch', 'these', 'words', 'get', 'upcased']
>>> array
['Watch', 'these', 'words', 'get', 'upcased']
>>> list(map(lambda x: x.upper(), array))
['WATCH', 'THESE', 'WORDS', 'GET', 'UPCASED']

>>> from functools import reduce
>>> array = [1, 2, 3, 4, 5]
>>> sum = reduce(lambda x, y: x + y, array)
>>> sum
15
>>> multiplication = reduce(lambda x, y: x * y, array)
>>> multiplication
120

>>> array = [1, 2, 3, 4, 5]
>>> list(filter(lambda x: x < 4, array))
[1, 2, 3]

Ruby 里边可以有相同类名的类(会对里边的内容自动进行扩展):

class HelloWorld
    def instance_method
        puts "instance method"
    end
end

class HelloWorld
    def test
        puts "test"
    end
end

HelloWorld.new.instance_method
HelloWorld.new.test

Python 里边不可以有相同类名的类(或者说可以有相同的,但是后定义的类会覆盖掉先定义的):

class HelloWorld:
    def instance_method(self):
        print('instance method')

class HelloWorld:
    def test(self):
        print("test")

HelloWorld().instance_method()    # AttributeError: 'HelloWorld' object has no attribute 'instance_method'
HelloWorld().test()

在类方面,Ruby 和 Python 还有一个很大的不同:如果 Ruby 的类里边没有实现某个实例变量的 set 和 get 方法的话,从对象外部不能直接访问实例变量或对实例变量进行赋值。

# Ruby
class Human
  # 类变量,被类的所有实例共享
  @@species = 'H. sapiens'

  # 初始化
  def initialize(name, age = 0)
    # 实例变量初始化, 实例变量无法脱离方法进行声明和定义
    @name = name
    # 如果 age 没有,取默认值
    @age = age
  end

  # set 方法
  def name=(name)
    @name = name
  end

  # get 方法
  def name
    @name
  end

  # attr_accessor相当于attr_reader和attr_writer的合集,实际上是在定义类成员变量的时候就给他定义了一个get和set方法。
  attr_accessor :age
  # 在ruby中,类成员变量都是私有的,不能直接通过(类名.成员变量名)这样来对成员变量值进行操作。
  # get/set 方法也可以像下面这么单独创建,如果没有创建的话,不能按照如下这样使用:
  # 实例对象.age
  # 实例对象.age = 2
  attr_reader :age # get
  attr_writer :age # set

  def say_something(msg) # 实例方法
    puts msg
  end

  # 类方法通过 self 与实例方法进行区分,只能通过类进行调用
  def self.say(msg)
    puts msg
  end

  # 可以通过类方法或者实例方法修改类变量
  # 实例方法
  def modify_species(new_species)
    @@species = new_species
  end

  def species
    @@species
  end
end

# Instantiating of a class
jim = Human.new('Jim Halpert')
dwight = Human.new('Dwight K. Schrute')

# You can call the methods of the generated object.
puts jim.species #=> "H. sapiens"
puts jim.name #=> "Jim Halpert"
jim.name = "Jim Halpert II" #=> "Jim Halpert II"
puts jim.name #=> "Jim Halpert II"
puts dwight.species #=> "H. sapiens"
puts dwight.name #=> "Dwight K. Schrute"

# 调用类方法
Human.say('Hi') #=> "Hi"
jim.say_something("Hello") #=> "Hello"
jim.modify_species("animals")
puts jim.species #=> "animals"
jim.modify_species("H. sapiens")
puts jim.species #=> "H. sapiens"
puts jim.age #=> 0
jim.age = 5
puts jim.age #=> 5
# Python3
class Human:
    # 类属性,被类的所有实例共享
    species = "H. sapiens"

    def __init__(self, name, age=0):
        self.name = name
        self._age = age

    # An instance method. All methods take "self" as the first argument
    def say(self, msg):
        print("{name}: {message}".format(name=self.name, message=msg))

    # Another instance method
    def sing(self):
        return 'yo... yo... microphone check... one two... one two...'

    # A class method is shared among all instances
    # They are called with the calling class as the first argument
    @classmethod
    def get_species(cls):
        return cls.species

    # A static method is called without a class or instance reference
    @staticmethod
    def grunt():
        return "*grunt*"

    # A property is just like a getter.
    # It turns the method age() into an read-only attribute of the same name.
    # There's no need to write trivial getters and setters in Python, though.
    @property  # getter
    def age(self):
        return self._age

    # This allows the property to be set
    @age.setter
    def age(self, age):
        self._age = age

    # This allows the property to be deleted
    @age.deleter
    def age(self):
        del self._age


# 当 Python 解释器读取一个源码文件时,它会执行其中所有代码
# 用 __name__ 确保这个代码块只有为主程序时才执行。
if __name__ == '__main__':
    i = Human(name="Ian")
    i.say("hi")  # "Ian: hi"
    j = Human("Joel")
    j.say("hello")  # "Joel: hello"
    i.say(i.get_species())  # "Ian: H. sapiens"
    Human.species = "H. neanderthalensis"
    i.say(i.get_species())  # => "Ian: H. neanderthalensis"
    j.say(j.get_species())  # => "Joel: H. neanderthalensis"

    # 通过类调用静态方法
    print(Human.grunt())  # => "*grunt*"
    # 通过实例对象调用静态方法
    print(i.grunt())  # => "*grunt*"

    # 更新实例属性
    i.age = 42
    # 获取属性
    i.say(i.age)  # => "Ian: 42"
    j.say(j.age)  # => "Joel: 0"
    # 删除属性
    del i.age

--------------------------------------------------------------------------------
class Human:
    species = 'H. sapiens'

    def __init__(self, name, age=0):
        self.name = name
        self.age = age

    # 实例方法,第一个参数需要是self,它表示一个具体的实例对象本身,因为方法可能用的实例本身的一些变量
    def instance_method(self):
        print(f"Hello, I am instance_method, my name is {self.name}")

    # 如果用staticmethod装饰,那么就可以无视这个self,而将这个方法当成一个普通的函数使用
    @staticmethod
    def static_method():
        print("Hello, I am static_method")
        return "Hello, I am static_method"

    # 如果用classmethod,它的第一个参数是cls,它表示这个类本身,可以通过类名进行调用
    # 可在类方法中使用静态方法
    @classmethod
    def class_method(cls):
        print(cls.static_method() + " called by class_method")
        print("Hello, I am class_method")


jim = Human('Jim Halpert')
dwight = Human('Dwight K. Schrute')
print(jim.species)
print(Human.species)
jim.instance_method()
jim.static_method()
Human.static_method()
Human.class_method()


"D:\Program Files\Python36\python3.exe" D:/MyProject/Python/workspace/test.py
H. sapiens
H. sapiens
Hello, I am instance_method, my name is Jim Halpert
Hello, I am static_method
Hello, I am static_method
Hello, I am static_method
Hello, I am static_method called by class_method
Hello, I am class_method

Process finished with exit code 0

子类

# Ruby
# 基类
class Human
  @@foo = 0

  # 下面这两个函数类似于类变量的 get/set 方法
  def self.foo
    @@foo
  end

  def self.foo=(value)
    @@foo = value
  end
end

# 派生类(子类)
class Worker < Human
end

puts Human.foo #=> 0
puts Worker.foo #=> 0

# 类变量被它的所有子类共享
puts Human.foo = 2
puts Worker.foo #=> 2

--------------------------------------------------------------------------------
class Human
  @bar = 0

  def self.bar
    @bar
  end

  def self.bar=(value)
    @bar = value
  end
end

class Doctor < Human
end

# 类实例变量不被子类所共享
Human.bar #=> 0
Doctor.bar #=> nil
# Python3
class Human:
    # 类属性,被类的所有实例共享
    species = "H. sapiens"

    def __init__(self, name, age=0):
        self.name = name
        self._age = age

    # An instance method. All methods take "self" as the first argument
    def say(self, msg):
        print("{name}: {message}".format(name=self.name, message=msg))

    # Another instance method
    def sing(self):
        return 'yo... yo... microphone check... one two... one two...'

    # A class method is shared among all instances
    # They are called with the calling class as the first argument
    @classmethod
    def get_species(cls):
        return cls.species

    # A static method is called without a class or instance reference
    @staticmethod
    def grunt():
        return "*grunt*"

    # A property is just like a getter.
    # It turns the method age() into an read-only attribute of the same name.
    # There's no need to write trivial getters and setters in Python, though.
    @property  # getter
    def age(self):
        return self._age

    # This allows the property to be set
    @age.setter
    def age(self, age):
        self._age = age

    # This allows the property to be deleted
    @age.deleter
    def age(self):
        del self._age


class Superhero(Human):
    species = 'Superhuman'

    def __init__(self, name, movie=False,
                 superpowers=["super strength", "bulletproofing"]):
        # add additional class attributes:
        self.fictional = True
        self.movie = movie
        # be aware of mutable default values, since defaults are shared
        self.superpowers = superpowers
        super().__init__(name)  # 调用父类的初始化函数

    # override the sing method
    def sing(self):
        return 'Dun, dun, DUN!'

    # add an additional instance method
    def boast(self):
        for power in self.superpowers:
            print("I wield the power of {pow}!".format(pow=power))


if __name__ == '__main__':
    sup = Superhero(name="Tick")

    # Instance type checks
    if isinstance(sup, Human):
        print('I am human')  # 超级英雄也是人,所以实例化的对象仍然是父类的一个实例
    if type(sup) is Superhero:
        print('I am a superhero')

    # 子类会优先去自己类本身找相应的方法和属性,找不到才到父类继续寻找
    print(sup.get_species())  # => Superhuman
    # Calls overridden method
    print(sup.sing())  # => Dun, dun, DUN!
    # Calls method from Human
    sup.say('Spoon')  # => Tick: Spoon

    # Call method that exists only in Superhero
    sup.boast()  # => I wield the power of super strength!
    # => I wield the power of bulletproofing!

    # Inherited class attribute
    sup.age = 31
    print(sup.age)  # => 31

    # Attribute that only exists within Superhero
    print('Am I Oscar eligible? ' + str(sup.movie))

module

简单理解你就把他当成一个 namespace (命名空间),这样在调用的时候不至于太混乱。

# Ruby
# trig.rb
module Trig
  PI = 3.141592654

  def Trig.sin(x)
    Math.sin(x)
  end

  def Trig.cos(x)
    Math.cos(x)
  end
end

--------------------------------------------------------------------------------
# moral.rb
module Moral
  VERY_BAD = 0
  BAD = 1
  def Moral.sin(badness)
    Math.sin(badness)
  end
end

--------------------------------------------------------------------------------
# test.rb
$LOAD_PATH << '.'
# $LOAD_PATH << '.' 让 Ruby 知道必须在当前目录中搜索被引用的文件
require 'trig.rb'
require 'moral'

y = Trig.sin(Trig::PI/4)
wrongdoing = Moral.sin(Moral::VERY_BAD)
puts y, wrongdoing

D:\Ruby23-x64\bin\ruby.exe D:/MyProject/Ruby/workspace/test.rb
0.7071067812590626
0.0

Process finished with exit code 0

--------------------------------------------------------------------------------
# Ruby
module ModuleExample
  def foo
    'foo'
  end
end

# include modules 将他们的方法和类实例进行绑定(也即只能通过生成的实例来进行调用)
# extend modules 将他们的方法和类本身进行绑定 (也即只能通过类本身进行调用)
class Person
  include ModuleExample
end

class Book
  extend ModuleExample
end

puts Person.foo     #=> NoMethodError: undefined method `foo' for Person:Class
puts Person.new.foo #=> "foo"
puts Book.foo       #=> "foo"
puts Book.new.foo   #=> NoMethodError: undefined method `foo'

--------------------------------------------------------------------------------
module ConcernExample
  def self.included(base)
    base.extend(ClassMethods)
    base.send(:include, InstanceMethods)
  end

  module ClassMethods
    def bar
      'bar'
    end
  end

  module InstanceMethods
    def qux
      'qux'
    end
  end
end

class Something
  include ConcernExample
end

puts Something.bar     #=> "bar"
puts Something.qux     #=> NoMethodError: undefined method `qux'
puts Something.new.bar #=> NoMethodError: undefined method `bar'
puts Something.new.qux #=> "qux"

JSON文件解析

新建 input.json 文件

# input.json

{
  "President": "Alan Isaac",
  "CEO": "David Richardson",
  
  "India": [
    "Sachin Tendulkar",
    "Virender Sehwag",
    "Gautam Gambhir"
  ],
 
  "Srilanka": [
    "Lasith Malinga",
    "Angelo Mathews",
    "Kumar Sangakkara"
  ],
 
  "England": [
    "Alastair Cook",
    "Jonathan Trott",
    "Kevin Pietersen"
  ]
}
# Ruby
[1] pry(main)> require 'json'
=> true
[2] pry(main)> require 'pp'
=> false
[3] pry(main)> json = File.read('input.json')
=> "{\n  \"President\": \"Alan Isaac\",\n  \"CEO\": \"David Richardson\",\n  \n  \"India\": [\n    \"Sachin Tendulkar\",\n    \"Virender Sehwag\",\n    \"Gautam Gambhir\"\n  ],\n \n  \"Srilanka\": [\n    \"Lasith Malinga\",\n    \"Angelo Mathews\",\n    \"Kumar Sangakkara\"\n  ],\n \n  \"England\": [\n    \"Alastair Cook\",\n    \"Jonathan Trott\",\n    \"Kevin Pietersen\"\n  ]\n}\n"
[4] pry(main)> obj = JSON.parse(json)
=> {"President"=>"Alan Isaac",
 "CEO"=>"David Richardson",
 "India"=>["Sachin Tendulkar", "Virender Sehwag", "Gautam Gambhir"],
 "Srilanka"=>["Lasith Malinga", "Angelo Mathews", "Kumar Sangakkara"],
 "England"=>["Alastair Cook", "Jonathan Trott", "Kevin Pietersen"]}
[5] pry(main)> obj['President']
=> "Alan Isaac"
# Python3
>>> import json
>>> with open('input.json', 'r') as f:
...     data = json.load(f)
... 
>>> data
{'President': 'Alan Isaac', 'CEO': 'David Richardson', 'India': ['Sachin Tendulkar', 'Virender Sehwag', 'Gautam Gambhir'], 'Srilanka': ['Lasith Malinga', 'Angelo Mathews', 'Kumar Sangakkara'], 'England': ['Alastair Cook', 'Jonathan Trott', 'Kevin Pietersen']}
>>> type(data)

>>> data['President']
'Alan Isaac'

目录遍历

# Ruby
parentDir = 'D:\\MyProject\\Python\\DataStructure\\DataSet2014\\'

def find_all_file(filepath)
  if File.directory?(filepath)
    Dir.foreach(filepath) do |filename|
      if filename != "." and filename != ".."
        find_all_file(filepath + "\\" + filename)
      end
    end
  else
    puts filepath
  end
end

find_all_file parentDir
# Python3
import os

parentDir = 'D:\\MyProject\\Python\\DataStructure\\DataSet2014'


def find_all_file(parentDir):
    if os.path.isdir(parentDir): 
        dir_list = os.listdir(parentDir)
        paths = [os.path.join('%s\\%s' % (parentDir, tt)) for tt in dir_list]
        for path in paths:
            find_all_file(path)
    else:
        print(parentDir)


find_all_file(parentDir)

命令行参数解析

# Ruby
require 'optparse'

options = {}
OptionParser.new do |opts|
  opts.banner = 'here is help messages of the command line tool.'
  options[:switch] = false
  opts.on('-s', '--switch', 'Set options as switch') do
    options[:switch] = true
  end

  opts.on('-n NAME', '--name Name', 'Pass-in single name') do |value|
    options[:name] = value
  end

  opts.on('-a A,B', '--array A,B', Array, 'List of arguments') do |value|
    options[:array] = value
  end
end.parse!

puts options.inspect

------------------------------------------------------------
D:\MyProject\Ruby\workspace>ruby test.rb -h
here is help messages of the command line tool.
    -s, --switch                     Set options as switch
    -n, --name Name                  Pass-in single name
    -a, --array A,B                  List of arguments

D:\MyProject\Ruby\workspace>ruby test.rb -s
{:switch=>true}

D:\MyProject\Ruby\workspace>ruby test.rb -n Looking
{:switch=>false, :name=>"Looking"}

D:\MyProject\Ruby\workspace>ruby test.rb -a Ruby, Python
{:switch=>false, :array=>["Ruby"]}

D:\MyProject\Ruby\workspace>ruby test.rb -a Ruby,Python
{:switch=>false, :array=>["Ruby", "Python"]}

你可能感兴趣的:(Ruby,Python,Ruby,Python)