Ruby'nin Python'un sahip olmadığı ve tam tersi ne var?


263

Python ve Ruby hakkında pek çok tartışma var ve ben hepsini tamamen yararsız buluyorum, çünkü hepsi X özelliğinin neden Y dilinde emdiğini ya da aslında bu Y dilinin X'e sahip olmadığını iddia ediyorlar. Ayrıca neden Python'u tercih ettiğimi de biliyorum, ama bu aynı zamanda özneldir ve gelişimde benim gibi aynı zevklere sahip olmayabilecekleri için kimseyi seçmesine yardımcı olmaz.

Bu nedenle, farklılıkları objektif olarak listelemek ilginç olacaktır. Yani "Python'un lambdasları berbat" değil. Bunun yerine Ruby'nin lambdaslarının Python'un yapamayacağını neler yapabileceğini açıklayın. Öznellik yok. Örnek kod iyi!

Bir cevapta birkaç farklılık yok, lütfen. Ve doğru olduğunu bildiklerinizi oylayın ve bildiklerinizi yanlış (veya öznel) yapın. Ayrıca, sözdizimindeki farklılıklar ilginç değildir. Python'un Ruby'nin parantez ve uçlarla ne yaptığını girintiyle yaptığını biliyoruz ve buna Python'da self denir.

GÜNCELLEME: Bu artık bir topluluk wiki'si, bu yüzden büyük farklılıkları buraya ekleyebiliriz.

Ruby sınıf gövdesinde bir sınıf referansı var

Ruby'de zaten sınıf gövdesindeki sınıf (benlik) için bir referansınız vardır. Python'da, sınıf inşaatı bitene kadar sınıfa referansınız yoktur.

Bir örnek:

class Kaka
  puts self
end

bu durumda kendini sınıf, ve bu kod "Kaka" çıktı. Sınıf adını yazdırmanın veya başka yollarla Python'daki sınıf tanımı gövdesinden sınıfa erişmenin bir yolu yoktur (dış yöntem tanımları).

Tüm sınıflar Ruby'de değiştirilebilir

Bu, çekirdek sınıflara uzantılar geliştirmenizi sağlar. Bir ray uzantısına örnek:

class String
  def starts_with?(other)
    head = self[0, other.length]
    head == other
  end
end

Python (bir ''.startswithyöntem olmadığını hayal edin ):

def starts_with(s, prefix):
    return s[:len(prefix)] == prefix

Herhangi bir dizide kullanabilirsiniz (sadece dizelerde değil). Kullanmak için açıkça almanız gerekir , örn from some_module import starts_with.

Ruby, Perl benzeri komut dosyası oluşturma özelliklerine sahiptir

Ruby, birinci sınıf normal ifadelere, $ değişkenli, satır satır giriş döngüsüne ve awk / perl satır giriş döngüsüne ve metin dosyalarını birleştiren veya diğer programlar için tutkal kodu görevi gören küçük kabuk komut dosyaları yazmaya daha uygun hale getiren diğer özelliklere sahiptir.

Ruby birinci sınıf devam ediyor

Callcc bildirimi sayesinde. Python'da çeşitli tekniklerle süreklilik oluşturabilirsiniz, ancak dilde yerleşik bir destek yoktur.

Ruby'nin blokları var

"Do" ifadesiyle Ruby'de do'nun önündeki yönteme argüman olarak iletilecek ve oradan çağrılacak çok satırlı anonim bir işlev oluşturabilirsiniz. Bunun yerine Python'da bunu bir yöntem geçirerek ya da jeneratörlerle yaparsınız.

Yakut:

amethod { |here|
    many=lines+of+code
    goes(here)
}

Python (Ruby blokları Python'daki farklı yapılara karşılık gelir):

with amethod() as here: # `amethod() is a context manager
    many=lines+of+code
    goes(here)

Veya

for here in amethod(): # `amethod()` is an iterable
    many=lines+of+code
    goes(here)

Veya

def function(here):
    many=lines+of+code
    goes(here)

amethod(function)     # `function` is a callback

İlginç bir şekilde, Ruby'de bir blok çağırmak için uygunluk ifadesine Python'da bir jeneratör oluşturacak olan "verim" denir.

Yakut:

def themethod
    yield 5
end

themethod do |foo|
    puts foo
end

Python:

def themethod():
    yield 5

for foo in themethod():
    print foo

İlkeler farklı olmasına rağmen sonuç çarpıcı biçimde benzerdir.

Ruby, işlevsel stil (boru benzeri) programlamayı daha kolay destekler

myList.map(&:description).reject(&:empty?).join("\n")

Python:

descriptions = (f.description() for f in mylist)
"\n".join(filter(len, descriptions))

Python'un yerleşik jeneratörleri vardır (bunlar yukarıda belirtildiği gibi Ruby blokları gibi kullanılır)

Python'un dilde jeneratörler için desteği var. Ruby 1.8'de bir bloktan jeneratör oluşturmak için süreklilikleri kullanan jeneratör modülünü kullanabilirsiniz. Veya sadece bir blok / proc / lambda kullanabilirsiniz! Dahası, Ruby 1.9'da Fiberler jeneratörlerdir ve kullanılabilirler ve Enumerator sınıfı yerleşik bir jeneratör 4'tür.

docs.python.org bu jeneratör örneğine sahiptir:

def reverse(data):
    for index in range(len(data)-1, -1, -1):
        yield data[index]

Bunu yukarıdaki blok örnekleriyle karşılaştırın.

Python'un esnek ad alanı kullanımı var

Ruby'de, bir dosyayı içe requireaktardığınızda, o dosyada tanımlanan her şey genel ad alanınızda sona erer. Bu, ad alanı kirliliğine neden olur. Bunun çözümü Rubys modülleridir. Ancak modülle bir ad alanı oluşturursanız, içerilen sınıflara erişmek için bu ad alanını kullanmanız gerekir.

Python'da dosya bir modüldür ve içerdiği adları ile içe aktarabilir from themodule import *, böylece isterseniz ad alanını kirletebilirsiniz. Ancak, yalnızca seçili adları ile içe aktarabilir from themodule import aname, anotherveya adlarına basitçe import themoduleve sonra erişebilirsiniz themodule.aname. Ad alanınızda daha fazla seviye istiyorsanız, modül ve __init__.pydosya içeren dizinler olabilir .

Python'un öğretileri var

Docstrings, modüllere, işlevlere ve yöntemlere bağlı olan ve çalışma zamanında içgözlenebilen dizelerdir. Bu, yardım komutu ve otomatik dokümantasyon gibi şeyler oluşturmanıza yardımcı olur.

def frobnicate(bar):
    """frobnicate takes a bar and frobnicates it

       >>> bar = Bar()
       >>> bar.is_frobnicated()
       False
       >>> frobnicate(bar)
       >>> bar.is_frobnicated()
       True
    """

Ruby'nin eşdeğeri javadoclara benzer ve içinde değil yöntemin üzerinde bulunur. 1.9'ın Yöntem # source_location örnek kullanımı kullanılarak çalışma zamanında dosyalardan alınabilirler

Python'un birden fazla mirası var

Ruby yapmaz ("bilerek" - Ruby'nin web sitesine bakın, Ruby'de nasıl yapıldığını buradan görebilirsiniz ). Modül kavramını bir tür soyut sınıf olarak yeniden kullanır.

Python'da liste / dikte anlama

Python:

res = [x*x for x in range(1, 10)]

Yakut:

res = (0..9).map { |x| x * x }

Python:

>>> (x*x for x in range(10))
<generator object <genexpr> at 0xb7c1ccd4>
>>> list(_)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Yakut:

p = proc { |x| x * x }
(0..9).map(&p)

Python 2.7+ :

>>> {x:str(y*y) for x,y in {1:2, 3:4}.items()}
{1: '4', 3: '16'}

Yakut:

>> Hash[{1=>2, 3=>4}.map{|x,y| [x,(y*y).to_s]}]
=> {1=>"4", 3=>"16"}

Python'un dekoratörleri var

Dekoratörlere benzer şeyler Ruby'de de oluşturulabilir ve Python'da olduğu kadar gerekli olmadıkları da iddia edilebilir.

Sözdizimi farklılıkları

Ruby, tüm kapsamlarını kapatmak için "son" veya "}" gerektirirken Python yalnızca beyaz boşluk kullanır. Ruby'de yalnızca boşluk girintisine izin verme girişimleri olmuştur http://github.com/michaeledgar/seamless


2
Birden fazla miras ile ilgili olarak, sadece "Ruby yapmaz" demek saçmadır. Ben modülleri / "mixin kalıtım" ile ruby ​​yapamam çoklu miras ile Python yapabileceğiniz bir şey düşünemiyorum. (Bu modüller dahil sadece düz bile tartışılabilir olduğunu çoklu kalıtım.)
Logan CAPALDO

2
Aynı şeyi başka bir şekilde yapabilmeniz, tutmayan bir argüman. Burada her şeyi başka bir şekilde yapabilirsiniz. Modüller sınıf olmadığı için çoklu kalıtım değildir. Ruby modülleriyle Pythons çoklu mirasta nasıl yapıldığına dair kod örneklerine katkıda bulunabilirsiniz.
Lennart Regebro

3
Modüller Sınıf değil, Sınıflar Modüldür. % ruby ​​-e 'p Sınıfı <Modül' doğru
Logan Capaldo

8
-1 Ne yazık ki, bu soru amacını kaçırıyor ve iddia edilen farklılıkların çoğu hiç fark değil ve yanlış bilgi doludur!
önyargı

2
Modül içerir aslında sadece kavram olarak değil, Ruby yorumlayıcı gerçek uygulamada çoklu miras. Bir Ruby modülü dahil edildiğinde, miras zincirine üst sınıflarla aynı şekilde enjekte edilir. Yöntem çözünürlüğü aynıdır. Ruby'de çoklu modül, çoklu kalıtım içerir. Birden fazla miras olarak buna anlamsal olarak “aynı şey değil” olarak itiraz etmek isteyen herkes sadece bilgiçlikçidir. Etki aynı ve kolayca elde edilebiliyorsa, bir şeyin "aynı şey" olmamasının anlamı nedir? Farksız bir ayrım.
Dave Sims

Yanıtlar:


34

Ruby, kodun bir bölümü etrafında temel olarak sözdizimsel şeker olan blok kavramlarına sahiptir ; kapatmalar oluşturmanın ve bunları bloğu kullanabilen veya kullanamayan başka bir yönteme geçirmenin bir yoludur. Bir blok daha sonra bir yieldifade ile çağrılabilir .

Örneğin, eachüzerinde bir yöntemin basit bir tanımı Arrayşöyle olabilir:

class Array
  def each
    for i in self  
      yield(i)     # If a block has been passed, control will be passed here.
    end  
  end  
end  

Sonra bunu şöyle çağırabilirsiniz:

# Add five to each element.
[1, 2, 3, 4].each{ |e| puts e + 5 }
> [6, 7, 8, 9]

Python'un anonim işlevleri / kapanışları / lambdasları vardır, ancak bazı yararlı sözdizimsel şeker eksik olduğu için blokları yoktur. Bununla birlikte, geçici bir şekilde almanın en az bir yolu vardır. Örneğin, buraya bakınız .


6
@Lennart: Örneğinizin yanı sıra korkunç olmaktan başka sözdizimsel olarak da yanlış.

2
@unbeknow: A, doğru. Ama bu baskı yerine bir işlev olsaydı, işe yarardı. Python 3'te bu çalışır: [1,2,3,4] 'de e için [print (e + 5)] Ve korkunçluk söz konusu olduğunda, yukarıdaki yakut kodun korkunç olduğunu düşünüyorum, bu yüzden açıkça öznel ve dolayısıyla bir bu sorunun bir parçası. @John Eşdeğer olduğunu söylemiyorum, örnekten farkın ne olduğu belli değil. @Bastien, hayır, ancak benzer şeyler yapabilmeniz aynı oldukları anlamına gelmez. Buradaki farklılıklar, bunu yapmanın diğer yolları olsa bile listelenmelidir.
Lennart Regebro

22
Ben bir Python Programcısıyım. Ruby bloklarının Python'dan daha kısaca veya daha güzel bir şey yazmanıza nasıl yardımcı olduğunu gösteren bir örnek görmek istiyorum çünkü blokları yok. Örneğiniz şöyle yazılabilir: [1, 2, 3, 4] 'deki i için: print (i + 5). Blokları değil, özlü ve güzel yanı sıra her yakut örneği kullanıyor.
Manuel Ceron

10
@Manuel, procs, 'for-loop' edilemeyen ve bu nedenle enine özel yineleyiciler gerektiren önemsiz olmayan veri yapılarına (ağaçlar, grafikler ...) functors eklemek için kullanışlıdır. Anonim proc olan bloklar, kodlayıcı sürecini önemli ölçüde hızlandıran ve amacı netleştiren bir ifadede functor'ı uygulamanızı (vs. sonra tanımla sonra uygula) sağlar. Örneğin, bir grafik veri yapısı oluşturuyorsanız, bir 'her' yineleyici tanımlayabilir ve sonra onlarca yineleyiciye (sıralama, hepsi ?, herhangi bir ?, grep) anında erişmenizi sağlayacak Enumerable'ı karıştırabilirsiniz. Şimdi bir blok çağırıyorsun ...
önyargı

4
@RommeDeSerieux, çünkü dilde bir isme ihtiyacı var! Dahası, bir işlev değil, bir işlev nesnesidir. Ruby Docs'a bakalım: "Proc nesneleri, bir dizi yerel değişkene bağlı kod bloklarıdır", bu nedenle anonim bir Proc sadece bloktur ve kesinlikle sadece bir işlev değildir!
önyargı

28

Python Örneği

İşlevler Python'daki birinci sınıf değişkenlerdir. Bir işlevi bildirebilir, bir nesne olarak iletebilir ve üzerine yazabilirsiniz:

def func(): print "hello"
def another_func(f): f()
another_func(func)

def func2(): print "goodbye"
func = func2

Bu, modern kodlama dillerinin temel bir özelliğidir. JavaScript ve Lua da bunu yapıyor. Ruby işlevlere bu şekilde davranmaz; bir işlevin adlandırılması işlevi çağırır.

Elbette, bunları Ruby'de yapmanın yolları var, ancak bunlar birinci sınıf operasyonlar değil. Örneğin, bir işlevi değişken olarak işlemek için Proc.new ile bir işlevi sarabilirsiniz - ancak artık bir işlev değildir; "call" yöntemine sahip bir nesne.

Ruby'nin işlevleri birinci sınıf nesneler değil

Ruby işlevleri birinci sınıf nesneler değildir. Fonksiyonlar bir nesnenin etrafından geçebilmelidir; ortaya çıkan nesneye bir işlev gibi davranılamaz. Fonksiyonlar birinci sınıf bir şekilde atanamaz; bunun yerine, konteyner nesnesindeki bir işlevi değiştirmek için çağrılmalıdır.

def func; p "Hello" end
def another_func(f); method(f)[] end
another_func(:func)      # => "Hello"

def func2; print "Goodbye!"
self.class.send(:define_method, :func, method(:func2))
func                     # => "Goodbye!"

method(:func).owner      # => Object
func                     # => "Goodbye!"
self.func                # => "Goodbye!"    

8
Kafan çok karıştı. Birinci sınıf nesneler x = yçağrı ile değil atama ile atanır self.class.send(:define_method, :func, method(:func2)). "Karşı örnek", Ruby'nin işlevlerinin nasıl birinci sınıf olmadığını gösterir. Eğer katılmıyorsanız, kendi cevabınızı göndermekten çekinmeyin; karışıklığımı benimkine yapıştırma.
Glenn Maynard

7
def ... endRuby'de tanımlanan şeyler işlev değildir. Bunlar yöntemlerdir (onları tanımlama şekliniz Kernel). Yöntemler, #methoddaha sonra nesneler olan ( yöntemi kullanarak ) bağlanmamış olabilir . Ruby'nin işlevlere en yakın şey Proc, aynı zamanda nesne olan ve etrafından geçirilebilen veya çağrılabilen örneklerdir. Ayrıca Proc, John Feminella'nın cevabında tartıştığı gibi, bir yönteme tek bir geri çağrı iletmek için özel bir sözdizimi vardır .
rampa

4
@Glenn: Söylediklerinizi anlıyorum, ama Ruby'nin yeniden tanımlayan işlevlerinin - yöntemlerin ayrı bir anlamsal kavram olduğu iddiasıyla tartıştım. Eğer tanım oyununu oynamak istiyorsanız, en zorunlu kod fonksiyonlar değil prosedürlerdir. Zor olmaya çalışmıyorum, sadece tanımların ve kesinliğin önemli olduğuna inanıyorum. Bir manipüle UnboundMethodetmenin bir PITA olabileceğini kabul edeceğim , tho.
rampa

5
@Glenn: Güzellik bakanın gözündedir. Bununla birlikte, yöntemler tanımı yerine getirerek birinci sınıf nesnelerdir (bu durumda Wikipedia tanımına atıfta bulunuyorum). Belki birinci sınıftan başka bir tanımınız var mı? Birinci sınıfa çıkmak için Platin Sık Uçan Kartlara ihtiyaçları var mı?
önyargı

4
@Glenn SO SSS bölümüne "Diğer kişiler eşyalarımı düzenleyebilir mi ?!" - bu bir Topluluk Wiki'si.
önyargı

26

Sonuçta tüm cevaplar bir düzeyde öznel olacak ve şimdiye kadar gönderilen cevaplar, diğer dilde eşit derecede hoş olmayan (benzer değilse) herhangi bir özelliğe işaret edemeyeceğinizi kanıtlıyor. , çünkü her iki dil de çok özlü ve etkileyici.

Python'un sözdizimini seviyorum. Ancak, Ruby'nin gerçek güzelliğini bulmak için sözdiziminden biraz daha derin kazmanız gerekir. Ruby'nin tutarlılığında zen benzeri bir güzellik var. Hiçbir önemsiz örnek bunu tam olarak açıklayamasa da, burada ne demek istediğimi açıklamak için bir tane bulmaya çalışacağım.

Bu dizedeki kelimeleri ters çevirin:

sentence = "backwards is sentence This"

Bunu nasıl yapacağınızı düşündüğünüzde aşağıdakileri yaparsınız:

  1. Cümleyi kelimelere ayır
  2. Kelimeleri tersine çevir
  3. Kelimeleri tekrar bir dizeye yeniden birleştir

Ruby'de bunu yaparsınız:

sentence.split.reverse.join ' '

Tam olarak düşündüğünüz gibi, aynı sırayla, bir yöntem birbiri ardına çağırır.

Python'da daha çok şuna benzer:

" ".join(reversed(sentence.split()))

Anlamak zor değil, ama aynı akışa sahip değil. Özne (cümle) ortaya gömüldü. İşlemler, işlevlerin ve nesne yöntemlerinin bir karışımıdır. Bu önemsiz bir örnektir, ancak Ruby ile gerçekten çalışırken ve anlarken, özellikle önemsiz olmayan görevlerde birçok farklı örnek keşfedilir.


1
Katılıyorum. Ruby yazarken doğal olarak akıyor gibi görünüyor, bu yüzden "zenlike" iyi bir terim.
Tin Man

18

Python'un "hepimiz yetişkiniz" zihniyeti var. Böylece, Ruby'nin Python'da sabitler gibi şeyler olduğunu göreceksiniz (Ruby'nin sabitleri sadece bir uyarı verse de). Python'un düşünce tarzı, bir şeyi sürekli yapmak istiyorsanız, değişken adlarını tüm büyük harflere koymalı ve değiştirmemelisiniz.

Örneğin, Ruby:

>> PI = 3.14
=> 3.14
>> PI += 1
(irb):2: warning: already initialized constant PI
=> 4.14

Python:

>>> PI = 3.14
>>> PI += 1
>>> PI
4.1400000000000006

19
Ha .. bu sadece piton 2. * en az, sen ... ben bunların doğru sabit inanıyoruz yapabilir "Doğru, Yanlış = Yanlış, Doğru" olduğunu hatırlatıyor piton 3.0 ... bu şey o gerektiğini yapmamak.
Tom

11
Şahsen, bu dilde yazılmış tüm kodları tutarlı hale getirdiğinden, dil tarafından uygulanan katı yönergeleri severim. Sizi yönergeleri izlemeye zorlar ve kodunuzu okuyan geliştiriciler bir bakışta ne olduğunu söyleyebilir. Çoğu Python kodlayıcısı aynı genel "stili" kullanırken, Ruby'de mümkün olmayan bazı büyük tutarsızlıklar gördüm.
Sasha Chedygov

8
@bias - Beni neden düşürdüğünden emin değilim. Bu cevap bir şeyler yapmanın python tarzını kabul etmiyor ya da katılmıyor. Bu sadece bir gerçek ifadesi.
Jason Baker

13
@ Jason "burada hepimiz yetişkiniz" gerçeğinin bir ifadesi mi? Bir özelliğin etrafına sarılan bir görüş, dolayısıyla aşağı oylama demek istiyorum.
önyargı

7
@bias - "Burada hepimiz yetişkiniz" demek hafif bir şey değildi. En iyi burada açıklandığına inandığım gayri resmi bir Python sloganı: mail.python.org/pipermail/tutor/2003-October/025932.html
Evan Porter

18

Python'daki bir modülden yalnızca belirli işlevleri alabilirsiniz. Ruby'de yöntemlerin tamamını alırsınız. Onları Ruby'de "ithalatı" yapabilirsiniz, ama hepsi bununla ilgili değildir.

DÜZENLE:

bu Ruby modülünü alalım:


module Whatever
  def method1
  end

  def method2
  end
end

kodunuza eklerseniz:


include Whatever

Her iki görürsünüz method1 ve method2 senin ad eklendi. Yalnızca yöntem1'i içe aktaramazsınız . İkisini de içe aktarırsınız veya hiç içe aktarmazsınız. Python'da yalnızca seçtiğiniz yöntemleri içe aktarabilirsiniz. Bu bir isme sahip olsaydı, belki seçici ithal denir?


2
Ah, doğru! Python ad alanlarını sever. Ruby'de durum böyle değil mi? import bla; bla.foo()Ruby'de değil misin?
Lennart Regebro

2
İçindeki tüm işlevleri değil, yalnızca a işlevini içe aktarabilirsiniz. Örneğin, statik olmayan 3 işlev bildiren bir Ruby modülü eklerseniz bunların tümünü ad alanınıza dahil edersiniz. Python'da modül içe aktarmadan * yazmanız gerekir.
Geo

6
Bu çok fazla ad alanı dağınıklığına yol açmıyor mu?
Lennart Regebro

1
Bence öyle. Ruby modüllerinden nefret ediyorum.
Geo

8
Ruby'nin aslında python ile aynı anlamda bir modül sistemi yok. gerektirir temelde pişmiş dupilicate dahil etmek için bazı kontroller ile metin içerme olarak çalışır. (ab) modülleri ad alanları olarak kullanabilirsiniz, ancak moduleaslında biraz yanlış isim. Modüller temelde sınıflar new, allocateyöntemler. En iyi, kütüphaneleri bölümlere ayırma mekanizması olarak değil, kodları sınıflar arasında / nesne bazında paylaşmanın ya da programlar arasında paylaşmanın bir yolu olarak çalışırlar.
Logan Capaldo

16

Ruby'nin web sitesinden :

Benzerlikler Python'da olduğu gibi, Ruby'de ...

  • Etkileşimli bir istem (irb denir) var.
  • Dokümanları komut satırında okuyabilirsiniz (pydoc yerine ri komutuyla).
  • Özel satır sonlandırıcıları yoktur (normal satırsonu hariç).
  • Dize değişmez değerleri Python'un üç tırnaklı dizeleri gibi birden çok satıra yayılabilir.
  • Parantezler listeler içindir ve parantezler dikteler içindir (Ruby'de "karma" olarak adlandırılır).
  • Diziler aynı şekilde çalışır (onları eklemek uzun bir dizi yapar, ancak bunları böyle oluşturmak a3 = [ a1, a2 ]size bir dizi dizisi verir).
  • Nesneler güçlü ve dinamik olarak yazılmıştır.
  • Her şey bir nesnedir ve değişkenler sadece nesnelere referanstır.
  • Anahtar kelimeler biraz farklı olsa da, istisnalar aynı şekilde çalışır.
  • Gömülü doktor araçlarınız var (Ruby'ye rdoc denir).

Python'dan farklı, Ruby'de ...

  • Dizeler değiştirilebilir.
  • Sabitler yapabilirsiniz (değerini değiştirmek istemediğiniz değişkenler).
  • Bazı zorlanmış vaka kuralları vardır (örneğin, sınıf adları büyük harfle başlar, değişkenler küçük harfle başlar).
  • Sadece bir çeşit liste kapsayıcısı (Array) vardır ve değiştirilebilir.
  • Çift tırnaklı dizeler, kaçış dizilerine (\ t gibi) ve özel bir “ifade değiştirme” sözdizimine izin verir (bu, Ruby ifadelerinin sonuçlarını "+" dizeleri "+" birlikte "eklemenize gerek kalmadan doğrudan diğer dizelere eklemenizi sağlar) . Tek tırnaklı dizeler Python'un r "ham dizeleri" gibidir.
  • “Yeni stil” ve “eski stil” dersleri yoktur. Sadece bir tür.
  • Özelliklere asla doğrudan erişemezsiniz. Ruby ile, tüm yöntem çağrıları.
  • Yöntem çağrıları için parantezler genellikle isteğe bağlıdır.
  • Python yerine erişim sağlamak için herkese açık, özel ve korumalı _voluntary_ underscore __convention__.
  • Çoklu kalıtım yerine “karması” kullanılır.
  • Yerleşik sınıfların yöntemlerini ekleyebilir veya değiştirebilirsiniz. Her iki dil de herhangi bir noktada sınıfları açmanıza ve değiştirmenize izin verir, ancak Python yerleşiklerin değiştirilmesini önler - Ruby yapmaz.
  • Doğru ve Yanlış yerine doğru ve yanlış var (ve Hiçbiri yerine sıfır).
  • Gerçek için test edildiğinde, sadece yanlış ve sıfır yanlış değeri değerlendirir. Diğer her şey doğrudur (0, 0,0, "" ve [] dahil).
  • Elif yerine elif.
  • İçe aktarma yerine zorunludur. Aksi halde, kullanım aynıdır.
  • Dokümanların oluşturulması için, şeylerin üzerindeki satır (lar) üzerindeki olağan tarzdaki yorumlar (altındaki dokümanlar yerine) kullanılır.
  • Hatırlamanız gereken daha çok şey olmasına rağmen, hızlı bir şekilde öğrenebileceğiniz birkaç kısayol vardır. Ruby'yi eğlenceli ve üretken yapma eğilimindedirler.

2
"İthalat yerine zorunludur. Aksi halde kullanım aynıdır." Tamamen yanlış görünüyor.
Glenjamin

Ruby'de insanların nadiren kullandığı Setler de var, ancak yerleşikler. Yani şunu söyleyebilirim, stuff_in_backpack = Set.new; stuff_in_backpack << "bilgisayar"; stuff_in_backpack << "ayakkabılar"; # ve set siparişi garanti etmeden tüm değerleri tutacaktır.
zachaysan

12

Ruby'nin Python üzerinde sahip olduğu, komut dosyası dil yetenekleridir. Bu bağlamdaki komut dosyası dili, kabuk komut dosyalarında "tutkal kodu" ve genel metin kullanımı için kullanılması anlamına gelir.

Bunlar çoğunlukla Perl ile paylaşılıyor. Birinci sınıf yerleşik normal ifadeler, $ -Değişkenler, Perl (-a, -e) gibi kullanışlı komut satırı seçenekleri vb.

Kısa ve epoksif sözdizimi ile birlikte bu tür görevler için mükemmeldir.

Bana göre Python, öğrenmesi çok kolay ve temiz bir sözdizimine sahip, dinamik olarak yazılmış bir iş dilidir. Ruby kadar güzel değil ama temiz. Python'un Ruby üzerinde bana sahip olduğu şey, diğer kütüphaneler için çok sayıda ciltleme. Qt ve diğer GUI kütüphanelerine bağlamalar, birçok oyun destek kütüphaneleri ve ve. Ruby'nin çok daha azı var. Veritabanlarına çok kullanılan bağlamalar kaliteli olsa da, aynı kütüphanede bir Ruby bağlaması olsa bile, niş kütüphanelerin Python'da daha iyi desteklenmesini buldum.

Yani, her iki dilin de kullanımı olduğunu söyleyebilirim ve hangisinin kullanılacağını tanımlayan görevdir. Her ikisi de öğrenmesi kolay. Onları yan yana kullanıyorum. Komut dosyası oluşturma için Ruby ve bağımsız uygulamalar için Python.


1
Henüz Ruby bilmeyen bir kişinin sorusu: "$ -Variables" ile ne demek istiyorsun? Küresel değişkenleri mi kastediyorsunuz? Eğer öyleyse, Python'da, sınıf veya fonksiyonun dışındaki bir modülde tanımlanan bir değişken globaldir. Değilse - ayrım nedir?
Anon

1
Anon: Eğer kodun herhangi bir yerinde bir $ değişkeni bildirirseniz, önek nedeniyle globaldir. Bu nedenle, nerede tanımlandığı önemli değildir, her zaman küreseldir ve her zaman böyle bilinir.
Robert K

8
Tam olarak değil, aslında $ _, $ 1 vb. Gibi önceden tanımlanmış değişkenler demek istedim. $ _ en son okunan satırdır. $ 1, $ 2 vb. Son eşleşmeden gelen normal ifade eşleşmeleridir. Tam bir liste için buraya bakın: zenspider.com/Languages/Ruby/QuickRef.html#17 Temel olarak kompakt komut dosyaları için bir hack'tir . Tüm bilgileri API çağrıları yoluyla da alabilirsiniz, ancak $ değişkenlerini kullanarak daha da kısadır. Bu tür değişkenler sadece Python'un tarzına uymuyor, kasıtlı olarak onları dışarıda bıraktılar.
haffax

Zenspider bağlantısı için teşekkürler - Ruby için hızlı (öğretici olmayan) bir his için böyle bir şey arıyordum.
Anon

12

"Ruby'de X ve Python yok, Python'da Y ve Ruby yok" diye düşünmüyorum. Pek çok ortak yeteneğe sahip, oldukça benzer dillerdir.

Büyük ölçüde, fark dilin zarif ve okunabilir kıldığı şeydir. Getirdiğiniz bir örneği kullanmak için, her ikisinin de teorik olarak lambdaları vardır, ancak Python programcıları bunlardan kaçınma eğilimindedir ve bunları kullanarak yapılan yapılar Ruby'deki kadar okunabilir veya deyimsel görünmez. Yani Python, iyi bir programcı aslında sırf problem o Ruby olduğundan daha çözme için farklı bir yol almaya isteyecektir olduğunu bunu yapmak için iyi bir yol.


5
Lambdaların sınırlı bir kapsamı olduğunu ve birçok durumda yararlı olmadığını kabul ediyorum. Ancak, Python programcılarının veba gibi onlardan kaçındığını söylemenin adil olduğunu düşünmüyorum.
Jason Baker

1
Lambdaların Python ile sıklıkla kullanıldığını kabul ediyorum - harita, filtre, azaltma gibi. En büyük fark, Python lambdaların ifadelerle sınırlı olduğu görülürken, Ruby blokları çok satırlı olabilir ve ifadeler içerebilir. Ruby hakkında okuduğumdan genel izlenimim, bu özelliğin özellikle Rubyistleri DSL yaklaşımına yöneltmesi, Pythonista'ların ise API'ları yaratma olasılığı daha yüksek. Ruby hakkındaki bilgilerim hala çok yüzeysel.
Anon

2
@Lennart: Ruby'de çok satırlı bloklar her zaman kullanılır - aslında idiomatik Python kodunda kullanılan lambdaları gördüğümden daha sık. Yaygın bir örnek için bkz. İnfo.michael-simons.eu/2007/08/06/rails-respond_to-method .
Chuck

1
@Lennart: Hayır, verim kullanmaz. (Ruby'nin verimi zaten Python'unkinden tamamen farklıdır - bir jeneratör döndürmez.) Yazmak anlamlı olmaz for format in respond_to(). respond_toYöntem anlamlı bir şey dönmez - bu sadece şimdiki HTTP isteğine yanıt verir. doİçinde respond_to dobir blok başlangıcıdır. Bu blokta, formatbir HTTP isteğine yanıt vermek için çok temel bir DSL uygulayan geçici bir nesneyle ( bu örnekte etiketlenmiş ) konuşuyoruz .
Chuck

3
Bir jeneratöre 'Sayılabilir' karıştırabilir ve anında 30 yeni ve harika yineleyici alabilir misiniz? Blokların / Proc'ların neden mükemmel olduğunu anlamadan önce dile bakmanız gerekir.
önyargı

12

Orijinal sorunun bir çeşidini önermek istiyorum, "Ruby'de Python'un sahip olmadığı ve tam tersi?" hayal kırıklığı yaratan yanıtı, "Peki, Intercal'da yapılamayan Ruby veya Python ile ne yapabilirsiniz?" Bu seviyede bir şey yok, çünkü Python ve Ruby, Turing yaklaşımı olduğu tahtında oturan engin kraliyet ailesinin bir parçası.

Peki ya bu:

Ruby'de böyle bir güzellik ve iyi mühendislikle yapılamayan Python'da zarif ve iyi ne yapılabilir?

Bu sadece özellik karşılaştırmasından çok daha ilginç olabilir.


en iyi yorum. hala benim +1
nawfal

11

Python, liste birleşimleri ve jeneratörler için açık ve yerleşik bir sözdizimine sahipken Ruby'de harita ve kod bloklarını kullanırsınız.

Karşılaştırmak

list = [ x*x for x in range(1, 10) ]

için

res = (1..10).map{ |x| x*x }

liste kavrayışları nasıl basit bir Python değildir ? Python'da da bir harita fonksiyonu var.
SilentGhost

Ancak Ruby
Dario'da

Python: res = harita (lambda x: x * x, aralık (1,10))
GogaRieger

Python:res=map(2 .__rpow__, range(1,10))
John La Rooy

11

"Büyük harfle başlayan değişkenler sabit olur ve değiştirilemez"

Yanlış. Yapabilirler.

Sadece yaparsanız bir uyarı alırsınız.


2
Bir dil size bir işlem için uyarı verirse, bence bu işlemi "mümkün değil" olarak çok iyi düşünebilirsiniz. Başka bir şey delilik.
porgarmingduod

11

Biraz daha altyapı tarafında:

  • Python, C ++ ile ( Boost.Python , SIP ve Py ++ gibi şeyler) Ruby'den daha iyi bir entegrasyona sahiptir , burada seçenekler doğrudan Ruby yorumlayıcı API'sına (Python ile de yapabilirsiniz) tabi ki, ancak her iki durumda da düşük seviyeli, sıkıcı ve hataya eğilimli) veya SWIG kullanın (bu, çalışırken ve birçok dili desteklemek istiyorsanız kesinlikle harika, Boost kadar güzel değil. özellikle C ++ 'ı bağlamak istiyorsunuz).

  • Python'un bir dizi web uygulama ortamı vardır (Django, Pylons / Turbogears, web.py, muhtemelen en az yarım düzine diğerleri), Ruby (etkili) ise bir tane vardır: Raylar. (Diğer Ruby web çerçeveleri mevcut, ancak görünüşe göre Rails'e karşı çok çekiş yapmakta zorlanıyorlar). Bu yön iyi mi kötü mü? Söylemesi zor ve muhtemelen oldukça öznel; Python durumunun daha iyi ve Ruby durumunun daha iyi olduğu iddialarını kolayca hayal edebiliyorum.

  • Kültürel olarak, Python ve Ruby toplulukları biraz farklı görünüyor, ancak Ruby topluluğuyla etkileşimde o kadar fazla deneyime sahip olmadığım için bunu ima edebilirim. Bunu çoğunlukla her ikisiyle de çok fazla deneyimi olan birinin bu ifadeyi güçlendirebileceği (veya reddedebileceği) umuduyla ekliyorum.


7
İkinci noktanız en iyi şekilde yanlış bilgilendirilmiştir. Rack ve Sinatra'ya bakmalısın
Max Ogden

6
Açıkça diğer Rails yığınlarının bulunduğunu; Sadece kimsenin onları kullandığını sanmıyorum. Sinatra ve Rack'i kontrol etmek bu izlenimi tam olarak değiştirmedi. Gerçekten, Sinatra (toplam 94 SO sorusu) veya Kamp (toplam 2 SO sorusu) veya başkalarının gerçekten gerçek bir kullanıcı tabanına / topluluğa sahip olduğunu düşünüyor musunuz? Anlayabildiğim kadarıyla, çoğu gerçek hayat kullanıcılarına bile sahip değil. Django (4K +) veya Rails (7K +) veya hatta bu konuda web.py ile karşılaştırın.
Jack Lloyd

1
Sinatra aslında DSL'si nedeniyle farklı, hafif işler için oldukça popülerdir. Sadece daha az kullanılır çünkü Rail'in MVC'si daha fazlasını sağlar. Rails aslında Rack üzerine inşa edilmiştir - Phusion Passenger'ı mümkün kılan da budur.
alternatif

11

Utanmadan yapıştırılan / kopyalama: Alex Martelli üzerine cevap " Ne Yakut Python göre yaklaşık iyidir " den iplik comp.lang.python posta listesine.

18 Ağu 2003, 10:50, Erik Max Francis şunu yazdı:

"Brandon J. Van Every" _unu yazd 1:

Ruby hakkında Python'dan daha iyi ne olabilir? Eminim bir şey vardır. Bu ne?

Python insanlarından ziyade Ruby insanlarına bunu sormak daha anlamlı olmaz mıydı?

Kişinin amaçlarına bağlı olarak olabilir veya olmayabilir - örneğin, amaçlarında Python topluluğunun "sosyolojik bir araştırması" varsa, o topluluğa soru sormanın, başka bir yere koymaktan daha fazla bilgiyi ifşa etmesi muhtemeldir. :-).

Şahsen, Dave Thomas'ın son OSCON'daki bir günlük Ruby eğitimini takip etme fırsatını memnuniyetle aldım. Sözdizimi farklılıklarının ince bir kaplamasının altında, Ruby ve Python'u inanılmaz derecede benzer buluyorum - hemen hemen herhangi bir dil kümesi arasında minimum yayılma ağacını hesaplasaydım, Python ve Ruby'nin birleşecek ilk iki yaprak olacağından eminim bir ara düğüm :-).

Tabii, Ruby'de her bloğun sonuna aptalca "son" yazarak (sadece rahatsız edici olmaktan ziyade) yorgunum - ama sonra Python'un gerektirdiği eşit derecede aptalca ':' yazmaktan kaçınıyorum başlangıç her bloğun, yani :-) neredeyse bir yıkama olduğunu. '@Foo' ve 'self.foo' ya da Ruby vs Python'daki davanın daha yüksek önemi gibi diğer sözdizimi farklılıkları gerçekten benim için önemsiz.

Diğerleri şüphesiz programlama dillerini seçtikleri bu tür sorunlara dayandırıyorlar ve en sıcak tartışmaları üretiyorlar - ama bana göre bu Parkinson Yasası'nın sadece bir örneğidir (bir konudaki tartışma miktarı konuyla ters orantılıdır) gerçek önem).

Edit (AM 6/19/2010 11:45): Bu aynı zamanda "bikeshed boyama" (veya kısaca, "bikeshedding") olarak da bilinir - referans yine "tartışmalar yapan Northcote Parkinson'a" "önemsiz konularda sıcak tartışmalar" tipik bir örneği olarak bikeshed boyamak için hangi renk. (sonu Değiştir).

Önemli bulduğum bir sözdizimi farkı ve Python'un lehine - ama diğer insanlar şüphesiz tam tersini düşünecek - "parametre almayan bir işlevi nasıl çağırıyorsunuz". Python'da (C'deki gibi), bir işlevi çağırmak için her zaman "çağrı operatörü" nü uygularsınız - aradığınız nesnenin hemen sonundaki parantezleri (bu sondaki parantezlerin içinde çağrıda ilettiğiniz argümanlar gider - eğer hiçbir argüman geçirmiyorsanız, parantezler boştur). Bu sadece herhangi birinden bahseder herhangi bir bağlamda, özel durumlar, istisnalar, ad-hoc kurallar ve benzerleri olmadan, sadece nesneye referans olarak kullanılan nesne. Ruby'de (Pascal'da olduğu gibi), argümanlarla bir işlevi çağırmak için argümanları iletirsiniz (normalde parantez içinde, her zaman böyle değildir) - AMA işlev hiçbir argüman almazsa, işlevden dolaylı olarak bahsettikten sonra onu çağırır. Bu, birçok insanın beklentilerini karşılayabilir (en azından şüphesiz, daha önce programlama deneyimi Pascal ile olan veya Visual Basic gibi benzer "örtük çağrı" olan diğer diller) - ama bana göre sadece bir nesneden bahsetmek EITHER, nesnenin türüne bağlı olarak nesneye bir başvuru, VEYA nesneye bir çağrı anlamına gelebilir - ve bu durumlarda ' t sadece söz ederek nesneye bir referans almak açık "bana bir referans vermek, onu arama YAPMAYIN!" aksi halde gerekli olmayan operatörler. Bunun işlevlerin (veya yöntemlerin veya diğer çağrılabilir nesnelerin) "birinci sınıfını" ve nesnelerin sorunsuz bir şekilde değiştirilmesi olasılığını etkilediğini hissediyorum. Bu nedenle, benim için, bu özel sözdizimi farkı Ruby'ye karşı ciddi bir kara leke - ama onlarla daha sert bir şekilde katılmıyorum olsa bile, başkalarının neden başka bir şey olacağını anlıyorum :-). fonksiyonların (veya yöntemlerin veya diğer çağrılabilir nesnelerin) ve nesnelerin düzgün bir şekilde değiştirilmesi olasılığı. Bu nedenle, benim için, bu özel sözdizimi farkı Ruby'ye karşı ciddi bir kara leke - ama onlarla daha sert bir şekilde katılmıyorum olsa bile, başkalarının neden başka bir şey olacağını anlıyorum :-). fonksiyonların (veya yöntemlerin veya diğer çağrılabilir nesnelerin) ve nesnelerin düzgün bir şekilde değiştirilmesi olasılığı. Bu nedenle, benim için, bu özel sözdizimi farkı Ruby'ye karşı ciddi bir kara leke - ama onlarla daha sert bir şekilde katılmıyorum olsa bile, başkalarının neden başka bir şey olacağını anlıyorum :-).

Sözdiziminin altında, temel anlambilimde bazı önemli farklılıklara giriyoruz - örneğin, Ruby'deki dizeler değiştirilebilir nesnelerdir (C ++ gibi), Python'da değişebilir değiller (Java'da olduğu gibi veya C # 'a inanıyorum). Yine, öncelikle aşina olduklarına göre karar verenler, bunun Ruby için bir artı olduğunu düşünebilirler (elbette Java veya C # 'a aşina olmadıkları sürece :-). Ben, değişmez dizeleri mükemmel bir fikir olduğunu düşünüyorum (ve Java, bağımsız olarak bence, zaten Python olan bu fikri yeniden icat şaşırttı), ama ben de bir "değişebilir dize tampon" türü de sakıncası olmaz (ve ideal olarak Java'nın kendi "dize arabelleklerinden" daha iyi kullanım kolaylığı olan); ve bu yargıyı aşinalık nedeniyle vermiyorum - Java'yı incelemeden önce, tüm veriler değişmez, bildiğim tüm dillerin değişebilir dizeleri vardı - yine de Java'da değişmez dize fikrini ilk gördüğümde (Python'u öğrenmeden önce iyi öğrendim), hemen bana mükemmel geldi, çok iyi uyuyordu daha üst düzey bir programlama dilinin referans semantiği (makineye daha yakın ve C gibi uygulamalardan daha uzak dillerle en iyi uyan değer semantiklerinin aksine) birinci sınıf, yerleşik (ve güzel önemli) veri türü.

Ruby'nin temel anlambilimde bazı avantajları vardır - örneğin, Python'un "listeler ile tuples" un kaldırılması son derece ince bir ayrımdır. Ama çoğunlukla puan (ben tutmak gibi, basitlik ile büyük bir artı ve ince, akıllı ayrımlar dikkate değer bir eksi) Ruby karşıdır (örneğin, hem kapalı hem de yarı açık aralıklarla, a..b ve a gösterimleri ile .. .b [kimse hangisinin hangisinin açık olduğunu iddia etmek ister ? -)] aptalca - IMHO, tabii ki!). Yine, bir dilin özünde bir MINUS yerine bir PLUS, benzer ama kurnazca farklı şeylere sahip olmayı düşünen insanlar, elbette bunları "saydığım" yoldan sayıyor :-).

İki dilin çok iyi olduğunu düşünmek için yapılan bu karşılaştırmalarla yanıltılmayın. farklı, dikkat et. Onlar değil. Ama "capelli d'angelo" yu "spaghettini" ile karşılaştırmam istenirse, bu iki çeşit makarnanın hemen hemen herkes tarafından ayırt edilemez olduğunu ve hazırlamak isteyebileceğiniz herhangi bir yemeğin yerine geçebileceğini belirledikten sonra, kaçınılmaz olarak uzunlukların ve çapların fark edilemez bir şekilde nasıl farklılaştığı, ipliklerin uçlarının bir durumda ve diğerinde değil, nasıl sivrildiklerinin mikroskobik incelemesine geçmek ve kişisel olarak neden capelli d'yi tercih ettiğimi açıklamak için herhangi bir et suyunda makarna olarak angelo, ama makarna gibi makarnalar gibi uzun ince makarna formları (zeytinyağı, kıyılmış sarımsak, kıyılmış kırmızı biber ve ince öğütülmüş hamsi için uygun soslar ile gitmek istiyorum, örneğin - ancak sarımsak ve biberleri kıymak yerine dilimlediyseniz, spagettininin daha ince bir şekilde evrimleşmesi yerine spagetti'nin daha sağlam gövdesini seçmelisiniz ve yerine taze bahar fesleğen eklemeniz tavsiye edilir. [ hatta sapkınım! - hafif nane ...] yaprakları - yemeğe hizmet etmeden önceki son anda). Üzgünüm, yurtdışına seyahat ettiğimi ve bir süredir makarna yemediğimi gösteriyor. Ama benzetme hala oldukça iyi! -) - hafif nane ...] yaprakları - yemeğe hizmet etmeden önceki son anda). Üzgünüm, yurtdışına seyahat ettiğimi ve bir süredir makarna yemediğimi gösteriyor. Ama benzetme hala oldukça iyi! -) - hafif nane ...] yaprakları - yemeğe hizmet etmeden önceki son anda). Üzgünüm, yurtdışına seyahat ettiğimi ve bir süredir makarna yemediğimi gösteriyor. Ama benzetme hala oldukça iyi! -)

Python ve Ruby'ye geri döndüğümüzde iki büyük boyuta (dilde uygun olarak - kütüphaneleri terk etmek ve araçlar ve ortamlar, her dilin nasıl gömüleceği / genişletileceği vb.) şimdilik - her dilin tüm UYGULAMALARI için geçerli olmazlar, örneğin, Jython vs Klasik Python, Python dilinin iki uygulamasıdır!):

  1. Ruby'nin yineleyicileri ve kod blokları ile Python'un yineleyicileri ve jeneratörleri;

  2. Ruby'nin TOTAL, dizginsiz "dinamikliği",
    tüm yerleşik sınıflar dahil olmak üzere mevcut herhangi bir sınıfı "yeniden açma" ve çalışma zamanında davranışını değiştirme - Python'un varolan davranışını asla değiştirmeyen geniş ama sınırlı dinamikliği yerleşik sınıflar ve örnekleri.

Şahsen, 1'i bir yıkama olarak görüyorum (farklılıklar o kadar derin ki, insanların ya yaklaşımdan nefret etmesini ve diğerini geri çevirmesini kolayca görebiliyordum, ancak BENİM kişisel ölçeklerimde artıları ve eksileri neredeyse eşit olarak görebiliyorum); ve 2 önemli bir konu - Ruby'yi "tinkering" için çok daha uygun hale getiren bir sorun, AMA Python büyük üretim uygulamalarında kullanım için eşit derecede daha uygun. Bir bakıma komik, çünkü her iki dil de diğerlerinden çok daha dinamik, sonuçta POV'umdan aralarındaki anahtar fark buna bağlı olmalı - Ruby bu konuda "on bire gidiyor" (referans "Tabii ki" Spinal Tap "için). Ruby'de,Bunu yapabilirim ! Yani, dahili bir dize sınıfını dinamik olarak değiştirebilirim, böylece a == b yazdır "eşit! \ N" başka yazdır "farklı! \ N" bitiş WILL print "olursa, a =" Hello World "b =" merhaba dünya " eşit". Python'da bunu yapmanın bir yolu yok. Metaprogramlama, deneysel çerçevelerin uygulanması ve benzeri amaçlar için, Ruby'nin bu şaşırtıcı dinamik yeteneği son derece çekici. AMA - geniş çaplı uygulamalardan bahsediyorsak, birçok insan tarafından geliştirilmiş ve farklı kaynaklardan her türlü kütüphane de dahil olmak üzere daha da fazlası tarafından korunuyor ve müşteri sitelerinde üretime girmeye ihtiyaç duyuyorsak ... Eh, İSTEMİYORUM çok dinamik bir dil, çok teşekkür ederim. Bazı kütüphanelerin farkında olmadan, bu dizelere farklı olan diğer ilgisiz olanları kırma fikrinden nefret ediyorum - bu, LOOK'un ayrı olması ve ayrı olması gereken kod parçaları arasında derin ve derinden gizlenmiş bir "kanal" türü büyük ölçekli programlama. Herhangi bir modülün diğer "gizli" davranışlarını etkilemesine izin vererek, yerleşik türlerin anlambilimini değiştirme yeteneği, üretim uygulaması programlama için sadece bir KÖTÜ fikirdir,

Ruby'yi bu kadar büyük bir uygulama için kullanmak zorunda kalsaydım, kodlama stili kısıtlamalarına, birçok teste (HERHANGİ bir değişiklik olduğunda yeniden çalıştırılmak için - tamamen ilgisiz olması gerekse ...) ve benzerlerine güvenmeye çalışırdım, bu dil özelliğinin kullanılmasını yasaklamak için. Ama ilk etapta bu özelliğe sahip OLMAMAK daha iyi, bence - Python'un belirli bir sayıda yerleşik "çivilenmiş" olabilmesi durumunda uygulama programlaması için daha iyi bir dil olacağı gibi, , örneğin, len ("ciao") 4'tür (birinin yerleşik modülde 'len' adının bağlanmasını değiştirip değiştirmediği konusunda bilinçaltıyla endişelenmek yerine ...). Umarım sonunda Python yerleşiklerini "çivi" yapar.

Ancak sorun önemsizdir, çünkü yerleşik isimleri yeniden hatırlamak Python'da oldukça yaygın değildir ve nadir bir uygulamadır. Ruby'de, bana büyük gibi geliyor - tıpkı diğer dillerin (örneğin Dylan gibi) çok güçlü makro tesislerinin kendi düşüncemde benzer riskler sunduğu gibi (Python'un asla bu kadar güçlü bir makro sistemi almamasını umuyorum, hayır "insanların dilin içine yerleştirilmiş kendi alan adına özgü küçük dillerini tanımlamasına izin verme" cazibesi - IMHO, Python'un uygulama programlama için harika yararlılığını bozacak ve her programcının kalbinde gizlenir ...).

Alex


9

Bazıları:

http://www.ruby-lang.org/en/documentation/ruby-from-other-languages/to-ruby-from-python/

(Bu sayfayı güncelledikten sonra herhangi bir şeyi yanlış yorumladıysam veya bunlardan herhangi biri Ruby tarafında değiştiyse, birisi düzenlemekten çekinmeyin ...)

Dizeler Ruby'de değiştirilebilir, Python'da değil (yeni dizelerin "değişiklikler" ile oluşturulduğu).

Ruby'nin bazı zorunlu dava sözleşmeleri var, Python yok.

Python'un hem listeleri hem de tuplleri vardır (değişmez listeler). Ruby, Python listelerine karşılık gelen dizilere sahiptir, ancak bunların değişmez bir varyantı yoktur.

Python'da, nesne niteliklerine doğrudan erişebilirsiniz. Ruby'de, her zaman yöntemlerle.

Ruby'de, yöntem çağrıları için parantezler genellikle isteğe bağlıdır, ancak Python'da değildir.

Ruby, Python'un alt çizgi ve ad yönetimi kullanma sözleşmesi yerine, genel, özel ve erişimi zorlamak için korunmaktadır.

Python'un birden fazla mirası vardır. Ruby'de "mixins" var.

Ve çok alakalı başka bir bağlantı:

http://c2.com/cgi/wiki?PythonVsRuby

Özellikle hangi, bağlantılar Alex Martelli başka iyi biri de SO üzerinde burada büyük bir sürü şey gönderme oldu:

http://groups.google.com/group/comp.lang.python/msg/028422d707512283


1
Ruby'de değişmez bir şeye değiştirmek için dizinizi dondurabilirsiniz
user163365

Alex Martelli :) ile mükemmel gönderi
Skilldrick

8

Bundan emin değilim, bu yüzden önce bir cevap olarak ekliyorum.

Python ilişkisiz yöntemleri işlev olarak görür

Bu, bir yöntemi gibi theobject.themethod()veya tarafından çağırabileceğiniz anlamına gelir TheClass.themethod(anobject).

Düzenleme: Yöntemler ve işlevler arasındaki fark Python'da küçük ve Python 3'te var olmayan olmasına rağmen, Ruby'de işlevler olmadığı için Ruby'de de yoktur. İşlevleri tanımladığınızda, aslında Object üzerindeki yöntemleri tanımlarsınız.

Ama yine de bir sınıfın yöntemini alıp bir işlev olarak adlandıramazsınız, onu çağırmak istediğiniz nesneye yeniden bağlamanız gerekir, ki bu çok daha engellidir.


Ruby'nin hiçbir işlevi yok. Yani TheClass.instance_method(:themethod).bind(anobject).call, eşdeğer yakut olurdu.
Logan Capaldo

Ah. Açık bir sınıfta olmayan bir işlevi tanımladığınızda bir tür sihirli ana sınıf var mı?
Lennart Regebro

Evet, en üst düzeyde tanımlanan yöntemler Object.
Logan Capaldo

1
FWIW, Python'da fonksiyonların ve yöntemlerin aslında aynı tipte olduğu ve farklı davranışlarının tanımlayıcılardan geldiği anlaşılıyor : users.rcn.com/python/download/… .
Bastien Léonard

1
Ancak bir nesneye bağlarsanız, o zaman bağlanmamıştır. Duh. :-) Ve Python'da da aynı şey. Sadece Ruby'nin aslında işlevleri yok. Bu da ifademin doğru olduğu anlamına geliyor. Bağlı olmayan bir yöntemi Python'da bir işlevmiş gibi çağırabilirsiniz. Ve bu aslında yararlıdır, bu, örneğin, bazen yararlı olan bir sınıfa sahip olmayan bir nesne üzerinde bir sınıfta tanımlanan bir yöntemi çağırabileceğiniz anlamına gelir.
Lennart Regebro

7

Bir nesne-öznitelik "iletişim" özelleştirmek izin Python tanımlayıcı API bahsetmek istiyorum. Ayrıca, Python'da, __getattribute__yöntemin varsayılan uygulaması yoluyla verilen varsayılanı geçersiz kılarak alternatif bir protokol uygulamakta serbesttir . Yukarıda belirtilenler hakkında daha fazla bilgi vereyim. Açıklayıcılar düzenli ile sınıflar vardır __get__, __set__ve / veya __delete__yöntemler. Tercüman böyle bir şeyle karşılaştığında anObj.anAttraşağıdakiler gerçekleştirilir:

  • __getattribute__yöntemi anObjçağrıldı
  • __getattribute__ sınıf diksiyonundan birAttr nesnesi alır
  • Bu abAttr nesne olup olmadığını kontrol eder __get__, __set__ya da __delete__çağrılabilir nesneleri
  • bağlam (yani, ayarlayıcı varsa ikincisi yerine arayan nesnesi veya sınıfı ve değeri) çağrılabilir nesneye aktarılır
  • sonuç döndürülür.

Belirtildiği gibi, bu varsayılan davranıştır. Biri yeniden uygulayarak protokol değiştirmek için ücretsizdir __getattribute__.

Bu teknik, dekoratörlerden çok daha güçlüdür.


6

Ruby, kullanmaya devam desteği sağlamıştır callcc.

Böylece amb-operatörü gibi harika şeyler uygulayabilirsiniz.


Keşke callcc'i anlamış olsaydım. McCarthy'nin Belirsiz Operatöründen daha fazla sıradan bir uygulama senaryosu verebilir misiniz, onun değerini takdir etmek için? Yani gerçek dünyadan bir şey, o korkak CS şeyleri değil mi ?!
ThomasH

"Funky CS şeyler" gerçek. Öğrenmek için biraz zaman ayırın: intertwingly.net/blog/2005/04/13/Continuations-for-Curmudgeons
Stephen EILERT


5

Python'un öğretileri vardır ve yakut yoktur ... Yoksa yoksa, pitondaki kadar kolay erişilebilir değildir.

Ps. Eğer yanılıyorsam, lütfen bir örnek mi bırakıyorsun Ben oldukça kolay sınıflara maymunbalığı olabilir bir geçici çözüm var ama ben "yerli şekilde" bir özellik docstring istiyorum.


3
doktora bilmiyor, ama RDoc var. Yani evet, kolay erişilebilir değil, ancak% 100 gizli değil.
Omar Qureshi

Ruby doktrin kullanmaz. Dokümantasyonu farklı bir şekilde yapar.
Chuck

1
Ömer: Evet, rdoc'u biliyorum ama afaik, python'un öğretileri kadar "erişilebilir" değiller. Örneğin, ben bir sınıf var ve ben oldukça ağır iş sınıf içinde rdoc belgeleri çıktı istiyorum. Ne yaptım i up2date tutmak ve daha sonra bu bilgi vi ri kendisi almak deneyin ri belgeleri oluşturmak olduğunu. Kesinlikle
python'un öğretileri ile

Docstringler doctest sağlamak için kullanılabilir. Ruby için böyle bir şey var mı?
Lennart Regebro

2
Evet, buna "Ruby Doctest" deniyor. Doctests söz konusu olduğunda, gerçekten önemli olan tek şey, test edilebilir kod snippet'lerini içeren bir yerde okunabilir belgelere sahip olmanızdır - bir doktora ya da yorumda olması fark etmez.
Chuck

5

Ruby, komut satırından girdi dosyaları ('-n' bayrağı) üzerinde satır satır döngüye sahiptir, böylece AWK gibi kullanılabilir. Bu Ruby tek astarlı:

ruby -ne 'END {puts $.}'

AWK tek katlı gibi satırları sayacak:

awk 'END{print NR}'

Ruby bunu, Perl ile sysadminleri bir şeyler yapma şeklini değiştirmek zorunda kalmadan almanın bir yolu olarak alan Perl aracılığıyla alıyor.


1
Python'un komut satırı desteğinin oldukça zayıf olduğunu eklemek istiyorum. Eksik otomatik döngünün yanı sıra, tek bir satıra birkaç ifade koyamaz ve bunu çeviriciye tek dize komut satırı argümanı olarak iletemezsiniz. En azından ben başaramadım.
ThomasH

Tabi ki yapabilirsin. Ama (herhangi bir otehr dilinde olduğu gibi) içine almanız gereken tırnak içine alınacaktır.
Lennart Regebro

Python komut satırında kullanılmaz, çünkü bu şekilde kullanmak istiyorsanız bazı şeyler (sys.stdin gibi) hakkında açık olmanız gerekirpython -c "import sys; print len(list(sys.stdin))"
u0b34a0f6ae

5

Ruby imzalı ve dallıdır, Python yoktur.

Edit : Ve çok önemli bir şey unuttum (sonuçta, önceki sadece biraz alev :-p oldu):

Python, bir JIT derleyicisine ( Psyco ), daha hızlı kod yazmak için daha düşük seviyeli bir dile ( Pyrex ) ve satır içi C ++ kodu ( Weave ) ekleme yeteneğine sahiptir .


Doğru, ama bu sadece sözdizimi.
Lennart Regebro

6
Eğer o yoldan gitmek istiyorsanız: her ikisi de Turing-complete. Diğer her şey sadece sözdizimidir.
Jörg W Mittag

Evet ve bir importtax sözdizimi farkı ;-)
fortran

1
@Foo veya self.foo yazmanız nasıl önemlidir?
Lennart Regebro

1
@ Jörg: Tamam, o zaman "sentaks" dan başka bir şey deyin. Mesele şu ki @foo ve self.foo aynı şeyi yapıyor, aslında Ruby'nin sahip olduğu ve Python'un sahip olmadığı bir işlevsellik değil.
Lennart Regebro

5

Benim python paslı, bu yüzden bunlardan bazıları python olabilir ve ben ilk etapta hatırlamıyorum / asla öğrenmedim, ama burada ilk düşündüğüm birkaç tane var:

Beyaz boşluk

Ruby boşlukları tamamen farklı işler. Yeni başlayanlar için hiçbir şey girintilemeniz gerekmez (yani 4 boşluk veya 1 sekme kullanmanız önemli değildir). Ayrıca akıllı hat devam ettirir, bu nedenle aşağıdakiler geçerlidir:

def foo(bar,
        cow)

Temel olarak, bir operatörle bitirirseniz, neler olduğunu anlar.

Katmalar

Ruby, tam sınıflar yerine örnekleri genişletebilen karışımlara sahiptir:

module Humor
  def tickle
    "hee, hee!"
  end
end
a = "Grouchy"
a.extend Humor
a.tickle    »   "hee, hee!"

Sıralamalar

Bunun jeneratörler ile aynı olup olmadığından emin değilim, ama Ruby 1.9 yakut olarak sayılar gibi,

>> enum = (1..4).to_enum
=> #<Enumerator:0x1344a8>

Referans: http://blog.nuclearsquid.com/writings/ruby-1-9-what-s-new-what-s-changed

"Anahtar Kelime Bağımsız Değişkenleri"

Orada listelenen her iki öğe de Ruby'de desteklenir, ancak bu gibi varsayılan değerleri atlayamazsınız. Ya sırayla gidebilirsiniz

def foo(a, b=2, c=3)
  puts "#{a}, #{b}, #{c}"
end
foo(1,3)   >> 1, 3, 3
foo(1,c=5) >> 1, 5, 3
c          >> 5

C = 5'in aslında çağrı kapsamındaki c değişkenini 5 değerini atar ve b parametresini 5 değerini ayarlar.

veya ikinci sorunu ele alan karmalarla yapabilirsiniz

def foo(a, others)
  others[:b] = 2 unless others.include?(:b)
  others[:c] = 3 unless others.include?(:c)
  puts "#{a}, #{others[:b]}, #{others[:c]}"
end
foo(1,:b=>3) >> 1, 3, 3
foo(1,:c=>5) >> 1, 2, 5

Kaynak: Pragmatik Programcı'nın Ruby Rehberi


İkinci örneğiniz foo (1, c = 5) düşündüğünüzü yapmaz. Ruby'nin adlandırılmış parametreleri yok.
horseyguy

5
Python vardır örtülü satır devam içi parantez (, [ya{
u0b34a0f6ae

5

Hem Ruby hem de Python'da sınıf tanımında kodunuz olabilir. Ancak, Ruby'de sınıfa (benlik) bir referansınız var. Sınıf henüz tanımlanmadığı için Python'da sınıfa referansınız yoktur.

Bir örnek:

class Kaka
  puts self
end

bu durumda kendini sınıf, ve bu kod "Kaka" çıktı. Sınıf adını yazdırmanın veya başka bir şekilde sınıfa Python'daki sınıf tanımı gövdesinden erişmenin bir yolu yoktur.


İlk noktanız için daha fazla ayrıntı (kod gibi) verebilir misiniz?
Loïc Wolff

Örnek kod iyi bir fikir, bu durum önemsiz olsa bile, ekledim.
Lennart Regebro

@SilentGhost: Şu anda gerçekten belirsiz olmayan birini düşünemiyorum. :)
Lennart Regebro

sınıfın içindeki sınıf adına python: class foo (): def init __ (self): print self .__ class .__ name__
txwikinger

1
@txwikinger: evet, ancak sınıfın içinde değil, classifadeyle aynı zamanda yürütülür .
Bastien Léonard

4

Sözdizimi küçük bir şey değildir, nasıl düşündüğümüz üzerinde doğrudan etkisi vardır. Kullandığımız sistemler için oluşturduğumuz kurallar üzerinde de doğrudan bir etkisi vardır. Örnek olarak, matematiksel denklemleri veya cümleleri yazma şeklimiz nedeniyle işlem sırasına sahibiz. Matematiğin standart gösterimi, insanların onu birden fazla şekilde okumasına ve aynı denklem verildiğinde farklı cevaplara ulaşmasına izin verir. Önek veya postfix gösterimi kullansaydık, yalnızca değerlerin hesaplanacağı sıra için kurallara sahip olmaktan ziyade, değiştirilecek sayıların ne olduğunu ayırt etmek için kurallar yaratırdık.

Standart gösterim, bunları hesaplamak için sipariş verirken hangi sayılardan bahsettiğimizi açıkça gösterir. Ön ek ve son düzeltme notasyonu, sayıları belirsiz hale getirirken düz hesaplamanın sırasını belirler. Eğer sözdizimsel boşluktan kaynaklanan zorluklar olmasaydı Python zaten çok satırlı lambdalara sahip olurdu. (Bu tür şeyleri, açık blok sınırlayıcıları eklemeden zorunlu olarak çıkarmak için öneriler mevcuttur.)

Bir koşulun yanlış olması durumunda koşulların yazılmasını daha kolay buluyorum . Günümüzde insanların kullandığı dillerin çoğunun gücü eşitse, her dilin sözdizimi nasıl önemsiz bir şey olarak kabul edilebilir? Bloklar ve kalıtım mekanizmaları vb. Gibi belirli özelliklerden sonra sözdizimi bir dilin en önemli kısmıdır, neredeyse yüzeysel bir şey değildir.

Yüzeysel olan, sözdizimine atfettiğimiz güzelliğin estetik nitelikleridir. Estetiğin bilişimizin nasıl çalıştığıyla hiçbir ilgisi yoktur, sözdizimi yapar.


Bu "yorum", bir yorumda ne olduğuna bakılmaksızın, bir yorumda izin verilen sürenin üç katıdır.
Andrew Grimm

Bu aslında bana bir cevap olarak iyi görünüyor. "Bu bir yorum" bitini düzenledi.
Kertenkele Bill

3

Ruby'nin "yöntem eksik" mekanizmasından bahseden hiçbir şey görmekten şaşırdım. Bu dil özelliğinin gücüne örnek olarak Rails'deki find_by _... yöntemlerine örnekler vereceğim. Tahminimce Python'da benzer bir şey uygulanabilir, ama bildiğim kadarıyla orada değil.


Python, Ruby'nin method_missing ile aynı şeyi yapan get_attribute'a sahiptir.
mipadi

3
Python geliştiricileri, ruby ​​HERHANGİ BİR YERDEN bahsedildiğinde neden bu kadar popo acıyor? Bunun doğru olmadığını inkar edemezsin.
aarona

method_missingbazı durumlarda Python benzeri oluşturulabilir: class M(): def __getattr__(self, n): return lambda: "Missing! " + n; M().hi(). Ancak, küçük farklılıklar vardır ve ben Python içinde deyim şüphe ediyorum :-)

1
@DJTripleThreat: Bunun doğru olduğunu inkar ediyorum.
Lennart Regebro

3

Python ve Ruby arasındaki lambdalardaki bir başka fark, Paul Graham'ın Akümülatör Jeneratörü problemiyle kanıtlanmıştır . Burada yeniden yazdırıldı:

N sayısını alan ve i sayısını alan ve i tarafından artırılan n değerini döndüren bir işlev foo yazın. Not: (a) tamsayı değil sayıdır, (b) artı değil artmış.

Ruby'de bunu yapabilirsiniz:

def foo(n)
  lambda {|i| n += i }
end

Python'da n durumunu tutmak için bir nesne oluşturursunuz:

class foo(object):
    def __init__(self, n):
        self.n = n
    def __call__(self, i):
        self.n += i
        return self.n

Bazı kişiler, biraz daha ayrıntılı olsa bile, açık Python yaklaşımının kavramsal olarak daha açık olmasını tercih edebilir. Başka bir şey için olduğu gibi devleti depolarsınız. Sadece başınızı, çağrılabilir nesneler fikrinin etrafına sarmanız gerekir. Ancak estetik olarak hangi yaklaşımı tercih ettiğine bakılmaksızın, Ruby lambdaların Python'lardan daha güçlü yapılar olduğu konusunda bir saygı gösterir.


3
Python'daki sayıları arttıramazsınız, böylece kısıtlama mantıklı değildir. Python'da rakamlar değişmez. Bunun yerine "artı" olarak değiştirirsek, sınıf gereksizdir. Bu nedenle bu lambda farkı hakkında bir şey göstermez, sayıların nasıl işlediğindeki farktır. Tabii ki değiştirilebilir bir sayı sınıfı oluşturmazsanız. :)
Lennart Regebro

2
Kısıtlama, istenen davranışı açıklığa kavuşturmak için vardır. Sorunun istediği şey: f = foo (10) f (2) >> 12 f (3) >> 15 ... lambda {| i | n + i} şunu verir: f = foo (10) f (2) >> 12 f (3) >> 13 ... Sayılar Ruby'de de değişmez - örneğin 2 + = 1 diyemezsiniz. Ve n + = 1 normal bir Python fonksiyonunda iyidir, ancak lambda değildir. Yani "n" nin ne olduğu, fonksiyon çağrıldığında ve lambda oluştuğunda yaratılmış olması, lambdada (sadece ifadeler yerine) atama yapabilmeniz ve n'nin değerini tutabilmesi birden fazla çağrı üzerinden.
dormsbee

Python'da böyle uzunluklara gitmen gerektiğini sanmıyorum. Fonksiyonlar diğer fonksiyonlar içinde tanımlanabilir. def foo(n): def f(i): return n + i return f.
FMc

2
Yine de aynı değil ve örneğiniz yukarıdaki yorumda Python lambda'ya eşdeğerdir. Ruby sürümü çağrılar arasında durumu koruyan bir lambda oluşturur. Gönderdiğiniz örnek n için bir başlangıç ​​değeri yapılandırmanıza izin verir, ancak foo'nun döndürdüğü işlev her zaman bu başlangıç ​​değerine sahip olur. Ruby sürümü artar. Diyelim ki f = foo (10). Python sürümü: f (1) => 11, f (1) => 11. Ruby sürümü f.call (1) => 11, f.call (1) => 12.
dormsbee

def foo(n): L=[n] def f(i): L[0] += i return L[0] return f. Python3'te nonlocalanahtar kelime kullanabilirsiniz .
jfs

3

python isteğe bağlı argümanlar adlandırdı

def func(a, b=2, c=3):
    print a, b, c

>>> func(1)
1 2 3
>>> func(1, c=4)
1 2 4

AFAIK Ruby yalnızca bağımsız değişkenleri konumlandırmıştır, çünkü işlev bildirimindeki b = 2 her zaman ekleyen bir şeydir.


3
"Ruby yalnızca bağımsız değişkenleri konumlandırmıştır, çünkü işlev bildirimindeki b = 2 her zaman ekleyen bir sevgi" anlamına gelir?
horseyguy

3
Hangi gezegende yaşadığınızı bilmeyin, ancak def my_method(param1, optional = false)Ruby 1.8.6, 1.8.7 ve muhtemelen 1.9'da çalışıyor!
Robert K

5
Kötü Pire ve yorumunu onaylayan insanlar, örneğe yeterince yakından bakmadınız. Aramadaki bparametreyi atlayabilir funcve yine de varsayılanını korur. Yani, bimzadaki ikinci argüman, ancak ikinci parametrenin önüne ön ek koyarak atlayabilir c=. Ruby bunu simüle etmek için karma kullanır, ancak tam olarak aynı değildir.
maček

2

Ruby belgeleri yerleştirdi:

 =begin

 You could use rdoc to generate man pages from this documentation

 =end

5
Öğreti dizileri, bunları ayarladığınız yöntemlerin / sınıfların bir parçası olarak ortaya çıkar. Böylece yardım (sınıf) yapabilirsiniz ve size
öğretileri


2

Ruby'de, bir dosyayı zorunlu olarak içe aktardığınızda, o dosyada tanımlanan her şey genel ad alanınızda sona erer.

Cargo ile " ad alanınızı karıştırmadan kütüphanelere ihtiyaç duyabilirsiniz ".

# foo-1.0.0.rb
class Foo
  VERSION = "1.0.0"
end

# foo-2.0.0.rb
class Foo
  VERSION = "2.0.0"
end
>> Foo1 = içe aktar ("foo-1.0.0")
>> Foo2 = içe aktar ("foo-2.0.0")
>> Foo1 :: SÜRÜM
=> "1.0.0"
>> Foo2 :: SÜRÜM
=> "2.0.0"

Bu yeni bir cevap değil, bir yorum olmalı.
Lennart Regebro
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.