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


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

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

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

    [sidian@VM_0_17_centos ruby_study]$ ruby -v
    ruby 2.0.0p648 (2015-12-16) [x86_64-linux]
    [sidian@VM_0_17_centos ruby_study]$ python3 -V
    Python 3.7.4
    [sidian@VM_0_17_centos ruby_study]$ 
    

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

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

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

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

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

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

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

    [sidian@VM_0_17_centos ruby_study]$ cat class_player.rb 
    class Player
        def initialize(name = "sidian")
            @name = name
        end
        def show()
            puts "play: #{@name}"
        end
    end
    
    
    sidian = Player.new("wudian")
    sidian.show()
    world = Player.new("world")
    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)【暂时没有找到查看所有实例属性的函数或者方法】

    class Game
        def initialize(title = "学习", price = "无价")
            @title = title
            @price = price    # 实例属性复制
        end
        def show
            puts "标题是:#{@title}"
            puts "价格是:#{@price}"
        end
        def show2()
        end
        def show3
        end
    end
    
    puts Game.instance_methods(false)
    g = Game.new()
    puts g
    puts Game.instance_methods(true)
    puts g.instance_methods(false)
    ~                                         
    

     结果

     ruby class_game 
    show
    show2
    show3
    #<Game:0x00000000f9ac90>
    show
    show2
    show3
    nil?
    ===
    =~
    !~
    eql?
    hash
    <=>
    class
    singleton_class
    clone
    dup
    taint
    tainted?
    untaint
    untrust
    untrusted?
    trust
    freeze
    frozen?
    to_s
    inspect
    methods
    singleton_methods
    protected_methods
    private_methods
    public_methods
    instance_variables
    instance_variable_get
    instance_variable_set
    instance_variable_defined?
    remove_instance_variable
    instance_of?
    kind_of?
    is_a?
    tap
    send
    public_send
    respond_to?
    extend
    display
    method
    public_method
    define_singleton_method
    object_id
    to_enum
    enum_for
    ==
    equal?
    !
    !=
    instance_eval
    instance_exec
    __send__
    __id__
    class_game:20:in `<main>': undefined method `instance_methods' for #<Game:0x00000000f9ac90 @title="学习", @price="无价"> (NoMethodError)
    [sidian@VM_0_17_centos ruby_study]$ 
    

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

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

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

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

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

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

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

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

     结果

    [sidian@VM_0_17_centos ruby_study]$ ruby class_game 
    show
    show2
    show3
    #<Game:0x00000001446c08>
    标题是:学习
    价格是:无价
    

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

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

    Last login: Sun May 10 22:01:34 on ttys004
    You have mail.
    
    The default interactive shell is now zsh.
    To update your account to use zsh, please run `chsh -s /bin/zsh`.
    For more details, please visit https://support.apple.com/kb/HT208050.
    shijianongdeMBP:~ shijianzhong$ ssh tx
    Last login: Sun May 10 21:59:49 2020 from 115.194.189.151
    [sidian@VM_0_17_centos ~]$ ls
    all.sql             c_study  db1_out_txt  exec_new3.sh  mysql.log    newfile     test
    crystal_centos.tar  c.tar    dump.rdb     log2.txt      new3_report  ruby_study  test.txt
    [sidian@VM_0_17_centos ~]$ cd ruby_study/
    [sidian@VM_0_17_centos ruby_study]$ ls
    ary.rb  begin_end.rb  begin.rb  hello.rb  here.rb  hsh.rb  方法
    [sidian@VM_0_17_centos ruby_study]$ ruby hello.rb 
    hello.rb:8:in `<main>': undefined local variable or method `syahello' for main:Object (NameError)
    [sidian@VM_0_17_centos ruby_study]$ ruby hello.rb 
    hello sidian.
    [sidian@VM_0_17_centos ruby_study]$ ruby hello.rb 
    hello wudian.
    [sidian@VM_0_17_centos ruby_study]$  ruby class_player.rb 
    class_player.rb:6:in `show': undefined method `purs' for #<Player:0x000000013b8160> (NoMethodError)
    	from class_player.rb:12:in `<main>'
    [sidian@VM_0_17_centos ruby_study]$ ruby hello.rb 
    hello wudian.
    [sidian@VM_0_17_centos ruby_study]$ ruby class_player.rb 
    play: 
    [sidian@VM_0_17_centos ruby_study]$ ruby class_player.rb 
    class_player.rb:11:in `initialize': wrong number of arguments (1 for 0) (ArgumentError)
    	from class_player.rb:11:in `new'
    	from class_player.rb:11:in `<main>'
    [sidian@VM_0_17_centos ruby_study]$ ruby class_player.rb 
    class_player.rb:11:in `initialize': wrong number of arguments (1 for 0) (ArgumentError)
    	from class_player.rb:11:in `new'
    	from class_player.rb:11:in `<main>'
    [sidian@VM_0_17_centos ruby_study]$ ruby class_player.rb 
    play: 
    [sidian@VM_0_17_centos ruby_study]$ ruby class_player.rb 
    play: sidian
    [sidian@VM_0_17_centos ruby_study]$ ruby class_player.rb 
    play: wudian
    [sidian@VM_0_17_centos ruby_study]$ ruby class_player.rb 
    play: wudian
    play: world
    [sidian@VM_0_17_centos ruby_study]$ ls
    ary.rb  begin_end.rb  begin.rb  class_player.rb  hello.rb  here.rb  hsh.rb  方法
    [sidian@VM_0_17_centos ruby_study]$ cat hello.rb 
    #!/usr/bin/ruby -w
    
    def sayhello(name="sidian")
        puts "hello #{name}."
    end
    
    #sayhello("sidian")
    sayhello("wudian")
    [sidian@VM_0_17_centos ruby_study]$ cat class_player.rb 
    class Player
        def initialize(name = "sidian")
            @name = name
        end
        def show()
            puts "play: #{@name}"
        end
    end
    
    
    sidian = Player.new("wudian")
    sidian.show()
    world = Player.new("world")
    world.show()
    [sidian@VM_0_17_centos ruby_study]$ packet_write_wait: Connection to 212.64.47.160 port 22: Broken pipe
    shijianongdeMBP:~ shijianzhong$ ssh tx
    Last login: Sun May 10 23:10:31 2020 from 115.194.189.151
    [sidian@VM_0_17_centos ~]$ ls
    all.sql             c_study  db1_out_txt  exec_new3.sh  mysql.log    newfile     test
    crystal_centos.tar  c.tar    dump.rdb     log2.txt      new3_report  ruby_study  test.txt
    [sidian@VM_0_17_centos ~]$ cd ruby_study/
    [sidian@VM_0_17_centos ruby_study]$ cal
          五月 2020     
    日 一 二 三 四 五 六
                    1  2
     3  4  5  6  7  8  9
    10 11 12 13 14 15 16
    17 18 19 20 21 22 23
    24 25 26 27 28 29 30
    31
    [sidian@VM_0_17_centos ruby_study]$ pqd
    -bash: pqd: 未找到命令
    [sidian@VM_0_17_centos ruby_study]$ pwd
    /home/sidian/ruby_study
    [sidian@VM_0_17_centos ruby_study]$ ls
    ary.rb  begin_end.rb  begin.rb  class_game  class_player.rb  hello.rb  here.rb  hsh.rb  方法
    [sidian@VM_0_17_centos ruby_study]$ cat class_player.rb > class_player2.rb
    [sidian@VM_0_17_centos ruby_study]$ vim class_player2.rb 
    
    class Player
        attr_accessor :price, :name    # 只有这里定义了,实例才能在外面读取该属性。
        def initialize(name = "sidian", price = 150)
            @name = name
            @price = price
        end
        def show()
            puts "play: #{@name}"
            puts "price: #{@price}"
        end
    end
    
    
    sidian = Player.new("wudian")
    sidian.show()
    world = Player.new("world")
    world.show()
    puts world.respond_to?("price=").to_s
    world.price = 500
    world.name= "白痴"
    world.show()
    puts "
    "
    puts world.name
    puts Player.instance_methods(false)
    ~                                                                                                                           
    ~                                                                                                                           
    ~                                                                                                                           
    "class_player2.rb" 24L, 474C 已写入                                                                       2,25         全部
    
    [sidian@VM_0_17_centos ruby_study]$ ruby class_player2.rb 
    play: wudian
    price: 150
    play: world
    price: 150
    true
    play: 白痴
    price: 500
    
    白痴
    price
    price=
    name
    name=
    show
    

    列表的操作 each do,  each_with_index

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

    备注的使用

    一行备注 跟Python 一样  #

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

    之后全部备注 __END__

    操作符号

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

    irb(main):016:0> ! nil
    => true
    irb(main):017:0> ! false
    => true
    irb(main):018:0> ! []
    => false
    irb(main):020:0> ! 0
    => false
    irb(main):021:0> 
    

     ruby 中只有false 与 nil才为假

    三项运算式

    irb(main):004:0> point
    => 30
    irb(main):005:0> puts point >= 30 ?"mvp": "一般"
    mvp
    => nil
    irb(main):006:0> puts point > 30 ?"mvp": "一般"
    一般
    => nil
    irb(main):007:0> 
    

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

    Python中的用法

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

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

    字符串的操作 + <<  *

    irb(main):007:0> a = "hello"
    => "hello"
    irb(main):008:0> b = "sidian"
    => "sidian"
    irb(main):009:0> a+b
    => "hellosidian"
    irb(main):010:0> a << b
    => "hellosidian"
    irb(main):012:0> a *5
    => "hellosidianhellosidianhellosidianhellosidianhellosidian"
    irb(main):013:0> a
    => "hellosidian"
    irb(main):014:0> 
    

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

    单引号与双引号的区别

    irb(main):021:0> "
    "
    => "
    "
    irb(main):022:0> p1 = "我号"
    => "我号"
    irb(main):023:0> puts p1
    我号
    => nil
    irb(main):024:0> "aa
    bb"
    => "aa
    bb"
    irb(main):025:0> p2 = 'aa
    bb'
    => "aa\nbb"
    irb(main):026:0> puts p2
    aa
    bb
    => nil
    irb(main):027:0> myp = "#{1+2}"
    => "3"
    irb(main):028:0> myp = '#{1+2}'
    => "#{1+2}"
    irb(main):029:0> puts myp
    #{1+2}
    => nil
    irb(main):030:0> 
    

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

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

    irb(main):033:0> mvp = {"sidian" => 'niubi',"wudiain"=>5}
    => {"sidian"=>"niubi", "wudiain"=>5}
    irb(main):034:0> myp
    => "#{1+2}"
    irb(main):035:0> mvp
    => {"sidian"=>"niubi", "wudiain"=>5}
    irb(main):036:0> mvp["wudian"]
    => nil
    irb(main):037:0> mvp["sidian"]
    => "niubi"
    irb(main):038:0> mvp["sidiain"]
    => nil
    irb(main):039:0> mvp["wudiain"]
    => 5
    irb(main):041:0> player = {name: 'sidian',age:18}
    => {:name=>"sidian", :age=>18}
    irb(main):042:0> player[:name]
    => "sidian"
    irb(main):043:0> player[:nam]
    => nil
    irb(main):044:0> 
    

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

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

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

    irb(main):047:0> a = 1.23
    => 1.23
    irb(main):048:0> a.to_i
    => 1
    irb(main):049:0> a.to_f
    => 1.23
    irb(main):050:0> a = "实践中"
    => "实践中"
    irb(main):051:0> b = 
    irb(main):052:0* 
    irb(main):053:0* b = "123"
    => "123"
    irb(main):054:0> b.to_i + 456
    => 579
    irb(main):055:0> c = "1.55"
    => "1.55"
    irb(main):056:0> c.to_i
    => 1
    irb(main):057:0> c = 1.55
    => 1.55
    irb(main):058:0> c.to_i
    => 1
    irb(main):059:0> 
    

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

    class 再入门

    class Player
        def initialize(name = "sidian")
            @name = name
        end 
        def show()
            puts "play: #{@name}"
        end 
        def self.toStr    # 静态方法不能被实例调用
            puts "my method is static"
        end 
    end
    
    
    sidian = Player.new("wudian")
    sidian.show()
    world = Player.new("world")
    world.show()
    Player.toStr
    

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

    类的继承

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

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

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

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

    module BaseFunc
         Version = "0.0.1"
    
        def v
            return Version
        end
    
        def add(a, b)      # 非静态方法不属于模块方法
            return a+b
        end
                
        def self.showVersiona    # 静态方法
            return Version
        end    
    
        module_function :v    # 定义为静态方法
          
    end
    
    puts BaseFunc::Version   # 模块中的属性通过::读取
    #puts BaseDunc.Version   # .不能读取 
    class BaseClass include BaseFunc   # 类中包含读取BaseFunc模块
    end
    
    puts BaseClass::Version
    b = BaseClass.new
    puts b.add(1,2)
    ~                  
    

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

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

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

    条件控制文

    if elsif else unless else case when else

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

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

    循环处理

    gamelist = ["one", "two", "three"]
    
    for g in gamelist do
        puts g
    end
    
    
    for i in 1..5 do
        puts i
    end
    
    for i in 1...5 do
        puts i
    end
    
    n = 1
    while n < 5 do
        puts "while #{n}"
        n += 1
    end
    puts n
    until n == 2 do    # 这个也很有意思,这个也是不成立才执行,日常开发用的少
        puts "until #{n}"
        n -= 1
    end
    ~            
    

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

    特殊循环

    g_list = ["one", "two", "three"]
    
    g_list.each {|game| puts game}
    
    
    g_list.each do |game|
        puts game
    end
    
    g_list.each_with_index do |g, i|
        puts g + (i+1).to_s
    end
      
    g_list.each_with_index{
       |g, i| puts g, i
    }
    
    5.times do |i|      # 重复执行
        puts "time #{i}"
    end
    
    1.step(10, 3) do |i|   # 起始数字step,参数结束数字,步进
        puts "step #{i}"
    end
    

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

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

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

    upto downto操作循环

    [sidian@VM_0_17_centos ruby_study]$ vim each.rb
    [sidian@VM_0_17_centos ruby_study]$ vim upto_downto.rb
    
    2.upto(5) do |i|
        puts "upto#{i}"
    end
    5.downto(2) do |i|
        puts "down#{i}"
    end
    ~         
    
    [sidian@VM_0_17_centos ruby_study]$ ruby upto_downto.rb 
    upto2
    upto3
    upto4
    upto5
    down5
    down4
    down3
    down2
    

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

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

    begin    # 相当于Python中的try
        puts "逻辑开始执行"
        10 / 0
    rescue => e    # 相当于Python中的except Except as e
        puts "错误接收到了"
        puts e
    else
        puts "正常处理开始了"  # 这个Python中也有,是在用的很少
    ensure
        puts "这个我肯定要执行的" # 相当于Python中的finally
    end
    
    [sidian@VM_0_17_centos ruby_study]$ ruby begin_rescue.rb 
    逻辑开始执行
    错误接收到了
    divided by 0
    这个我肯定要执行的
    

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

  • 相关阅读:
    List装form
    《Java设计模式》之调停者模式(Mediator)
    android 4.0 禁用系统home键
    最大权二分匹配
    hdu 3667 /2010哈尔滨赛区H题 费用与流量为非线性关系/费用流
    【python】filter()
    【python】linux将python改为默认3.4版本
    【linux】VMware12.0安装
    【python】lxml-The E-factory
    【xml】python的lxml库使用
  • 原文地址:https://www.cnblogs.com/sidianok/p/12865997.html
Copyright © 2020-2023  润新知