python - रुबी के पास क्या है कि पायथन नहीं करता है, और इसके विपरीत?




ruby (20)

In Ruby, when you import a file with require, all the things defined in that file will end up in your global namespace.

Cargo साथ आप " अपने नामस्थान को छेड़छाड़ किए बिना पुस्तकालयों की आवश्यकता " कर सकते हैं ।

# 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 = import("foo-1.0.0")
>> Foo2 = import("foo-2.0.0")
>> Foo1::VERSION
=> "1.0.0"
>> Foo2::VERSION
=> "2.0.0"

पाइथन बनाम रूबी की कई चर्चाएं हैं, और मैं सभी उन्हें पूरी तरह से अनुपयोगी पाते हैं, क्योंकि वे सभी इस बात की ओर मुड़ते हैं कि एक्स एक्स भाषा में एक्स क्यों बेकार है, या दावा है कि वाई में एक्स नहीं है, हालांकि वास्तव में यह करता है। मुझे यह भी पता है कि मैं पाइथन क्यों पसंद करता हूं, लेकिन यह भी व्यक्तिपरक है, और किसी को भी चुनने में मदद नहीं करेगा, क्योंकि उनके पास विकास में समान स्वाद नहीं हो सकता है।

इसलिए मतभेदों को सूचीबद्ध रूप से सूचीबद्ध करना दिलचस्प होगा। तो नहीं "पायथन का भेड़ का बच्चा बेकार है"। इसके बजाय यह बताएं कि रूबी के लैम्बडा क्या कर सकते हैं कि पायथन नहीं कर सकता है। कोई विषयपरकता नहीं उदाहरण कोड अच्छा है!

कृपया एक जवाब में कई अंतर मत करो। और उन लोगों को वोट दें जिन्हें आप जानते हैं सही हैं, और जिन लोगों को आप जानते हैं उन्हें गलत (या व्यक्तिपरक हैं)। इसके अलावा, वाक्यविन्यास में मतभेद दिलचस्प नहीं है। हम जानते हैं कि पाइथन इंडेंटेशन के साथ करता है जो रूबी ब्रैकेट्स और सिरों के साथ करता है, और @ जिसे पायथन में स्वयं कहा जाता है।

अद्यतन: यह अब एक समुदाय विकी है, इसलिए हम यहां बड़े अंतर जोड़ सकते हैं।

रूबी कक्षा वर्ग में कक्षा का संदर्भ है

रूबी में आपके पास पहले से ही कक्षा के शरीर में कक्षा (स्वयं) का संदर्भ है। कक्षा निर्माण के समाप्त होने के बाद तक आपके पास पाइथन में कक्षा का संदर्भ नहीं है।

एक उदाहरण:

class Kaka
  puts self
end

इस मामले में स्वयं वर्ग है, और यह कोड "काका" प्रिंट करेगा। कक्षा के नाम को मुद्रित करने का कोई तरीका नहीं है या अन्य तरीकों से पायथन में कक्षा परिभाषा निकाय (विधि परिभाषाओं के बाहर) से कक्षा तक पहुंचने का कोई तरीका नहीं है।

रूबी में सभी वर्ग उत्परिवर्तनीय हैं

यह आपको कोर कक्षाओं में एक्सटेंशन विकसित करने देता है। रेल एक्सटेंशन का एक उदाहरण यहां दिया गया है:

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

पायथन (कल्पना करें कि वहां कोई ''.startswith विधि नहीं थी):

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

आप इसे किसी भी अनुक्रम पर उपयोग कर सकते हैं (केवल स्ट्रिंग नहीं)। इसका उपयोग करने के लिए आपको इसे स्पष्ट रूप से आयात करना चाहिए उदाहरण के लिए, from some_module import starts_with

रुबी में पर्ल जैसी स्क्रिप्टिंग विशेषताएं हैं

रूबी में प्रथम श्रेणी regexps, $ -variables, लाइन इनपुट लूप द्वारा अजीब / perl लाइन और अन्य विशेषताएं हैं जो छोटे शैल स्क्रिप्ट लिखने के लिए अधिक उपयुक्त बनाती हैं जो पाठ फ़ाइलों को मर्ज करती हैं या अन्य प्रोग्राम्स के लिए गोंद कोड के रूप में कार्य करती हैं।

रुबी के पास प्रथम श्रेणी की निरंतरता है

कॉलक स्टेटमेंट के लिए धन्यवाद। पायथन में आप विभिन्न तकनीकों द्वारा निरंतरता बना सकते हैं, लेकिन भाषा में कोई समर्थन नहीं है।

रूबी में ब्लॉक हैं

"डू" कथन के साथ आप रूबी में एक बहु-लाइन अज्ञात फ़ंक्शन बना सकते हैं, जिसे विधि के सामने विधि में तर्क के रूप में पारित किया जाएगा, और वहां से बुलाया जाएगा। पायथन में आप इसे या तो विधि या जेनरेटर के साथ पास करके करेंगे।

माणिक:

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

पायथन (रूबी ब्लॉक पायथन में विभिन्न संरचनाओं से मेल खाते हैं):

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

या

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

या

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

amethod(function)     # `function` is a callback

दिलचस्प बात यह है कि ब्लॉक को कॉल करने के लिए रूबी में सुविधा कथन को "उपज" कहा जाता है, जो पाइथन में जनरेटर बनाएगा।

माणिक:

def themethod
    yield 5
end

themethod do |foo|
    puts foo
end

अजगर:

def themethod():
    yield 5

for foo in themethod():
    print foo

हालांकि सिद्धांत अलग हैं, परिणाम काफी समान है।

रूबी अधिक आसानी से कार्यात्मक शैली (पाइप की तरह) प्रोग्रामिंग का समर्थन करता है

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

अजगर:

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

पायथन में अंतर्निर्मित जेनरेटर हैं (जो ऊपर बताए गए रूबी ब्लॉक की तरह उपयोग किए जाते हैं)

पाइथन भाषा में जेनरेटर के लिए समर्थन है। रूबी 1.8 में आप जेनरेटर मॉड्यूल का उपयोग कर सकते हैं जो ब्लॉक से जेनरेटर बनाने के लिए निरंतरता का उपयोग करता है। या, आप बस एक ब्लॉक / proc / lambda का उपयोग कर सकते हैं! इसके अलावा, रुबी में 1.9 फाइबर हैं, और जनरेटर के रूप में उपयोग किया जा सकता है, और एन्यूमेरेटर क्लास एक अंतर्निहित जेनरेटर 4

docs.python.org में यह जनरेटर उदाहरण है:

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

उपर्युक्त ब्लॉक उदाहरणों के साथ इसकी तुलना करें।

पायथन में लचीला नाम अंतरिक्ष हैंडलिंग है

रुबी में, जब आप require साथ एक फ़ाइल आयात करते हैं, तो उस फ़ाइल में परिभाषित सभी चीजें आपके वैश्विक नामस्थान में समाप्त हो जाएंगी। यह नेमस्पेस प्रदूषण का कारण बनता है। इसका समाधान रूबी मॉड्यूल है। लेकिन यदि आप मॉड्यूल के साथ नेमस्पेस बनाते हैं, तो आपको निहित कक्षाओं तक पहुंचने के लिए उस नेमस्पेस का उपयोग करना होगा।

पायथन में, फ़ाइल एक मॉड्यूल है, और आप अपने निहित नामों को उनके from themodule import * आयात कर सकते हैं, जिससे आप चाहें तो नेमस्पेस को प्रदूषित कर सकते हैं। लेकिन आप केवल from themodule import aname, another चयनित नाम आयात कर सकते हैं from themodule import aname, another या आप बस import themodule कर सकते हैं और फिर themodule.aname साथ नामों तक पहुंच सकते हैं। यदि आप अपने नेमस्पेस में अधिक स्तर चाहते हैं तो आपके पास पैकेज हो सकते हैं, जो मॉड्यूल के साथ निर्देशिकाएं हैं और एक __init__.py फ़ाइल हैं।

पायथन में डॉकस्ट्रिंग है

डॉकस्ट्रिंग स्ट्रिंग्स हैं जो मॉड्यूल, फ़ंक्शंस और विधियों से जुड़ी हैं और रनटाइम पर आत्मनिरीक्षण की जा सकती हैं। यह मदद कमांड और स्वचालित दस्तावेज़ीकरण जैसी चीजों को बनाने में मदद करता है।

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

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

रूबी के समकक्ष javadocs के समान हैं, और इसके बजाय विधि के ऊपर स्थित हैं। उन्हें 1.9 के विधि # स्रोत_ स्थान आवृत्ति उपयोग का उपयोग करके फ़ाइलों से रनटाइम पर पुनर्प्राप्त किया जा सकता है

पायथन में कई विरासत हैं

रुबी नहीं ("उद्देश्य पर" - रुबी की वेबसाइट देखें , यहां देखें कि यह रूबी में कैसे किया जाता है )। यह मॉड्यूल अवधारणा को एक प्रकार के सार वर्गों के रूप में पुन: उपयोग करता है।

पायथन में सूची / निर्देश की समझ है

अजगर:

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

माणिक:

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

अजगर:

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

माणिक:

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

पायथन 2.7+ :

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

माणिक:

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

पायथन में सजावटी हैं

रूबी में सजावट के समान चीजें भी बनाई जा सकती हैं, और यह भी तर्क दिया जा सकता है कि वे पाइथन में जितना आवश्यक नहीं हैं।

सिंटेक्स मतभेद

रूबी को अपने सभी क्षेत्रों को बंद करने के लिए "अंत" या "}" की आवश्यकता होती है, जबकि पायथन केवल सफेद-स्थान का उपयोग करता है। व्हाइटस्पेस केवल इंडेंटेशन की अनुमति देने के लिए रुबी में हाल ही में प्रयास किए गए हैं http://github.com/michaeledgar/seamless


पायथन उदाहरण

कार्य पाइथन में प्रथम श्रेणी चर हैं। आप एक समारोह घोषित कर सकते हैं, इसे किसी ऑब्जेक्ट के रूप में पास कर सकते हैं, और इसे ओवरराइट कर सकते हैं:

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

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

यह आधुनिक पटकथा भाषाओं की एक मौलिक विशेषता है। जावास्क्रिप्ट और लुआ यह भी करते हैं। रूबी इस तरह के कार्यों का इलाज नहीं करता है; फ़ंक्शन नामकरण इसे कॉल करता है।

बेशक, रूबी में इन चीजों को करने के तरीके हैं, लेकिन वे प्रथम श्रेणी के संचालन नहीं हैं। उदाहरण के लिए, आप एक चर के रूप में इलाज के लिए Proc.new के साथ एक फ़ंक्शन को लपेट सकते हैं - लेकिन तब यह अब कोई फ़ंक्शन नहीं है; यह एक "कॉल" विधि के साथ एक वस्तु है।

रूबी के कार्य प्रथम श्रेणी की वस्तुओं नहीं हैं

रूबी फ़ंक्शंस प्रथम श्रेणी की ऑब्जेक्ट्स नहीं हैं। कार्य को किसी ऑब्जेक्ट में उन्हें पास करने के लिए लपेटा जाना चाहिए; परिणामस्वरूप ऑब्जेक्ट को फ़ंक्शन की तरह नहीं माना जा सकता है। कार्यों को प्रथम श्रेणी के तरीके में असाइन नहीं किया जा सकता है; इसके बजाए, इसके कंटेनर ऑब्जेक्ट में एक फ़ंक्शन को संशोधित करने के लिए बुलाया जाना चाहिए।

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!"    

आखिर में सभी उत्तर कुछ स्तर पर व्यक्तिपरक होने जा रहे हैं, और अब तक पोस्ट किए गए उत्तरों में काफी साबित होता है कि आप किसी एक सुविधा को इंगित नहीं कर सकते हैं जो कि अन्य भाषा में समान रूप से अच्छा (यदि समान नहीं है) में करने योग्य नहीं है , क्योंकि दोनों भाषाएं बहुत संक्षिप्त और अभिव्यक्तिपूर्ण हैं।

मुझे पायथन का वाक्यविन्यास पसंद है। हालांकि, आपको रूबी की असली सुंदरता को खोजने के लिए वाक्यविन्यास से थोड़ा गहराई से खोदना होगा। रूबी की स्थिरता में ज़ेन जैसी सुंदरता है। हालांकि कोई मामूली उदाहरण संभवतः इसे पूरी तरह से समझा सकता है, लेकिन मैं इसका अर्थ समझाने के लिए यहां बस एक के साथ आने का प्रयास करूंगा।

इस स्ट्रिंग में शब्दों को उलट दें:

sentence = "backwards is sentence This"

जब आप सोचते हैं कि आप इसे कैसे करेंगे, तो आप निम्न कार्य करेंगे:

  1. वाक्य को शब्दों में विभाजित करें
  2. शब्दों को उलट दें
  3. शब्दों को एक स्ट्रिंग में दोबारा जुड़ें

रुबी में, आप यह करेंगे:

sentence.split.reverse.join ' '

जैसा कि आप इसके बारे में सोचते हैं, वही अनुक्रम में, एक विधि दूसरे के बाद कॉल करें।

पायथन में, यह इस तरह दिखता है:

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

समझना मुश्किल नहीं है, लेकिन इसमें काफी प्रवाह नहीं है। विषय (वाक्य) मध्य में दफनाया गया है। संचालन कार्यों और वस्तु विधियों का मिश्रण है। यह एक मामूली उदाहरण है, लेकिन वास्तव में रूबी के साथ काम करने और समझने के दौरान कई अलग-अलग उदाहरण सामने आते हैं, खासकर गैर-तुच्छ कार्यों पर।


आप पाइथन में मॉड्यूल से केवल विशिष्ट फ़ंक्शन आयात कर सकते हैं। रूबी में, आप विधियों की पूरी सूची आयात करते हैं। आप रूबी में उन्हें "महत्वहीन" कर सकते थे, लेकिन यह सब कुछ नहीं है।

संपादित करें:

चलो इस रूबी मॉड्यूल लेते हैं:


module Whatever
  def method1
  end

  def method2
  end
end

यदि आप इसे अपने कोड में शामिल करते हैं:


include Whatever

आप देखेंगे कि विधि 1 और method2 दोनों को आपके नामस्थान में जोड़ा गया है। आप केवल विधि 1 आयात नहीं कर सकते हैं। आप या तो दोनों को आयात करते हैं या आप उन्हें बिल्कुल आयात नहीं करते हैं। पायथन में आप केवल अपनी पसंद के तरीकों को आयात कर सकते हैं। यदि इसका नाम होगा तो इसे चुनिंदा आयात कहा जाएगा?


पाइथन में "हम सभी वयस्क हैं" मानसिकता है। इस प्रकार, आप पाएंगे कि रूबी में स्थिरांक जैसी चीजें हैं जबकि पायथन नहीं करता है (हालांकि रूबी के स्थिरांक केवल चेतावनी उठाते हैं)। सोचने का पाइथन तरीका यह है कि यदि आप कुछ स्थिर बनाना चाहते हैं, तो आपको वैरिएबल नामों को सभी कैप्स में रखना चाहिए और इसे बदलना नहीं चाहिए।

उदाहरण के लिए, रूबी:

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

अजगर:

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

पायथन में सूची-संकलन और जनरेटर के लिए एक स्पष्ट, अंतर्निहित वाक्यविन्यास है जबकि रूबी में आप मानचित्र और कोड ब्लॉक का उपयोग करेंगे।

तुलना

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

सेवा मेरे

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

मुझे नहीं लगता कि "रूबी एक्स और पायथन नहीं है, जबकि पाइथन में वाई और रूबी नहीं है" इसे देखने का सबसे उपयोगी तरीका है। वे कई साझा क्षमताओं के साथ, काफी समान भाषाएं हैं।

एक बड़ी डिग्री के लिए, अंतर वह है जो भाषा सुरुचिपूर्ण और पठनीय बनाता है। आपके द्वारा लाए गए उदाहरण का उपयोग करने के लिए, दोनों सैद्धांतिक रूप से लैम्ब्डा हैं, लेकिन पाइथन प्रोग्रामर उनसे बचने के लिए प्रवृत्त होते हैं, और उनका उपयोग करके बनाई गई रचनाएं रूबी में पढ़ने योग्य या बेवकूफ के रूप में कहीं भी नहीं दिखती हैं। तो पाइथन में, एक अच्छा प्रोग्रामर रूबी में समस्या से निपटने के लिए एक अलग मार्ग लेना चाहता है, सिर्फ इसलिए कि यह वास्तव में ऐसा करने का बेहतर तरीका है।


मैं मूल प्रश्न का एक संस्करण सुझा सकता हूं, "रुबी के पास क्या है कि पाइथन नहीं करता है, और इसके विपरीत?" जो निराशाजनक उत्तर को स्वीकार करता है, "ठीक है, आप रूबी या पायथन के साथ क्या कर सकते हैं जिसे इंटरकेल में नहीं किया जा सकता है?" उस स्तर पर कुछ भी नहीं, क्योंकि पाइथन और रुबी विशाल शाही परिवार का हिस्सा हैं जो ट्यूरिंग सिक्योरेंट होने के सिंहासन पर बैठे हैं।

लेकिन इसके बारे में क्या:

पाइथन में क्या किया जा सकता है और अच्छी तरह से किया जा सकता है जो रूबी में ऐसी सुंदरता और अच्छी इंजीनियरिंग के साथ नहीं किया जा सकता है, या इसके विपरीत?

यह केवल सुविधा तुलना की तुलना में अधिक दिलचस्प हो सकता है।


रूबी में ब्लॉक की अवधारणाएं होती हैं , जो कोड के एक वर्ग के आसपास अनिवार्य रूप से सिंटेक्टिक चीनी होती हैं; वे बंद करने और उन्हें किसी अन्य विधि में पास करने का एक तरीका हैं जो ब्लॉक का उपयोग कर सकता है या नहीं। एक yield स्टेटमेंट के माध्यम से बाद में एक ब्लॉक लगाया जा सकता है।

उदाहरण के लिए, Array पर each विधि की एक साधारण परिभाषा कुछ ऐसा हो सकती है:

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

फिर आप इसे इस तरह से बुला सकते हैं:

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

पायथन में अज्ञात कार्य / बंद / लैम्ब्डा हैं, लेकिन इसमें पर्याप्त ब्लॉक नहीं हैं क्योंकि इसमें कुछ उपयोगी वाक्य रचनात्मक चीनी गायब हैं। हालांकि, विज्ञापन-प्रसार में इसे पाने के लिए कम से कम एक तरीका है। उदाहरण के लिए, here देखें।



बेकार ढंग से प्रतिलिपि / चिपकाया गया: एलेक्स मार्टेलि ने comp.lang.python मेलिंग सूची से " पाइथन से रूबी के बारे में बेहतर क्या है " पर जवाब दिया।

18 अगस्त 2003, सुबह 10:50 बजे एरिक मैक्स फ्रांसिस ने लिखा:

"ब्रैंडन जे। वैन हर" ने लिखा:

पाइथन से रूबी के बारे में क्या बेहतर है? मुझे यकीन है कि कुछ है। यह क्या है?

क्या पाइथन लोगों की बजाय रूबी लोगों से यह पूछने के लिए और अधिक समझदारी नहीं होगी?

किसी के उद्देश्यों के आधार पर हो सकता है, या नहीं, उदाहरण के लिए, यदि किसी के उद्देश्यों में पाइथन समुदाय का "सामाजिक अध्ययन" शामिल है, तो उस समुदाय को प्रश्न डालने से उन्हें कहीं और जानकारी देने से अधिक जानकारी मिलती है :-)।

Personally, I gladly took the opportunity to follow Dave Thomas' one-day Ruby tutorial at last OSCON. Below a thin veneer of syntax differences, I find Ruby and Python amazingly similar -- if I was computing the minimum spanning tree among just about any set of languages, I'm pretty sure Python and Ruby would be the first two leaves to coalesce into an intermediate node:-).

Sure, I do get weary, in Ruby, of typing the silly "end" at the end of each block (rather than just unindenting) -- but then I do get to avoid typing the equally-silly ':' which Python requires at the start of each block, so that's almost a wash:-). Other syntax differences such as '@foo' versus 'self.foo', or the higher significance of case in Ruby vs Python, are really just about as irrelevant to me.

Others no doubt base their choice of programming languages on just such issues, and they generate the hottest debates -- but to me that's just an example of one of Parkinson's Laws in action (the amount on debate on an issue is inversely proportional to the issue's actual importance).

Edit (by AM 6/19/2010 11:45): this is also known as "painting the bikeshed" (or, for short, "bikeshedding") -- the reference is, again, to Northcote Parkinson, who gave "debates on what color to paint the bikeshed" as a typical example of "hot debates on trivial topics". (end-of-Edit).

One syntax difference that I do find important, and in Python's favor -- but other people will no doubt think just the reverse -- is "how do you call a function which takes no parameters". In Python (like in C), to call a function you always apply the "call operator" -- trailing parentheses just after the object you're calling (inside those trailing parentheses go the args you're passing in the call -- if you're passing no args, then the parentheses are empty). This leaves the mere mention of any object, with no operator involved, as meaning just a reference to the object -- in any context, without special cases, exceptions, ad-hoc rules, and the like. In Ruby (like in Pascal), to call a function WITH arguments you pass the args (normally in parentheses, though that is not invariably the case) -- BUT if the function takes no args then simply mentioning the function implicitly calls it. This may meet the expectations of many people (at least, no doubt, those whose only previous experience of programming was with Pascal, or other languages with similar "implicit calling", such as Visual Basic) -- but to me, it means the mere mention of an object may EITHER mean a reference to the object, OR a call to the object, depending on the object's type -- and in those cases where I can't get a reference to the object by merely mentioning it I will need to use explicit "give me a reference to this, DON'T call it!" operators that aren't needed otherwise. I feel this impacts the "first-classness" of functions (or methods, or other callable objects) and the possibility of interchanging objects smoothly. Therefore, to me, this specific syntax difference is a serious black mark against Ruby -- but I do understand why others would thing otherwise, even though I could hardly disagree more vehemently with them:-).

Below the syntax, we get into some important differences in elementary semantics -- for example, strings in Ruby are mutable objects (like in C++), while in Python they are not mutable (like in Java, or I believe C#). Again, people who judge primarily by what they're already familiar with may think this is a plus for Ruby (unless they're familiar with Java or C#, of course:-). Me, I think immutable strings are an excellent idea (and I'm not surprised that Java, independently I think, reinvented that idea which was already in Python), though I wouldn't mind having a "mutable string buffer" type as well (and ideally one with better ease-of-use than Java's own "string buffers"); and I don't give this judgment because of familiarity -- before studying Java, apart from functional programming languages where all data are immutable, all the languages I knew had mutable strings -- yet when I first saw the immutable-string idea in Java (which I learned well before I learned Python), it immediately struck me as excellent, a very good fit for the reference-semantics of a higher level programming language (as opposed to the value-semantics that fit best with languages closer to the machine and farther from applications, such as C) with strings as a first-class, built-in (and pretty crucial) data type.

Ruby does have some advantages in elementary semantics -- for example, the removal of Python's "lists vs tuples" exceedingly subtle distinction. But mostly the score (as I keep it, with simplicity a big plus and subtle, clever distinctions a notable minus) is against Ruby (eg, having both closed and half-open intervals, with the notations a..b and a...b [anybody wants to claim that it's obvious which is which?-)], is silly -- IMHO, of course!). Again, people who consider having a lot of similar but subtly different things at the core of a language a PLUS, rather than a MINUS, will of course count these "the other way around" from how I count them:-).

Don't be misled by these comparisons into thinking the two languages are very different, mind you. They aren't. But if I'm asked to compare "capelli d'angelo" to "spaghettini", after pointing out that these two kinds of pasta are just about undistinguishable to anybody and interchangeable in any dish you might want to prepare, I would then inevitably have to move into microscopic examination of how the lengths and diameters imperceptibly differ, how the ends of the strands are tapered in one case and not in the other, and so on -- to try and explain why I, personally, would rather have capelli d'angelo as the pasta in any kind of broth, but would prefer spaghettini as the pastasciutta to go with suitable sauces for such long thin pasta forms (olive oil, minced garlic, minced red peppers, and finely ground anchovies, for example - but if you sliced the garlic and peppers instead of mincing them, then you should choose the sounder body of spaghetti rather than the thinner evanescence of spaghettini, and would be well advised to forego the achovies and add instead some fresh spring basil [or even -- I'm a heretic...! -- light mint...] leaves -- at the very last moment before serving the dish). Ooops, sorry, it shows that I'm traveling abroad and haven't had pasta for a while, I guess. But the analogy is still pretty good!-)

So, back to Python and Ruby, we come to the two biggies (in terms of language proper -- leaving the libraries, and other important ancillaries such as tools and environments, how to embed/extend each language, etc, etc, out of it for now -- they wouldn't apply to all IMPLEMENTATIONS of each language anyway, eg, Jython vs Classic Python being two implementations of the Python language!):

  1. Ruby's iterators and codeblocks vs Python's iterators and generators;

  2. Ruby's TOTAL, unbridled "dynamicity", including the ability
    to "reopen" any existing class, including all built-in ones, and change its behavior at run-time -- vs Python's vast but bounded dynamicity, which never changes the behavior of existing built-in classes and their instances.

Personally, I consider 1 a wash (the differences are so deep that I could easily see people hating either approach and revering the other, but on MY personal scales the pluses and minuses just about even up); and 2 a crucial issue -- one that makes Ruby much more suitable for "tinkering", BUT Python equally more suitable for use in large production applications. It's funny, in a way, because both languages are so MUCH more dynamic than most others, that in the end the key difference between them from my POV should hinge on that -- that Ruby "goes to eleven" in this regard (the reference here is to "Spinal Tap", of course). In Ruby, there are no limits to my creativity -- if I decide that all string comparisons must become case-insensitive, I CAN DO THAT ! Ie, I can dynamically alter the built-in string class so that a = "Hello World" b = "hello world" if a == b print "equal!\n" else print "different!\n" end WILL print "equal". In python, there is NO way I can do that. For the purposes of metaprogramming, implementing experimental frameworks, and the like, this amazing dynamic ability of Ruby is extremely appealing. BUT -- if we're talking about large applications, developed by many people and maintained by even more, including all kinds of libraries from diverse sources, and needing to go into production in client sites... well, I don't WANT a language that is QUITE so dynamic, thank you very much. I loathe the very idea of some library unwittingly breaking other unrelated ones that rely on those strings being different -- that's the kind of deep and deeply hidden "channel", between pieces of code that LOOK separate and SHOULD BE separate, that spells death in large-scale programming. By letting any module affect the behavior of any other "covertly", the ability to mutate the semantics of built-in types is just a BAD idea for production application programming, just as it's cool for tinkering.

If I had to use Ruby for such a large application, I would try to rely on coding-style restrictions, lots of tests (to be rerun whenever ANYTHING changes -- even what should be totally unrelated...), and the like, to prohibit use of this language feature. But NOT having the feature in the first place is even better, in my opinion -- just as Python itself would be an even better language for application programming if a certain number of built-ins could be "nailed down", so I KNEW that, eg, len("ciao") is 4 (rather than having to worry subliminally about whether somebody's changed the binding of name 'len' in the builtins module...). I do hope that eventually Python does "nail down" its built-ins.

But the problem's minor, since rebinding built-ins is quite a deprecated as well as a rare practice in Python. In Ruby, it strikes me as major -- just like the too powerful macro facilities of other languages (such as, say, Dylan) present similar risks in my own opinion (I do hope that Python never gets such a powerful macro system, no matter the allure of "letting people define their own domain-specific little languages embedded in the language itself" -- it would, IMHO, impair Python's wonderful usefulness for application programming, by presenting an "attractive nuisance" to the would-be tinkerer who lurks in every programmer's heart...).

एलेक्स


Another difference in lambdas between Python and Ruby is demonstrated by Paul Graham's Accumulator Generator problem. Reprinted here:

Write a function foo that takes a number n and returns a function that takes a number i, and returns n incremented by i. Note: (a) that's number, not integer, (b) that's incremented by, not plus.

In Ruby, you can do this:

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

In Python, you'd create an object to hold the state of n:

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

Some folks might prefer the explicit Python approach as being clearer conceptually, even if it's a bit more verbose. You store state like you do for anything else. You just need to wrap your head around the idea of callable objects. But regardless of which approach one prefers aesthetically, it does show one respect in which Ruby lambdas are more powerful constructs than Python's.


I would like to mention Python descriptor API that allows one customize object-to-attribute "communication". It is also noteworthy that, in Python, one is free to implement an alternative protocol via overriding the default given through the default implementation of the __getattribute__ method. Let me give more details about the aforementioned. Descriptors are regular classes with __get__ , __set__ and/or __delete__ methods. When interpreter encounters something like anObj.anAttr , the following is performed:

  • __getattribute__ method of anObj is invoked
  • __getattribute__ retrieves anAttr object from the class dict
  • it checks whether abAttr object has __get__ , __set__ or __delete__ callable objects
  • the context (ie, caller object or class, and value, instead of the latter, if we have setter) is passed to the callable object
  • the result is returned.

As was mentioned, this is the default behavior. One is free to change the protocol by re-implementing __getattribute__ .

This technique is lot more powerful than decorators.


I'm unsure of this, so I add it as an answer first.

Python treats unbound methods as functions

That means you can call a method either like theobject.themethod() or by TheClass.themethod(anobject) .

Edit: Although the difference between methods and functions is small in Python, and non-existant in Python 3, it also doesn't exist in Ruby, simply because Ruby doesn't have functions. When you define functions, you are actually defining methods on Object.

But you still can't take the method of one class and call it as a function, you would have to rebind it to the object you want to call on, which is much more obstuse.


Python has docstrings and ruby doesn't... Or if it doesn't, they are not accessible as easily as in python.

Ps. If im wrong, pretty please, leave an example? I have a workaround that i could monkeypatch into classes quite easily but i'd like to have docstring kinda of a feature in "native way".


Ruby has a line by line loop over input files (the '-n' flag) from the commandline so it can be used like AWK. This Ruby one-liner:

ruby -ne 'END {puts $.}'

will count lines like the AWK one-liner:

awk 'END{print NR}'

Ruby gets feature this through Perl, which took it from AWK as a way of getting sysadmins on board with Perl without having to change the way they do things.


Ruby has embedded documentation:

 =begin

 You could use rdoc to generate man pages from this documentation

 =end

Ruby has sigils and twigils, Python doesn't.

Edit : And one very important thing that I forgot (after all, the previous was just to flame a little bit :-p):

Python has a JIT compiler ( Psyco ), a sightly lower level language for writing faster code ( Pyrex ) and the ability to add inline C++ code ( Weave ).


Syntax is not a minor thing, it has a direct impact on how we think. It also has a direct effect on the rules we create for the systems we use. As an example we have the order of operations because of the way we write mathematical equations or sentences. The standard notation for mathematics allows people to read it more than one way and arrive at different answers given the same equation. If we had used prefix or postfix notation we would have created rules to distinguish what the numbers to be manipulated were rather than only having rules for the order in which to compute values.

The standard notation makes it plain what numbers we are talking about while making the order in which to compute them ambiguous. Prefix and postfix notation make the order in which to compute plain while making the numbers ambiguous. Python would already have multiline lambdas if it were not for the difficulties caused by the syntactic whitespace. (Proposals do exist for pulling this kind of thing off without necessarily adding explicit block delimiters.)

I find it easier to write conditions where I want something to occur if a condition is false much easier to write with the unless statement in Ruby than the semantically equivalent "if-not" construction in Ruby or other languages for example. If most of the languages that people are using today are equal in power, how can the syntax of each language be considered a trivial thing? After specific features like blocks and inheritance mechanisms etc. syntax is the most important part of a language,hardly a superficial thing.

What is superficial are the aesthetic qualities of beauty that we ascribe to syntax. Aesthetics have nothing to do with how our cognition works, syntax does.


You can have code in the class definition in both Ruby and Python. However, in Ruby you have a reference to the class (self). In Python you don't have a reference to the class, as the class isn't defined yet.

एक उदाहरण:

class Kaka
  puts self
end

self in this case is the class, and this code would print out "Kaka". There is no way to print out the class name or in other ways access the class from the class definition body in Python.





ruby