首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > Ruby Rails >

python 与 ruby 其间的区别

2012-12-20 
python 与 ruby 之间的区别Number 类型python 是 int 和 longruby 是 Fixnum 和 Bignum num 87.times do

python 与 ruby 之间的区别
Number 类型

python 是 int 和 long
ruby 是 Fixnum 和 Bignum

num = 87.times do  print num.type, " ", num, "\n"  num *= numend produces: Fixnum 8Fixnum 64Fixnum 4096Fixnum 16777216Bignum 281474976710656Bignum 79228162514264337593543950336Bignum 6277101735386680763835789423207666416102355444464034512896


对象区别
isinstance(object, classinfo) #是否为类或继承类的实例class A(object):...     pass... class B(A):...     pass>>> b = B()>>> isinstance(b,B)59: True>>> isinstance(b,A)60: True


instance_of?(object, classinfo) #是否为该类kind_of?(object, classinfo) # #是否为类或继承类的实例


String 类型

1. 类型
>>> type("s")20: <type 'str'>>>> type(u"s")21: <type 'unicode'>


irb(main):236:0> "dd".type=> String


2.字符串格式化

>>> print '%s %s' % ("hi","world")>>> print '%(name)s %(v)s' % {"name":1 ,"v":2}



>>> a= "world">>> puts "hello \t #{a}"


3. print函数
>>> print "hi world" #换行>>>  print "hi world", #不换行


>>> puts "hi world" #换行>>>  print "hi world"  #不换行


4.多行字符串
astring = """   The body of the string    is the input lines up to    one ending with the same    text that followed the '<<'"""


aString = <<END_OF_STRING    The body of the string    is the input lines up to    one ending with the same    text that followed the '<<'END_OF_STRING


字符串拼接,这个比较重要要提一下join方法
 ",".join([1,2,3])


[1,2,3].join(",")



5.ruby的其他表现形式
>>> %q {hi world} #single-quoted string >>>  %Q {hi world} #double-quoted string 




Range 类型

在这里ruby 使用 a.to_enum (Included Modules Enumerable)的方法对序列进行迭代,而python的range 直接生成一个数组,python的xrange的实现与 ruby的Enumerable类似

>>> range(10)>>> xrange(10)


>>> (0..9).to_a >>> 0..9


Regular Expressions
ruby 里的正则表达式似乎没有global 参数
IGNORECASE: INT2FIX(RE_OPTION_IGNORECASE)
EXTENDED:   INT2FIX(RE_OPTION_EXTENDED)
MULTILINE:  INT2FIX(RE_OPTION_MULTILINE)

>>> a = "Fats Waller"  >>> a =~ /a/  #这里返回匹配位置


python 也没有global 但是有 DOTALL 并且支持re.UNICODE
>>> d = re.match(r"(.+)+","abc\nccc",re.DOTALL)>>> d.groups()42: ('abc\nccc',)


>>> re.subn(r"(hello)","\g<1> edisonlz's","hello world")51: ("hello edisonlz's world", 1)


irb(main):020:0> "edison:lz".gsub(/(\w+):(\w+)/,'\2,\1')=> "lz,edison"


>>> type(r"dd")52: <type 'str'>


irb(main):021:0> /dd/.type=> Regexp


对Class 的扩展
python 使用metaclass对类进行扩展(初始化类的类),而ruby 使用 partial class和 mixin 对类进行扩展,python 不支持 partial class  和 mixin的方法,


class ModelBase(type):    """Metaclass of the Model.""" def __new__(cls, name, bases, dct):        return type.__new__(cls, name, bases, dct)    def __init__(cls, name, bases, attrs):        """        intialize name base modle  attribute        param:            name:string            bases:base model            attrs: attribute        """        super(ModelBase, cls).__init__(name, bases, attrs)        cls._initialize_attributes(cls, name, bases, attrs)        cls._initialize_manager(cls)        def _initialize_attributes(self,model_class, name, bases, attrs):        """        Initialize the attributes of the model.        param:            model_class:object            name:string            bases:base model            attrs:attribute        """        #主要功能:添加属性列表        model_class.attributes = {}        for k, v in attrs.iteritems():            if isinstance(v,Attribute):                    model_class.attributes[k] = v                    v.name = v.name or k            def _initialize_manager(self,model_class):        """        Initializes the objects manager attribute of the model.        param:            model_class:object        """        model_class.objects = ModelSet(model_class)        passclass Model(object):    __metaclass__ = ModelBase    



class Array    def inject(n)       each { |value| n = yield(n, value) }       n    end    def sum      inject(0) { |n, value| n + value }    end    def product      inject(1) { |n, value| n * value }    end  end  [ 1, 2, 3, 4, 5 ].sum  ? 15  [ 1, 2, 3, 4, 5 ].product  ? 120  

decorator的应用
python 使用func decorator 的方法,ruby 使用 yield block的方法和Rails alias_method的方法

>>> _cache = {}... def cache(sec=10):...     def wrap(f):...         def func(*args,**kwargs):...             data = _cache.get(",".join(args))...             if not data:...                 data = f(*args,**kwargs)...                 _cache[",".join(args)] = data...                 print "no cache"...             else:...                 print "in cache"...             return data...         return func...     return wrap... ... @cache(10)... def page(html):...     return "response %s" % html>>> page("haha")no cache70: 'response haha'>>> page("haha")in cache71: 'response haha'



class Object def memory(name)         ori = "ori_#{name}"          alias_method ori,name                  define_method(name) do          cache = instance_variable_get("@#{name}")          if cache            return cache          else            cache =  send(ori)            instance_variable_set("@#{name}",cache)            return cache          end         end endend class A def run   puts "sleeping"         sleep 5  "a" end memory(:run)end  a = A.newputs a.runputs a.run



def select(n) t = [] for i in n t.push(i) if yield(i)  endreturn t  end=> nilirb(main):052:0> select([1,2,3]){|i| i>2}=> [3]


module ActiveRecordExtension    def self.included(base)        base.extend(ClassMethods)        base.class_eval do            class << self                p "Aliasing find" # Used to check if alias_method isn't called twice                alias_method :find_without_someting, :find                alias_method :find, :find_with_someting            end        end    end    module ClassMethods # :nodoc:        def find_with_something(*args)          p "0"          x = find_without_something(*args)          p "1"          return x        end    end   end

ruby还有一个写滴向javascript滴东东
irb(main):015:0> c = "1"irb(main):015:0> class << cirb(main):016:1>   def to_ffirb(main):017:2>     self.to_firb(main):018:2>     endirb(main):019:1>   end=> nilirb(main):020:0> c.to_ff1.0


lambda的应用
python和ruby 中都有有lambda,并且意思也都一样,但是python 中没有 proc
ruby 中的 lambda  和 proc 是一个东东
proc   { |...| block }  => a_proc
lambda { |...| block }  => a_proc
---------------------------------------------
Equivalent to Proc.new, except the resulting Proc objects check the number of parameters passed when called.


>>> def f(x):...     return x*2...     >>> f(3)>>> g = lambda x: x*2  >>> g(3)



>>> g = lambda { |x| x*2  }>>> g.call(3)


一般情况lambda 表达式与闭包一起应用

def nTimes(aThing)    return proc { |n| aThing * n }  end   p1 = nTimes(23)  p1.call(3)  ? 69  p1.call(4)  ? 92  p2 = nTimes("Hello ")  p2.call(3)  ? "Hello Hello Hello "  



python 中滴闭包,这里举个小列子,用于一次完成多个替换
>>> import re... def mre(dic,text):...     rc = re.compile("|".join( map( re.escape,dic.keys() ) ) )...     print rc...     def get_value(match):...         return dic.get(match.group(0))...     return rc.sub(get_value,text)>>> dic = {"a":"A","b":"B"}... mre(dic,"abab")<_sre.SRE_Pattern object at 0x01A8CED0>115: 'ABAB'



yield  区别

在python 中yield 是一个generator 可以保存住当前的context,这一点和ruby 类似,
但是ruby的yield 是调用一个block 也就是调用一个 proc.new {}
我个人编程不习惯使用python的yield

>>> def y(n):...     for  i in xrange(n):...         yield i... for g in y(10):...     print g ,0 1 2 3 4 5 6 7 8 9


def any(n) t = [] for i in n return true if yield(i)  endreturn false  end=> nilirb(main):052:0> any([0,1,0]){|i|  i!=0}=>  true



symbol and tuple
在python 中建议在传递参数和迭代的时候使用tuple来减少开销
在ruby中大家使用 symbol 来提高访问速度,都是挺好的特性
:edisonlz.id('edison','lz')



inheritance
python 中支持多继承,ruby 不支持多继承但是支持mixin
python 多继承的查找链规则: This is depth-first, left-to-right
ruby 中的查找链规则:self->mixin->super

class Base():    passclass Car():    passclass BMW(Base,Car):    pass


ruby中的继承:
in the diagram below, "normal" classes are green, and meta-classes are blue. The dashed lines represent "instance off" (the "klass" pointer), and the solid lines represent "inherits" (the "super" method):



block
The blocks used by iterators (such as loop and each) are a little different. Normally, the local variables created in these blocks are not accessible outside the block. [ 1, 2, 3 ].each do |x|  y = x + 1end[ x, y ] produces: prog.rb:4: undefined local variable or method `x'for #<Object:0x401c0ce0> (NameError)



ruby独有的特性
What happens when you copy a frozen object? That depends on the method you use. If you call an object's clone method, the entire object state (including whether it is frozen) is copied to the new object. On the other hand, dup typically copies only the object's contents---the new copy will not inherit the frozen status. str1 = "hello"  str1.freeze  ? "hello"  str1.frozen?  ? true  str2 = str1.clone  str2.frozen?  ? true  str3 = str1.dup  str3.frozen?  ? false  


private protected,和public
python 中是没有private protected,和public滴
ruby中对private protected,和public是有定义滴,并且能对定义重载

>>> class Base(object):...     def __p(self):...         print "private"...     def _prot(self):...         print "protected"...     def p(self):...         print "public">>> b = Base()>>> b.__p()Traceback (most recent call last):  File "<pyshell#24>", line 1, in <module>    b.__p()AttributeError: 'Base' object has no attribute '__p'>>> b._prot()protected>>> b.p()public>>> b._Base__p0: <bound method Base.__p of <__main__.Base object at 0x01985C70>>>>> b._Base__p()private


class Base  def aMethod    puts "Got here"  end  private :aMethodendclass Derived1 < Base  public :aMethodendclass Derived2 < Baseend 



令人困惑地instance_eval and class_eval

Use ClassName.instance_eval to define class methods.Use ClassName.class_eval to define instance methods.That’s right. Not a typo. Here are some examples, shamelessly stolen from his post:1# Defining a class method with instance_eval2Fixnum.instance_eval { def ten; 10; end }3Fixnum.ten #=> 104 5# Defining an instance method with class_eval6Fixnum.class_eval { def number; self; end }77.number #=> 7



method_missing

ruby 中独有滴methods missing 使得rails更加滴方便

user.find_by_XXX
uesr.find_or_create_by_xxx
当然这些都不神秘,

def method_missing(method_id, *arguments, &block)          if match = DynamicFinderMatch.match(method_id)            attribute_names = match.attribute_names            super unless all_attributes_exists?(attribute_names)            if match.finder?class DynamicFinderMatch    def self.match(method)      df_match = self.new(method)      df_match.finder ? df_match : nil    end    def initialize(method)      @finder = :first      case method.to_s      when /^find_(all_by|last_by|by)_([_a-zA-Z]\w*)$/        @finder = :last if $1 == 'last_by'        @finder = :all if $1 == 'all_by'        names = $2      when /^find_by_([_a-zA-Z]\w*)\!$/        @bang = true        names = $1      when /^find_or_(initialize|create)_by_([_a-zA-Z]\w*)$/        @instantiator = $1 == 'initialize' ? :new : :create        names = $2      else        @finder = nil      end      @attribute_names = names && names.split('_and_')    end    attr_reader :finder, :attribute_names, :instantiator    def finder?      !@finder.nil? && @instantiator.nil?    end    def instantiator?      @finder == :first && !@instantiator.nil?    end    def bang?      @bang    end  end


const_missing 也不神秘
class Module  define_method(:const_missing) do |name|    name.to_s  endA =》 'A'


查找路径
python sys.pathruby $:rails $LOAD_PATH$: == $LOAD_PATH


django 和rails之间的区别
框架:两种框架都是MVC,

REST: django 对REST 支持的并不好, 不像Rails那面优雅

模板系统:django的模板系统那就是个X,实在受不了,读取模板文件要几百毫秒,但幸运滴是,有jinja2模板系统,使用c写滴,这个很让人满意,rails虽然也有第三方的模板系统但是,与rails版本有关联,这个不大好

Model : django 使用 objects.filter和objects.get 功能比较少,而且查询关键字比较怪
               rails 使用 find,并且支持 select ,where 等字段重写,挺好滴

DB :目前 django 还不支持db connection poll,需要第三方滴
         rails 目前支持 db connection poll

但是除了django 和 rails 相比,python 在其他领域那就比ruby强太多了,
例如:wxpython,tornado,twisted,pypy, cjson, pylibmc,都是被人津津乐道的,ruby 似乎只有rails可以被人津津乐道,杯具啊!



加载环境 rails 和 django 使用的加载环境方法基本一样

  rails 加载顺序

 
  require File.join(File.dirname(__FILE__), 'boot')    # All that for this:  Rails.boot!  def boot!      unless booted?        preinitialize        pick_boot.run      end   end  def preinitialize      load(preinitializer_path) if File.exist?(preinitializer_path)  end  def pick_boot      (vendor_rails? ? VendorBoot : GemBoot).new  end  class Boot    def run      load_initializer      Rails::Initializer.run(:set_load_path)    end  end  class GemBoot < Boot    def load_initializer      self.class.load_rubygems      load_rails_gem      require 'initializer'    end  end    #   Rails::Initializer.run do |config|  #     config.frameworks -= [ :action_mailer ]  #   end   class Initializer    def self.run(command = :process, configuration = Configuration.new)      yield configuration if block_given?      initializer = new configuration      initializer.send(command)      initializer    end   def process      Rails.configuration = configuration      check_ruby_version      install_gem_spec_stubs      set_load_path      add_gem_load_paths      require_frameworks      set_autoload_paths      add_plugin_load_paths      load_environment      preload_frameworks      initialize_encoding      initialize_database      initialize_cache      initialize_framework_caches      initialize_logger      initialize_framework_logging      initialize_dependency_mechanism      initialize_whiny_nils      initialize_time_zone      initialize_i18n      initialize_framework_settings      initialize_framework_views      initialize_metal      add_support_load_paths      check_for_unbuilt_gems      load_gems      load_plugins      # pick up any gems that plugins depend on      add_gem_load_paths      load_gems      check_gem_dependencies      # bail out if gems are missing - note that check_gem_dependencies will have      # already called abort() unless $gems_rake_task is set      return unless gems_dependencies_loaded      load_application_initializers      # the framework is now fully initialized      after_initialize      # Setup database middleware after initializers have run      initialize_database_middleware      # Prepare dispatcher callbacks and run 'prepare' callbacks      prepare_dispatcher      # Routing must be initialized after plugins to allow the former to extend the routes      initialize_routing      # Observers are loaded after plugins in case Observers or observed models are modified by plugins.      load_observers      # Load view path cache      load_view_paths      # Load application classes      load_application_classes      # Disable dependency loading during request cycle      disable_dependency_loading      # Flag initialized      Rails.initialized = true    end         def default_load_paths        paths = []        # Add the old mock paths only if the directories exists        paths.concat(Dir["#{root_path}/test/mocks/#{environment}"]) if File.exists?("#{root_path}/test/mocks/#{environment}")        # Add the app's controller directory        paths.concat(Dir["#{root_path}/app/controllers/"])        # Followed by the standard includes.        paths.concat %w(          app          app/metal          app/models          app/controllers          app/helpers          app/services          lib          vendor        ).map { |dir| "#{root_path}/#{dir}" }.select { |dir| File.directory?(dir) }        paths.concat builtin_directories      end  return to environment.rb  proceed......



在谈一下rack 和 tornado
tornado是一个lightweight web server
可是rack  比tornado还要 lightweight ,因为tornado 实现了自己的网络层
,rack则使用fastcgi,cgi,mongrel这些现有滴实现
还有ruby 滴sinatra 是rack 滴扩展,但是提倡 minimalist,更少地代码。


对ruby滴扩展


class NilClass  def try(*args)   nil  endend=> niluser = User.find(100)user ? user.name : niluser.try(:name)



class Objectdef blank? return  respond_to?(:empty) ? empty? : !selfenddef present?!blank?endend=> nila = ""=> ""a.present?=> falsea.blank?=> true



ruby metaprogramming


yes = "yes"ok = "ok"String.class_eval do  define_method(yes) do   print ok endendputs "123".yes #=> ok#create singleton methods#String.class_eval do# class << self #         define_method(yes) do#           print ok#         end# end#end#puts String.yes #C:/Users/liuzheng/Desktop/a.rb:46:in `singletonclass': undefined local variable#or method `yes' for #<Class:String> (NameError)#        from C:/Users/liuzheng/Desktop/a.rb:45:in `block in <main>'#        from C:/Users/liuzheng/Desktop/a.rb:44:in `class_eval'#        from C:/Users/liuzheng/Desktop/a.rb:44:in `<main>'#because class << self has new scopeyes = "yes"ok = "ok"metaclass = (class <<String; self;end)metaclass.class_eval do  define_method(yes) do     puts ok endendputs String.yes => "ok"



2 楼 chloerei 2011-05-16   我觉得这些只是很表面的区别,真正的区别是解决问题的思路。不过我不懂python就无法比较了。 3 楼 edisonlz 2011-05-16   chloerei 写道我觉得这些只是很表面的区别,真正的区别是解决问题的思路。不过我不懂python就无法比较了。

说滴对,还在继续总结,在后面会有解决问题的区别


4 楼 edisonlz 2011-05-17   今日更新了,对Class 的扩张 往下滴 5 楼 sevk 2011-05-17   ruby string 可以这样写:
s= "
hello 'world'
"


s= '
hello "world"
'

puts s

6 楼 kanny87929 2011-05-17   做java的路过,看到这样的代码极其的不和谐 7 楼 googya 2011-05-17   kanny87929 写道做java的路过,看到这样的代码极其的不和谐
我倒是没有看到什么不和谐的地方。。。。 8 楼 l8653668 2011-05-17   python和ruby和相似?只有少部分不同?学了python的话是不是学ruby也很容易上手了? 9 楼 jerry 2011-05-17   一个Rails就足够了。1万把步枪顶不了一个“小胖子” 10 楼 sevk 2011-05-18   jerry 写道一个Rails就足够了。1万把步枪顶不了一个“小胖子”

有道理,ruby的gem会越来越好用的. 11 楼 john813 2011-05-18   ruby是给“玩”程序的人用的,python是给“写”程序的人用的。一种带有强烈的极客风格,一种带有君子的谦谦品质。另外,python奉行“做一件事只有一种方式”,ruby奉行“做一件事可以有n种方式”。

最后一点是我在评估后选择python的最重要原因。 12 楼 edisonlz 2011-05-18   说滴好
john813 写道ruby是给“玩”程序的人用的,python是给“写”程序的人用的。一种带有强烈的极客风格,一种带有君子的谦谦品质。另外,python奉行“做一件事只有一种方式”,ruby奉行“做一件事可以有n种方式”。

最后一点是我在评估后选择python的最重要原因。

13 楼 simplemx 2011-05-20   lz几天就小更新一下,真有心 14 楼 skyfen 2011-05-20   LZ说的不错啊,加油。我只会python,c++没办法,不懂Ruby 15 楼 tonyseek 2011-05-21   可以补充否?Python 有 with 语法用于文件、数据库等上下文管理~ 16 楼 edisonlz 2011-05-21   今天 又更新了一些关于 metaclass 滴东东,希望大家喜欢

热点排行