zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    【Nginx】ngx_event_core_module模块
    ELMAH--Using HTTP Modules and Handlers to Create Pluggable ASP.NET Components 77 out of 90 rated th
    nyist oj 214 单调递增子序列(二) (动态规划经典)
    java 入门书籍(java7)
    ARCGIS将WGS84坐标投影到高斯平面
    【linux】linux下对java程序生成dump文件,并使用IBM Heap Analyzer进行分析,查找定位内存泄漏的问题代码
    【springboot】【socket】spring boot整合socket,实现服务器端两种消息推送
    【linux】linux修改open file 大小
    【docker】docker限制日志文件大小的方法+查看日志文件的方法
    【docker】docker部署spring boot服务,但是docker logs查看容器输出控制台日志,没有日志打印,日志未打印,docker logs不打印容器日志
  • 原文地址:https://www.cnblogs.com/sidianok/p/12865997.html
Copyright © 2011-2022 走看看