ruby 简单笔记对比Python (待完善)

后端开发   发布日期:2025年07月09日   浏览次数:112

工作需要,需要使用静态语言crystal,但crystal的资料很少,语法接近ruby,网上说crystal是一帮ruby的爱好者搞起来的语言,废话不多,进入主题。

学习视频:https://www.bilibili.com/video/BV1QW411F7rh?p=1

ruby 通过 -v 查看版本   Python -V

  1. [sidian@VM_0_17_centos ruby_study]$ ruby -v
  2. ruby 2.0.0p648 (2015-12-16) [x86_64-linux]
  3. [sidian@VM_0_17_centos ruby_study]$ python3 -V
  4. Python 3.7.4
  5. [sidian@VM_0_17_centos ruby_study]$

通过irb进入交互界面. Python 进行命令行python就可以,或者安装了ipython命令行ipython进入交互模式

通过puts 屏幕终端输出信息   py通过print输出屏幕终端

  1. [sidian@VM_0_17_centos ruby_study]$ irb
  2. irb(main):001:0> puts "hello world"
  3. hello world
  4. => nil
  5. irb(main):002:0> exit
  6. [sidian@VM_0_17_centos ruby_study]$ python3
  7. Python 3.7.4 (default, Oct 28 2019, 00:18:00)
  8. [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)] on linux
  9. Type "help", "copyright", "credits" or "license" for more information.
  10. >>> print("hello,owlrd")
  11. hello,owlrd
  12. >>>

 ruby构建函数基本与Python差不多

  1. [sidian@VM_0_17_centos ruby_study]$ cat hello.rb
  2. #!/usr/bin/ruby -w
  3. def sayhello(name="sidian")
  4. puts "hello #{name}."
  5. end
  6. #sayhello("sidian")
  7. sayhello("wudian")

 总体来说就多了一个end,而且当默认没有参数的时候,可以省略小括号。

 

接下来直接定义类,跟Python非常像

  1. [sidian@VM_0_17_centos ruby_study]$ cat class_player.rb
  2. class Player
  3. def initialize(name = "sidian")
  4. @name = name
  5. end
  6. def show()
  7. puts "play: #{@name}"
  8. end
  9. end
  10. sidian = Player.new("wudian")
  11. sidian.show()
  12. world = Player.new("world")
  13. world.show()

 从定义可以看出,实例化需要使用类属性new()执行,调用该类属性。通过new小括号里面进行实例化参数的传递

类内部实例的属性定义,通过@号实现,这个跟Python中的self.的形式进行实例属性复制差不多。

当调用类属性new以后,首先自动触发执行类方法initialize函数,进行实例对象的初始化并返回。相对与Python的__init__初始化方法弱爆了。

格式话输出的还是通过#{}的方式输出。

 

ruby的instance_methods, respond_to?, send的三个命令参数,对应Python的dir或vars,第二个就是hasattr,第三个就是getattr()以后执行.

首先展示instance_methods这是一个类属性,实例不具有,通过类名可以调用该方法,内部可以传参数(true或false)【暂时没有找到查看所有实例属性的函数或者方法】

  1. class Game
  2. def initialize(title = "学习", price = "无价")
  3. @title = title
  4. @price = price # 实例属性复制
  5. end
  6. def show
  7. puts "标题是:#{@title}"
  8. puts "价格是:#{@price}"
  9. end
  10. def show2()
  11. end
  12. def show3
  13. end
  14. end
  15. puts Game.instance_methods(false)
  16. g = Game.new()
  17. puts g
  18. puts Game.instance_methods(true)
  19. puts g.instance_methods(false)
  20. ~

 结果

  1. ruby class_game
  2. show
  3. show2
  4. show3
  5. #<Game:0x00000000f9ac90>
  6. show
  7. show2
  8. show3
  9. nil?
  10. ===
  11. =~
  12. !~
  13. eql?
  14. hash
  15. <=>
  16. class
  17. singleton_class
  18. clone
  19. dup
  20. taint
  21. tainted?
  22. untaint
  23. untrust
  24. untrusted?
  25. trust
  26. freeze
  27. frozen?
  28. to_s
  29. inspect
  30. methods
  31. singleton_methods
  32. protected_methods
  33. private_methods
  34. public_methods
  35. instance_variables
  36. instance_variable_get
  37. instance_variable_set
  38. instance_variable_defined?
  39. remove_instance_variable
  40. instance_of?
  41. kind_of?
  42. is_a?
  43. tap
  44. send
  45. public_send
  46. respond_to?
  47. extend
  48. display
  49. method
  50. public_method
  51. define_singleton_method
  52. object_id
  53. to_enum
  54. enum_for
  55. ==
  56. equal?
  57. !
  58. !=
  59. instance_eval
  60. instance_exec
  61. __send__
  62. __id__
  63. class_game:20:in `<main>': undefined method `instance_methods' for #<Game:0x00000000f9ac90 @title="学习", @price="无价"> (NoMethodError)
  64. [sidian@VM_0_17_centos ruby_study]$

 通过结果可以看出来instance_methods类方法,实例使用会报错,如果传入flase返回的是定义类的时候传入的属性(函数),

如果传入true或者不传入,那返回的是类所有的属性,一些属性应该是类创建的时候,继承与python中的object类似。

  1. 16 puts Game.instance_methods(false)
  2. 17 g = Game.new()
  3. 18 puts g
  4. 19 if g.respond_to?("shw2") # 这个就跟Python中的hasattr就一样的,只不过一个是函数,一个是方法
  5. 20 puts "show2 is in"
  6. 21 end
  7. 22
  8. 23 # puts Game.instance_methods()
  9. 24 # puts g.instance_methods(false)

 respont_to?返回一个实例对象是否存在一个继承与类的属性???应该是,至少实例的属性不行,这个跟hasattr有点区别。

我刚测试,只有show,show1,show2返回的是真,实例的属性resopt_to并不会读取到。根据我的测试返回的就是instance_methods()类方法调用以后返回值里面的值,只要

在该值范围的内的都为真。

 

send就跟getattr()()这个有点像了,就是通过字符串的形式给实例传递方法的名字,并运行该方法。ruby的函数,没有默认参数的情况下,不用()也会执行

  1. 17 g = Game.new()
  2. 18 puts g
  3. 19 if g.respond_to?("send") # "send"在instance_methods的内容中,所以会执行g.send
  4. 20 puts g.send("show") # 传入类中定义的函数
  5. 21 end
  6. 22
  7. 23 # puts Game.instance_methods()
  8. 24 # puts g.instance_methods(false)

 结果

  1. [sidian@VM_0_17_centos ruby_study]$ ruby class_game
  2. show
  3. show2
  4. show3
  5. #<Game:0x00000001446c08>
  6. 标题是:学习
  7. 价格是:无价

 

私有属性能够被外部需要在类属性中定义一个attr_accessor :price, :name,:属性名字

这样定义以后在instance_methons能够读取该属性,一读取还是两个一个是属性名称,一个是属性名称加=号

  1. Last login: Sun May 10 22:01:34 on ttys004
  2. You have mail.
  3. The default interactive shell is now zsh.
  4. To update your account to use zsh, please run `chsh -s /bin/zsh`.
  5. For more details, please visit https://support.apple.com/kb/HT208050.
  6. shijianongdeMBP:~ shijianzhong$ ssh tx
  7. Last login: Sun May 10 21:59:49 2020 from 115.194.189.151
  8. [sidian@VM_0_17_centos ~]$ ls
  9. all.sql c_study db1_out_txt exec_new3.sh mysql.log newfile test
  10. crystal_centos.tar c.tar dump.rdb log2.txt new3_report ruby_study test.txt
  11. [sidian@VM_0_17_centos ~]$ cd ruby_study/
  12. [sidian@VM_0_17_centos ruby_study]$ ls
  13. ary.rb begin_end.rb begin.rb hello.rb here.rb hsh.rb 方法
  14. [sidian@VM_0_17_centos ruby_study]$ ruby hello.rb
  15. hello.rb:8:in `<main>': undefined local variable or method `syahello' for main:Object (NameError)
  16. [sidian@VM_0_17_centos ruby_study]$ ruby hello.rb
  17. hello sidian.
  18. [sidian@VM_0_17_centos ruby_study]$ ruby hello.rb
  19. hello wudian.
  20. [sidian@VM_0_17_centos ruby_study]$ ruby class_player.rb
  21. class_player.rb:6:in `show': undefined method `purs' for #<Player:0x000000013b8160> (NoMethodError)
  22. from class_player.rb:12:in `<main>'
  23. [sidian@VM_0_17_centos ruby_study]$ ruby hello.rb
  24. hello wudian.
  25. [sidian@VM_0_17_centos ruby_study]$ ruby class_player.rb
  26. play:
  27. [sidian@VM_0_17_centos ruby_study]$ ruby class_player.rb
  28. class_player.rb:11:in `initialize': wrong number of arguments (1 for 0) (ArgumentError)
  29. from class_player.rb:11:in `new'
  30. from class_player.rb:11:in `<main>'
  31. [sidian@VM_0_17_centos ruby_study]$ ruby class_player.rb
  32. class_player.rb:11:in `initialize': wrong number of arguments (1 for 0) (ArgumentError)
  33. from class_player.rb:11:in `new'
  34. from class_player.rb:11:in `<main>'
  35. [sidian@VM_0_17_centos ruby_study]$ ruby class_player.rb
  36. play:
  37. [sidian@VM_0_17_centos ruby_study]$ ruby class_player.rb
  38. play: sidian
  39. [sidian@VM_0_17_centos ruby_study]$ ruby class_player.rb
  40. play: wudian
  41. [sidian@VM_0_17_centos ruby_study]$ ruby class_player.rb
  42. play: wudian
  43. play: world
  44. [sidian@VM_0_17_centos ruby_study]$ ls
  45. ary.rb begin_end.rb begin.rb class_player.rb hello.rb here.rb hsh.rb 方法
  46. [sidian@VM_0_17_centos ruby_study]$ cat hello.rb
  47. #!/usr/bin/ruby -w
  48. def sayhello(name="sidian")
  49. puts "hello #{name}."
  50. end
  51. #sayhello("sidian")
  52. sayhello("wudian")
  53. [sidian@VM_0_17_centos ruby_study]$ cat class_player.rb
  54. class Player
  55. def initialize(name = "sidian")
  56. @name = name
  57. end
  58. def show()
  59. puts "play: #{@name}"
  60. end
  61. end
  62. sidian = Player.new("wudian")
  63. sidian.show()
  64. world = Player.new("world")
  65. world.show()
  66. [sidian@VM_0_17_centos ruby_study]$ packet_write_wait: Connection to 212.64.47.160 port 22: Broken pipe
  67. shijianongdeMBP:~ shijianzhong$ ssh tx
  68. Last login: Sun May 10 23:10:31 2020 from 115.194.189.151
  69. [sidian@VM_0_17_centos ~]$ ls
  70. all.sql c_study db1_out_txt exec_new3.sh mysql.log newfile test
  71. crystal_centos.tar c.tar dump.rdb log2.txt new3_report ruby_study test.txt
  72. [sidian@VM_0_17_centos ~]$ cd ruby_study/
  73. [sidian@VM_0_17_centos ruby_study]$ cal
  74. 五月 2020
  75. 日 一 二 三 四 五 六
  76. 1 2
  77. 3 4 5 6 7 8 9
  78. 10 11 12 13 14 15 16
  79. 17 18 19 20 21 22 23
  80. 24 25 26 27 28 29 30
  81. 31
  82. [sidian@VM_0_17_centos ruby_study]$ pqd
  83. -bash: pqd: 未找到命令
  84. [sidian@VM_0_17_centos ruby_study]$ pwd
  85. /home/sidian/ruby_study
  86. [sidian@VM_0_17_centos ruby_study]$ ls
  87. ary.rb begin_end.rb begin.rb class_game class_player.rb hello.rb here.rb hsh.rb 方法
  88. [sidian@VM_0_17_centos ruby_study]$ cat class_player.rb > class_player2.rb
  89. [sidian@VM_0_17_centos ruby_study]$ vim class_player2.rb
  90. class Player
  91. attr_accessor :price, :name # 只有这里定义了,实例才能在外面读取该属性。
  92. def initialize(name = "sidian", price = 150)
  93. @name = name
  94. @price = price
  95. end
  96. def show()
  97. puts "play: #{@name}"
  98. puts "price: #{@price}"
  99. end
  100. end
  101. sidian = Player.new("wudian")
  102. sidian.show()
  103. world = Player.new("world")
  104. world.show()
  105. puts world.respond_to?("price=").to_s
  106. world.price = 500
  107. world.name= "白痴"
  108. world.show()
  109. puts "\n"
  110. puts world.name
  111. puts Player.instance_methods(false)
  112. ~
  113. ~
  114. ~
  115. "class_player2.rb" 24L, 474C 已写入 2,25 全部

 

  1. [sidian@VM_0_17_centos ruby_study]$ ruby class_player2.rb
  2. play: wudian
  3. price: 150
  4. play: world
  5. price: 150
  6. true
  7. play: 白痴
  8. price: 500
  9. 白痴
  10. price
  11. price=
  12. name
  13. name=
  14. show

 

列表的操作 each do,  each_with_index

  1. game_list = ["实", "建忠", "牛逼"]
  2. game_list.each do |li| # 列表具有each属性
  3. puts "out_put#{li}"
  4. end
  5. game_list.each_with_index do |li,i|
  6. puts "my index#{i},content#{li}"
  7. end
  8. puts game_list.respond_to?("each").to_s # 可以通过respond_to?返回的值,判断一个对象是否具有该属性判断是否为列表
  9. puts game_list.join("中间") # 该方法跟Python一样

 

  1. out_put
  2. out_put建忠
  3. out_put牛逼
  4. my index0,content
  5. my index1,content建忠
  6. my index2,content牛逼
  7. true
  8. 实中间建忠中间牛逼

 

备注的使用

一行备注 跟Python 一样  #

多行备注 =begin ... =end   跟Python的""""""差不多,三引号

之后全部备注 __END__

 

操作符号

基本与Python一样, 除了逻辑操作符 &&,||,!等于Python中and or not

  1. irb(main):016:0> ! nil
  2. => true
  3. irb(main):017:0> ! false
  4. => true
  5. irb(main):018:0> ! []
  6. => false
  7. irb(main):020:0> ! 0
  8. => false
  9. irb(main):021:0>

 ruby 中只有false 与 nil才为假

 

三项运算式

  1. irb(main):004:0> point
  2. => 30
  3. irb(main):005:0> puts point >= 30 ?"mvp": "一般"
  4. mvp
  5. => nil
  6. irb(main):006:0> puts point > 30 ?"mvp": "一般"
  7. 一般
  8. => nil
  9. irb(main):007:0>

 标准语法 条件 ? 真的返回:假的返回

Python中的用法

  1. In [1]: 3 if 3>1 else 'lala'
  2. Out[1]: 3

 起始从逻辑来看,还是ruby的更加容易理解,但Python的我肯定不会说他差。

 

字符串的操作 + <<  *

  1. irb(main):007:0> a = "hello"
  2. => "hello"
  3. irb(main):008:0> b = "sidian"
  4. => "sidian"
  5. irb(main):009:0> a+b
  6. => "hellosidian"
  7. irb(main):010:0> a << b
  8. => "hellosidian"
  9. irb(main):012:0> a *5
  10. => "hellosidianhellosidianhellosidianhellosidianhellosidian"
  11. irb(main):013:0> a
  12. => "hellosidian"
  13. irb(main):014:0>

 从操作中看出+两个对象相加, <<相当于Python中的a = a+b, *跟Python的操作基本一样

 

单引号与双引号的区别

  1. irb(main):021:0> "\n"
  2. => "\n"
  3. irb(main):022:0> p1 = "我号\b"
  4. => "我号\b"
  5. irb(main):023:0> puts p1
  6. 我号
  7. => nil
  8. irb(main):024:0> "aa\nbb"
  9. => "aa\nbb"
  10. irb(main):025:0> p2 = 'aa\nbb'
  11. => "aa\\nbb"
  12. irb(main):026:0> puts p2
  13. aa\nbb
  14. => nil
  15. irb(main):027:0> myp = "#{1+2}"
  16. => "3"
  17. irb(main):028:0> myp = '#{1+2}'
  18. => "\#{1+2}"
  19. irb(main):029:0> puts myp
  20. #{1+2}
  21. => nil
  22. irb(main):030:0>

 从运行可以看出单引号好比python中的r不进行任何转义输出,双引号#{}输出,好比Python中的format格式化的f {}格式化输出

 

哈希变量操作,也就是Python中字典的操作,新建

  1. irb(main):033:0> mvp = {"sidian" => 'niubi',"wudiain"=>5}
  2. => {"sidian"=>"niubi", "wudiain"=>5}
  3. irb(main):034:0> myp
  4. => "\#{1+2}"
  5. irb(main):035:0> mvp
  6. => {"sidian"=>"niubi", "wudiain"=>5}
  7. irb(main):036:0> mvp["wudian"]
  8. => nil
  9. irb(main):037:0> mvp["sidian"]
  10. => "niubi"
  11. irb(main):038:0> mvp["sidiain"]
  12. => nil
  13. irb(main):039:0> mvp["wudiain"]
  14. => 5
  15. irb(main):041:0> player = {name: 'sidian',age:18}
  16. => {:name=>"sidian", :age=>18}
  17. irb(main):042:0> player[:name]
  18. => "sidian"
  19. irb(main):043:0> player[:nam]
  20. => nil
  21. irb(main):044:0>

 有两种创建方式,一种是通过=>的方式,取value通过[key],第二种是跟Python差不多的新建方式

但取值的时候通过[:value]的方式,这里发现一个有意思的玩意,就是如果取不到值返回的是nil,也就是跟false差不多

 

数据的转换,to_i,to_s,to_f相对与Python中的int,str,float

  1. irb(main):047:0> a = 1.23
  2. => 1.23
  3. irb(main):048:0> a.to_i
  4. => 1
  5. irb(main):049:0> a.to_f
  6. => 1.23
  7. irb(main):050:0> a = "实践中"
  8. => "实践中"
  9. irb(main):051:0> b =
  10. irb(main):052:0*
  11. irb(main):053:0* b = "123"
  12. => "123"
  13. irb(main):054:0> b.to_i + 456
  14. => 579
  15. irb(main):055:0> c = "1.55"
  16. => "1.55"
  17. irb(main):056:0> c.to_i
  18. => 1
  19. irb(main):057:0> c = 1.55
  20. => 1.55
  21. irb(main):058:0> c.to_i
  22. => 1
  23. irb(main):059:0>

 可以啊,to_i直接把字符串的float转换成整形,比Python牛逼么

 

class 再入门

  1. class Player
  2. def initialize(name = "sidian")
  3. @name = name
  4. end
  5. def show()
  6. puts "play: #{@name}"
  7. end
  8. def self.toStr # 静态方法不能被实例调用
  9. puts "my method is static"
  10. end
  11. end
  12. sidian = Player.new("wudian")
  13. sidian.show()
  14. world = Player.new("world")
  15. world.show()
  16. Player.toStr

 这个有个意义的东西,就是定义静态方法self.method,静态方法只能通过类名调用,无法通过实例调用。

 

类的继承

通过< 实现      儿子类名 < 父亲类名

没啥套路,不写了,直接所有的父类属性全部继承

 

模块的定义跟Python完全不一样了,需要通过命令 module来实现一个模块

调用模块的属性通过::,调用模块定义的静态方法可以通过::或者.,另外模块定义的函数可以传递给类

 

  1. module BaseFunc
  2. Version = "0.0.1"
  3. def v
  4. return Version
  5. end
  6. def add(a, b) # 非静态方法不属于模块方法
  7. return a+b
  8. end
  9. def self.showVersiona # 静态方法
  10. return Version
  11. end
  12. module_function :v # 定义为静态方法
  13. end
  14. puts BaseFunc::Version # 模块中的属性通过::读取
  15. #puts BaseDunc.Version # .不能读取
  16. class BaseClass include BaseFunc # 类中包含读取BaseFunc模块
  17. end
  18. puts BaseClass::Version
  19. b = BaseClass.new
  20. puts b.add(1,2)
  21. ~

 代码做了一些注释了,很有意思,模块中定义的方法,如果不定义称为静态方法,模块尽然不能直接调用,一定要称为静态方法才可以调用。

静态方法可以通过module_function :函数命 或者 self.函数名的方式编程静态方法

当一个类通过include包含了这个模块,可以通过::读取模块的属性,但不能调用模块的静态方法,但类的实例可以调用模块内定义的普通函数,有意思的家伙。

 

条件控制文

if elsif else unless else case when else

  1. p = 15
  2. if p >=30
  3. puts "3500万一年"
  4. elsif p >= 20
  5. puts "20一年"
  6. else
  7. puts "else这里来了"
  8. end
  9. unless p < 10 # 这个是不成立才触发
  10. puts "unless 触发"
  11. else
  12. puts "unldess未触发"
  13. end
  14. week_day = "3".to_i
  15. case week_day # 传入一个对象
  16. when 0,7 # 比较这个对象
  17. puts "星期天"
  18. when 1,2
  19. puts "这个是星期1或者2"
  20. when 3
  21. puts "这个是星期#{week_day}"
  22. else # 都没有的话,传入到这里
  23. puts "这个输入我没搞错"
  24. end

 相比Python,这个语法确实丰富多了,有三个。

 

循环处理

  1. gamelist = ["one", "two", "three"]
  2. for g in gamelist do
  3. puts g
  4. end
  5. for i in 1..5 do
  6. puts i
  7. end
  8. for i in 1...5 do
  9. puts i
  10. end
  11. n = 1
  12. while n < 5 do
  13. puts "while #{n}"
  14. n += 1
  15. end
  16. puts n
  17. until n == 2 do # 这个也很有意思,这个也是不成立才执行,日常开发用的少
  18. puts "until #{n}"
  19. n -= 1
  20. end
  21. ~

 与Python相比多了一个do,还有一个until,另外的理解都差不多,还有那个可恶的end我经常忘记了。

 

特殊循环

  1. g_list = ["one", "two", "three"]
  2. g_list.each {|game| puts game}
  3. g_list.each do |game|
  4. puts game
  5. end
  6. g_list.each_with_index do |g, i|
  7. puts g + (i+1).to_s
  8. end
  9. g_list.each_with_index{
  10. |g, i| puts g, i
  11. }
  12. 5.times do |i| # 重复执行
  13. puts "time #{i}"
  14. end
  15. 1.step(10, 3) do |i| # 起始数字step,参数结束数字,步进
  16. puts "step #{i}"
  17. end

 array有each的属性,后面通过do 或者{}迭代读取参数或者执行脚本

5.times do |i| 就是执行几次的意思,i自动会上+

x.step(a,b) do |i|   x是起始数字,a是结束数字,b是步进

 

upto downto操作循环

  1. [sidian@VM_0_17_centos ruby_study]$ vim each.rb
  2. [sidian@VM_0_17_centos ruby_study]$ vim upto_downto.rb
  3. 2.upto(5) do |i|
  4. puts "upto#{i}"
  5. end
  6. 5.downto(2) do |i|
  7. puts "down#{i}"
  8. end
  9. ~

 

  1. [sidian@VM_0_17_centos ruby_study]$ ruby upto_downto.rb
  2. upto2
  3. upto3
  4. upto4
  5. upto5
  6. down5
  7. down4
  8. down3
  9. down2

 这个step,upto,downto应该都是同一个批次的命令,这里的取值都是包含最后的取值的,也就是最后那个数字能够读取到的。

 

错误捕捉,begin rescue else ensure 对于错误的捕捉

  1. begin # 相当于Python中的try
  2. puts "逻辑开始执行"
  3. 10 / 0
  4. rescue => e # 相当于Python中的except Except as e
  5. puts "错误接收到了"
  6. puts e
  7. else
  8. puts "正常处理开始了" # 这个Python中也有,是在用的很少
  9. ensure
  10. puts "这个我肯定要执行的" # 相当于Python中的finally
  11. end

 

  1. [sidian@VM_0_17_centos ruby_study]$ ruby begin_rescue.rb
  2. 逻辑开始执行
  3. 错误接收到了
  4. divided by 0
  5. 这个我肯定要执行的

 

最后写一个获取对象的方法.methods

 

以上就是ruby 简单笔记对比Python (待完善)的详细内容,更多关于ruby 简单笔记对比Python (待完善)的资料请关注九品源码其它相关文章!