Що Рубі має той Python, і навпаки?


263

Існує багато дискусій про Python vs Ruby, і всі вони вважають їх абсолютно непосидними, тому що всі вони обертаються, чому функція X відмовляє в мові Y, або у тому, що мова претензії Y не має X, хоча насправді це так і є. Я також точно знаю, чому я віддаю перевагу Python, але це теж суб'єктивно, і нікому не допоможе вибрати, оскільки вони можуть не мати ті самі смаки в розвитку, як я.

Тому було б цікаво перелічити відмінності об’єктивно. Тож жодна «лямбда Пітона не смокче». Натомість поясніть, що можуть зробити лямбди Рубі, які не можуть Python. Без суб'єктивності. Приклад код хороший!

Не майте декількох відмінностей в одній відповіді, будь ласка. І проголосуйте за те, що ви знаєте, що вони правильні, а ті, кого ви знаєте, неправильні (або є суб'єктивними). Також відмінності в синтаксисі не цікаві. Ми знаємо, що Python робить з відступом, що робить Ruby з дужками і кінцями, і що @ називається self у Python.

ОНОВЛЕННЯ: Зараз це вікі спільноти, тому ми можемо додати тут великих відмінностей.

Рубі має посилання на клас в тілі класу

У Ruby у вас є посилання на клас (self), який вже знаходиться в тілі класу. У Python ви не маєте посилання на клас до закінчення побудови класу.

Приклад:

class Kaka
  puts self
end

self у цьому випадку є класом, і цей код видав би "Kaka". Немає можливості роздрукувати ім’я класу або іншим способом отримати доступ до класу з тіла визначення класу в Python (зовнішні визначення методів).

Усі класи в Рубі змінні

Це дозволяє розробляти розширення до основних класів. Ось приклад розширення рейок:

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

Python (уявіть, що ''.startswithметоду не було ):

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

Ви можете використовувати його в будь-якій послідовності (не тільки в рядках). Для того , щоб використовувати його , ви повинні імпортувати його в явному вигляді , наприклад, from some_module import starts_with.

У Рубі є сценарії, подібні до Perl

Ruby має першокласні regexps, $ -variables, рядок awk / perl за рядком введення рядка та інші функції, які роблять його більш придатним для написання невеликих скриптів оболонки, які об'єднують текстові файли або виконують роль клейкого коду для інших програм.

Рубі має продовження першого класу

Завдяки заяві callcc. У Python ви можете створювати продовження різними техніками, але немає підтримки, вбудованої в мову.

У Рубі є блоки

За допомогою оператора "do" ви можете створити багаторядову анонімну функцію в Ruby, яка буде передана як аргумент методу перед do, і викликається звідти. У Python ви б замість цього зробили або пропустивши метод, або з генераторами.

Ruby:

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

Python (блоки Ruby відповідають різним конструкціям Python):

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

Цікаво, що заява про зручність в Ruby для виклику блоку називається "дохідність", яка в Python створить генератор.

Ruby:

def themethod
    yield 5
end

themethod do |foo|
    puts foo
end

Пітон:

def themethod():
    yield 5

for foo in themethod():
    print foo

Хоча принципи різні, результат вражаюче схожий.

Ruby легше підтримує програмування в функціональному стилі (у вигляді труб)

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

Пітон:

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

Python має вбудовані генератори (які використовуються як блоки Ruby, як зазначено вище)

У Python є підтримка генераторів на мові. У Ruby 1.8 ви можете використовувати генераторний модуль, який використовує продовження для створення генератора з блоку. Або ви можете просто використовувати блок / proc / lambda! Більше того, у волокнах Ruby 1.9 волокна є і можуть використовуватися як генератори, а клас Enumerator - це вбудований генератор 4

docs.python.org має такий приклад генератора:

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

Порівняйте це з наведеними вище блоковими прикладами.

У Python є гнучка обробка простору імен

Коли ви імпортуєте файл у Ruby, requireусі речі, визначені у цьому файлі, опиняться у вашому глобальному просторі імен. Це спричиняє забруднення простору імен. Рішенням цього є модулі Rubys. Але якщо ви створюєте простір імен з модулем, вам доведеться використовувати цей простір імен для доступу до класів, що містяться.

У Python файл є модулем, і ви можете імпортувати містяться в ньому імена from themodule import *, тим самим забруднюючи простір імен, якщо хочете. Але ви також можете імпортувати лише вибрані імена за допомогою from themodule import aname, anotherабо ви можете просто import themoduleі потім отримати доступ до імен themodule.aname. Якщо ви хочете отримати більше рівнів у вашому просторі імен, ви можете мати пакунки, що представляють собою каталоги з модулями та __init__.pyфайлом.

У Python є документи

Документальні рядки - це рядки, які приєднуються до модулів, функцій та методів, і їх можна вводити під час виконання. Це допомагає створити такі речі, як команда довідки та автоматична документація.

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

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

Еквівалент Ruby схожий на javadocs, і розташований над методом замість нього. Їх можна отримати під час виконання з файлів, використовуючи приклад використання методу 1.9 з використанням # source_location

Пітон має багаторазове успадкування

Рубі не ("спеціально" - дивіться веб-сайт Ruby, дивіться тут, як це робиться в Ruby ). Він повторно використовує концепцію модуля як тип абстрактних класів.

Python має розуміння списку / вивідок

Пітон:

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

Ruby:

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]

Ruby:

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'}

Ruby:

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

У Python є декоратори

Речі, схожі на декораторів, також можна створити в Ruby, і можна також стверджувати, що вони не такі необхідні, як у Python.

Синтаксичні відмінності

Ruby вимагає "end" або "}", щоб закрити всі його області, тоді як Python використовує лише пробіл. Нещодавно були спроби в Ruby дозволити відступ лише для пробілів http://github.com/michaeledgar/seamless


2
Щодо багаторазового успадкування, сказати просто "Рубі не" є сумлінним. Я не можу придумати нічого, що ви можете зробити в Python з багаторазовим успадкуванням, що ви не можете зробити в рубіні з модулями / "mixin nasleditation". (Можна навіть сперечатися, що включення модулів просто не є багатократним успадкуванням.)
Логан Капальдо,

2
Те, що ви можете зробити те ж саме іншим способом, є аргументом, який не відповідає. Тут все можна зробити іншим способом. А оскільки модулі не є класами, це не множинне успадкування. Ви можете надати приклади коду того, як це робиться в багатократному спадкуванні Pythons порівняно з модулями Rubys.
Леннарт Регебро

3
Модулі - це не класи, але класи - це модулі. % ruby ​​-e 'p Клас <Модуль' вірно
Логан Капальдо

8
-1 На жаль, це питання не вистачає своєї мети, і більшість нібито відмінностей взагалі не є різницями та дезінформацією!
упередженість

2
Модуль включає насправді багаторазове успадкування, не лише в концепції, а в реальній реалізації в інтерпретаторі Ruby. Коли модуль Ruby включений, його вводять у ланцюг спадкування точно так само, як і суперкласи. Дозвіл методу однаковий. У Ruby кілька модулів включає в себе багатократне успадкування. Кожен, хто хоче оскаржити це як семантично «не те саме», як багаторазове успадкування, просто є педантичним. Який сенс, щоб щось не було «тим же самим», якщо ефект однаковий і такий же легко досягнутий? Відмінність без різниці.
Дейв Сімс

Відповіді:


34

У Рубі є поняття блоків , які по суті є синтаксичним цукром навколо розділу коду; вони є способом створити закриття та передати їх іншому методу, який може або не може використовувати блок. Пізніше виклик блоку можна через yieldоператор.

Наприклад, просте визначення eachметоду наArray може бути чимось на зразок:

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]

У Python є анонімні функції / закриття / лямбда, але це не зовсім блоки, оскільки в ньому відсутні деякі корисні синтаксичні цукру. Однак існує принаймні один спосіб отримати це в спеціальному порядку. Дивіться, наприклад, тут .


6
@Lennart: окрім вашого прикладу просто жахливого, це теж синтаксично неправильно.

2
@unbeknow: А, правильно. Але якби це була функція замість друку, вона працювала б. У python 3 це працює: [print (e + 5) for e in [1,2,3,4]] І коли мова йде про жахливість, я думаю, що код рубіну вище жахливий, тому це явно суб'єктивно, і, отже, не частина цього питання. @John Я не кажу, що це рівнозначно, я кажу, що не очевидно, в чому різниця у вашому прикладі. @Bastien, ні, але те, що ти можеш робити подібні речі, не означає, що вони однакові. Тут слід вказати відмінності, навіть якщо існують інші способи зробити це.
Леннарт Регебро

22
Я програміст Python. Я хотів би бачити приклад того, як блоки Ruby допомагають вам написати щось більш стисло або красивіше, ніж у Python, оскільки в ньому немає блоків. Ваш приклад може бути записаний: для i в [1, 2, 3, 4]: print (i + 5). Він не використовує блоки, але його лаконічний і красивий, а також рубін кожного прикладу.
Мануель Серон

10
@Manuel, програми корисні для приєднання функторів до нетривіальних структур даних (дерев, графіків ...), які не можуть бути "для петель" і, отже, потребують спеціальних ітераторів для поперек. Блоки, які є анонімними документами, дозволяють вам реалізувати функтор в одному виразі (порівняно з визначенням, а потім реалізувати), що різко прискорює процес кодування та уточнює наміри. Наприклад, якщо ви створювали структуру даних графіків, ви могли б визначити один ітератор "кожного", а потім змішати кількість, яка б миттєво надала вам доступ до десятків ітераторів (сортування, все? Будь-які ?, grep). Тепер ви дзвоните в блок ...
упередження

4
@RommeDeSerieux, тому що їй потрібна назва в мові! Більше того, це об’єкт функції, а не функція. Давайте подивимось на документи Ruby: "Об'єкти Proc - це блоки коду, які були прив'язані до набору локальних змінних", тож анонімний Proc є просто блоком, і це, звичайно, не просто функція!
упередженість

28

Приклад Python

Функції - це першокласні змінні в Python. Ви можете оголосити функцію, передати її як об'єкт і перезаписати:

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

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

Це фундаментальна особливість сучасних мов сценарію. JavaScript і Lua роблять це теж. Рубі не розглядає функції таким чином; іменування функції викликає її.

Звичайно, є такі способи зробити в Ruby, але це не першокласні операції. Наприклад, ви можете обернути функцію з Proc.new, щоб розглянути її як змінну - але тоді це вже не функція; це об’єкт методом "виклик".

Функції Ruby - це не першокласні об'єкти

Функції Ruby - це не першокласні об’єкти. Функції повинні бути загорнені в об’єкт, щоб передати їх навколо; отриманий об'єкт не може трактуватися як функція. Функції не можна призначати першокласно; натомість, щоб змінити їх, потрібно викликати функцію в об'єкті контейнера.

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
Ви сильно розгублені. Об'єкти першого класу присвоюються за призначенням:, а x = yне за викликом self.class.send(:define_method, :func, method(:func2)). Ваш "контрприклад" показує, як функції Рубі не першокласні. Якщо ви не згодні, не соромтеся розмістити власну відповідь; не вкладай мою плутанину в мою.
Гленн Мейнард

7
Речі, визначені def ... endв рубіні, не є функціями. Це методи (як ви їх визначили Kernel). Методи можуть бути незв'язаними (використовуючи #methodметод), які потім є об'єктами. Найбільш близьким до функцій рубіну є Procекземпляри, які також є об'єктами, і їх можна передавати навколо або викликати. Він також має спеціальний синтаксис для передачі єдиного зворотного дзвінка Procметоду, про що Джон Фемінелла обговорює у своїй відповіді .
чемпіон

4
@Glenn: Я розумію, що ви говорите, але я б посперечався з твердженням, що переглядання функцій Рубі - методи - це окреме смислове поняття. Якщо ви хочете грати у гру з визначеннями, найбільш імперативним кодом є процедури, а не функції. Я не намагаюся бути складним, я просто вважаю, що визначення та точність є важливими. Я погоджусь, що маніпулювати UnboundMethodнабором може бути ПДФО, тхо.
чемпіон

5
@Glenn: Краса в очах глядачів. Тим не менш, методи - це об'єкти першокласного рівня, виконуючи визначення (в даному випадку я маю на увазі визначення Вікіпедії). Можливо, у вас є якесь інше визначення першокласного? Чи потрібна їм платинова картка частого літака, щоб натрапити на першокласну?
упередження

4
@Glenn Перегляньте розділ SO FAQ "Інші люди можуть редагувати мої речі ?!" - це спільнота Wiki.
упередженість

26

Зрештою, всі відповіді будуть суб'єктивними на певному рівні, і відповіді, розміщені до цих пір, доволі доказують, що ви не можете вказати ні на одну особливість, яку не можна зробити в іншій мові не менш приємним (якщо не подібним) способом , оскільки обидві мови дуже стислі та виразні.

Мені подобається синтаксис Python. Однак вам доведеться копати трохи глибше синтаксису, щоб знайти справжню красу Рубі. У консистенції Рубі є зенітна краса. Хоча жоден банальний приклад не може повністю пояснити це, я спробую придумати один тут, щоб пояснити, що я маю на увазі.

Переверніть слова в цьому рядку:

sentence = "backwards is sentence This"

Коли ви думаєте, як би це зробити, ви зробите наступне:

  1. Розділіть речення на слова
  2. Переверніть слова
  3. Повторно з'єднайте слова назад у рядок

У Ruby ви зробите це:

sentence.split.reverse.join ' '

Точно так, як ви думаєте про це, у тій же послідовності один метод викликає інший.

У python це виглядало б приблизно так:

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

Це не важко зрозуміти, але це не зовсім однаковий потік. Тема (речення) закопується посередині. Операції - це поєднання функцій та об'єктних методів. Це тривіальний приклад, але ви знайдете безліч різних прикладів, коли реально працювати з Робі та розуміти її, особливо над нетривіальними завданнями.


1
Я згоден. Рубі, здається, тече природно, коли я це пишу, тому "дзенка" - це хороший термін.
Олов'яний чоловік

18

У Python менталітет "ми всі тут дорослі". Таким чином, ви побачите, що у Ruby є такі речі, як константи, тоді як у Python немає (хоча константи Ruby викликають лише попередження). Спосіб мислення Python полягає в тому, що якщо ви хочете зробити щось постійне, вам слід ставити назви змінних у всі шапки, а не змінювати його.

Наприклад, Ruby:

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

Пітон:

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

19
Ха .. це просто нагадує мені, що принаймні в python 2. * ви змогли зробити "True, False = False, True" ... Я вважаю, що вони правильно виправили це в python 3.0 ... це щось, що вам слід не можна робити це.
Том

11
Особисто мені подобаються чіткі вказівки, які виконуються мовою, тому що це робить весь код, написаний цією мовою, послідовним. Це змушує вас слідувати вказівкам, і розробники, які читають ваш код, можуть з першого погляду розповісти, що до чого. У той час як більшість кодерів Python використовують той самий загальний "стиль", я помітив досить великі невідповідності, які були б неможливі в Ruby.
Саша Чедигов

8
@bias - Я не впевнений, чому ти проти мене посилаєшся. Ця відповідь не погоджується чи не погоджується із способом виконання пітонів. Це просто констатація факту.
Джейсон Бейкер

13
@Jason "ми всі дорослі тут" - це твердження факту? Я б хотів назвати цю думку, обгорнуту якоюсь особливістю, звідси і голосування проти.
упередженість

7
@bias - Казати, що "ми всі дорослі тут", не вважалося незначним. Це неофіційний девіз Python, який, на мою думку, найкраще пояснюється тут: mail.python.org/pipermail/tutor/2003-O жовтня/025932.html
Еван Портер

18

Ви можете імпортувати лише певні функції з модуля в Python. У Ruby ви імпортуєте весь список методів. Ви можете "імпортувати" їх у Рубі, але справа не в тому.

Редагувати:

візьмемо цей модуль Ruby:


module Whatever
  def method1
  end

  def method2
  end
end

якщо ви включите його у свій код:


include Whatever

ви побачите, що і метод1, і метод2 були додані до вашого простору імен. Ви не можете імпортувати лише метод1 . Ви або імпортуєте їх обидва, або взагалі не імпортуєте. У Python ви можете імпортувати лише обрані вами методи. Якщо це має назву, можливо, це називалося б селективним імпортом?


2
О, так! Python любить простори імен. Чи не так у Рубі? Ви не import bla; bla.foo()в Рубі?
Леннарт Регебро

2
Ви можете імпортувати лише функцію a, а не всі функції всередині. Якщо, наприклад, ви включаєте модуль Ruby, який декларує 3 нестатичні функції, ви включаєте їх у ваше простір імен. У python вам доведеться писати з імпорту модуля *.
Гео

6
Чи це не призводить до великого захаращення простору імен?
Леннарт Регебро

1
Я думаю, що так і є. Ось що я ненавиджу модулі Ruby.
Гео

8
У Ruby насправді немає модульної системи в тому ж сенсі, що і python. вимагають роботи в основному як текстове включення з деякими чеками на включення дубліката. Ви можете (ab) використовувати модулі як простори імен, але moduleнасправді є дещо помилковим. Модулі в основному є класами new, allocateметодами. Вони найкраще працюють як спосіб спільного використання коду на основі класу / об’єкта, а не як механізм розподілу бібліотек або обмін кодом між програмами.
Логан Капальдо

16

З веб-сайту Ruby :

Подібність як з Python, у Ruby, ...

  • Існує інтерактивний запит (називається irb).
  • Ви можете читати документи в командному рядку (командою ri замість pydoc).
  • Не існує спеціальних лінійних термінаторів (крім звичайної нової лінії).
  • Рядкові літерали можуть охоплювати декілька рядків, таких як рядки з потрійним цитуванням Python.
  • Дужки призначені для списків, а дужки - для диктів (які в Ruby називають хешами).
  • Масиви працюють однаково (додавання їх робить один довгий масив, але складання їх таким чином a3 = [ a1, a2 ]дає вам масив масивів).
  • Об'єкти сильно та динамічно набираються.
  • Все є об'єктом, а змінні - це лише посилання на об'єкти.
  • Хоча ключові слова дещо відрізняються, винятки працюють приблизно однаково.
  • У вас є вбудовані інструменти doc (Рубі називається rdoc).

Відмінності на відміну від Python, у Ruby, ...

  • Струни змінні.
  • Ви можете робити константи (змінні, значення яких ви не збираєтесь змінювати).
  • Існують деякі примусові умовні випадки (наприклад, імена класів починаються з великої літери, змінні починаються з малої літери).
  • Є лише один вид контейнера списку (масив), і він може змінюватися.
  • Джерела з подвійним котируванням дозволяють виконувати послідовності виходу (наприклад, \ t) та спеціальний синтаксис "заміщення виразів" (який дозволяє вставляти результати виразів Ruby безпосередньо в інші рядки без необхідності "додавати" + "рядки" + "разом") . Рядки з цитуванням, що котируються на зразок, схожі на r-сирі рядки Python.
  • Не існує класів «новий стиль» та «старий стиль». Просто один вид.
  • Ви ніколи не отримуєте прямого доступу до атрибутів. З Ruby - це все виклики методу.
  • Дужки для викликів методів зазвичай не є обов'язковими.
  • Є загальнодоступні, приватні та захищені, щоб запровадити доступ замість Python _voluntary_ underscore __convention__ .
  • "Міксин" використовується замість багаторазового успадкування.
  • Ви можете додавати або змінювати методи вбудованих класів. Обидві мови дозволяють вам відкривати та змінювати класи в будь-якій точці, але Python не дозволяє модифікувати вбудовані модулі - Ruby цього не робить.
  • Ви отримали правду та хибність замість True та False (а нуль замість None).
  • Якщо перевіряється на істинність, лише хибне та нульове значення оцінюються як хибне значення. Все інше вірно (включаючи 0, 0,0, "" і []).
  • Це elsif замість elif.
  • Це потрібно замість імпорту. Інакше, однак, використання те саме.
  • Зазвичай в стилі коментарі до рядків над речами (замість докерів під ними) використовуються для створення документів.
  • Існує ряд ярликів, які, хоча і дають більше запам’ятати, швидко засвоюються. Вони, як правило, роблять Рубі веселою і дуже продуктивною.

2
"Це потрібно замість імпорту. В іншому випадку, використання є таким же." Здається, це абсолютно неточно.
Гленямін

У Ruby також є набори, які люди рідко використовують, але вони вбудовані. Тому я можу сказати, stuff_in_backpack = Set.new; stuff_in_backpack << "комп'ютер"; stuff_in_backpack << "взуття"; # і набір буде містити всі значення, не гарантуючи замовлення.
зачаян

12

Те, що Рубі має над Python, - це її мови сценаріїв. Мова сценаріїв у цьому контексті означає використовувати "клей-код" у скриптах оболонки та загальній маніпуляції текстом.

Вони в основному поділяються з Perl. Першокласні вбудовані регулярні вирази, $ -Variables, корисні параметри командного рядка, такі як Perl (-a, -e) тощо.

Разом із своїм коротким, але експресивним синтаксисом він ідеально підходить для подібних завдань.

Python для мене - це більше динамічно набрана ділова мова, яку дуже легко вивчити та має чіткий синтаксис. Не такий "крутий", як Рубі, але акуратний. Те, що Python має для мене над Рубі, - це велика кількість прив'язок для інших ліб. Прив’язки до Qt та інших графічних інтерфейсів GUI, багатьох бібліотек підтримки ігор та та та та. У Рубі набагато менше. Хоча багато використовувані прив’язки, наприклад, до Баз даних хорошої якості, я виявив, що нішеві вкладки краще підтримуються в Python, навіть якщо для тієї ж бібліотеки є також прив'язка Ruby.

Отже, я б сказав, що обидві мови мають своє використання, і саме це завдання визначає, яку саме використовувати. І те й інше досить просто навчитися. Я використовую їх поруч. Ruby для сценаріїв і Python для автономних додатків.


1
Питання від того, хто ще не знає Рубі: Що ви маєте на увазі під "$ -Variables"? Ви маєте на увазі глобальні змінні? Якщо так, то в Python змінна, визначена в модулі поза класом або функцією, є глобальною. Якщо ні - в чому відмінність?
Anon

1
Anon: якщо ви декларуєте змінну $ в будь-якому місці коду, вона є глобальною через префікса. Таким чином, не важливо, де він визначений, він завжди глобальний, і завжди відомий як такий.
Роберт К

8
Не зовсім, насправді я мав на увазі заздалегідь визначені змінні, такі як $ _, $ 1 тощо. Вони автоматично заповнені значеннями рубіном. $ _ - це останній прочитаний рядок. $ 1, $ 2 і т.д. - це відповідність регулярних виразів з останнього матчу. Тут ви знайдете повний список: zenspider.com/Languages/Ruby/QuickRef.html#17 В основному це злом для компактних сценаріїв. Ви можете отримувати всю інформацію і через дзвінки API, але з використанням змінних $ це ще коротше. Такий тип змінних просто не підходить стилю Python, вони навмисно їх покинули.
haffax

Дякуємо за посилання zenspider - шукали щось подібне для швидкого (позаурочного) відчуття Рубі.
Anon

12

Я не думаю, що "у Рубі є X, а в Python немає, у Python Y, а у Ruby немає" - це найкорисніший спосіб поглянути на це. Вони досить схожі мови, з багатьма спільними здібностями.

Значною мірою різниця полягає в тому, що мова робить елегантною та читаною. Для використання прикладу, який ви вигадали, теоретично обидва мають лямбда, але програмісти Python, як правило, уникають їх, і конструкції, виготовлені з їх допомогою, не виглядають ніде поблизу настільки читабельними чи ідіоматичними, як у Ruby. Таким чином , в Python, хороший програміст захоче взяти інший шлях до вирішення проблеми , ніж він був би в Ruby, просто тому , що на самому ділі це кращий спосіб зробити це.


5
Я погоджуюся, що лямбдахи мають обмежений обсяг і не є корисними у багатьох випадках. Однак я не думаю, що справедливо говорити, що програмісти Python уникають їх, як чума.
Джейсон Бейкер

1
Я згоден, що лямбда використовуються часто з Python - як, наприклад, карта, фільтр, зменшення. Велика різниця, здається, полягає в тому, що лямбди Python обмежені виразами, тоді як блоки Ruby можуть бути багаторядковими і включати оператори. Моє загальне враження від того, що я читав про Ruby, полягає в тому, що ця функція, зокрема, змушує рубістів скористатися підходом DSL, тоді як Pythonistas, швидше за все, створюють API. Моя інформація про Рубі все ще дуже поверхнева.
Anon

2
@Lennart: Багаторядні блоки весь час використовуються в Ruby - фактично частіше, ніж я бачу лямбди, що використовуються в ідіоматичному коді Python. Для поширеного прикладу див. Info.michael-simons.eu/2007/08/06/rails-respo_to-method .
Чак

1
@Lennart: Ні, вона не використовує врожайність. (Вихід Рубі зовсім не відрізняється від Python - він не повертає генератор.) Писати це не було б сенсом for format in respond_to(). respond_toМетод нічого значущого; не повертається - він просто реагує на поточний запит HTTP. doВ respond_to doпочатку блоку. У цьому блоці ми розмовляємо з тимчасовим об’єктом (позначеним formatу цьому прикладі), який реалізує дуже базовий DSL для відповіді на HTTP-запит.
Чак

3
Чи можете ви "змішати безліч" проти генератора і миттєво отримати 30 нових і чудових ітераторів? Вам потрібно вивчити мову в цілому, перш ніж зрозуміти, чому блоки / Прокси великі.
упередженість

12

Я хотів би запропонувати варіант оригінального запитання: "Що таке Рубі, у якого Python не має, і навпаки?" який визнає невтішну відповідь: "Ну, що ти можеш зробити з Ruby чи Python, що неможливо зробити в Intercal?" Нічого на цьому рівні, тому що Пітон і Рубі - це частина величезної королівської сім'ї, яка сидить на троні наближення Тюрінга.

А як щодо цього:

Що можна зробити витончено і добре в Python, що не можна зробити в Ruby з такою красою і гарною технікою, або навпаки?

Це може бути набагато цікавіше, ніж просто порівняння характеристик.


коментар у кращому випадку. все-таки мій +1
nawfal

11

У Python є явний вбудований синтаксис для списків-компресії та генераторів, тоді як у Ruby ви використовуєте блоки карти та коду.

Порівняйте

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

до

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

як розуміння списку не є простим Python ? і в Python є функція карти.
SilentGhost

Але в Рубі немає синтаксису розуміння списку
Даріо

Python: res = map (лямбда x: x * x, діапазон (1,10))
GogaRieger

Пітон:res=map(2 .__rpow__, range(1,10))
Джон Ла Руй

11

"Змінні, які починаються з великої літери, стають постійними і не можуть бути змінені"

Неправильно. Вони можуть.

Ви отримуєте попередження лише тоді, коли це зробите.


2
Якщо мова дає вам попередження про операцію, я вважаю, що ви дуже добре можете вважати операцію "неможливою". Все інше - це безумство.
porgarmingduod

11

Дещо більше з боку інфраструктури:

  • Python має набагато кращу інтеграцію з C ++ (через такі речі, як Boost.Python , SIP та Py ++ ), ніж Ruby, де параметри, схоже, є або записувати безпосередньо проти інтерпретатора Ruby API (що, звичайно, можна зробити і з Python) але в обох випадках це низький рівень, стомлюваність і схильність до помилок) або використовувати SWIG (що, хоча це працює і безумовно, чудово, якщо ви хочете підтримувати багато мов, не так добре, як Boost.Python або SIP, якщо ви спеціально хочете зв’язати C ++).

  • У Python є кілька середовищ веб-додатків (Django, Pylons / Turbogears, web.py, напевно, щонайменше півдесятка інших), тоді як у Ruby (ефективно) є одне: Rails. (Інші веб-рамки Ruby існують, але, здавалося б, важко отримати тягу до Rails). Добрий чи поганий цей аспект? Важко сказати, і, ймовірно, досить суб’єктивно; Я легко можу уявити аргументи, що ситуація з Python краща і ситуація з Ruby краща.

  • У культурному плані спільноти Python та Ruby здаються дещо різними, але я можу натякнути на це лише тому, що у мене немає такого досвіду взаємодії з спільнотою Ruby. Я додаю це переважно в надії, що той, хто має великий досвід роботи з обома, може посилити (або відхилити) це твердження.


7
Ваш другий пункт в кращому випадку дезінформований. Спершу слід поглянути на Rack and Sinatra
Макс Огден

6
Я чітко зазначаю, що існують інші стеки Rails; Я просто не думаю, що ніхто їх фактично не використовує. Перевірка Синатри та Рака точно не змінила цього враження. Ви дійсно думаєте, скажімо, Сінатра (всього 94 ТА питання), або Кемпінг (2 запитання загалом), чи хтось із інших, насправді має реальну базу користувачів / спільноту? Наскільки я можу сказати, більшість з них навіть не мають реальних користувачів. Порівняйте з цим питанням Django (4K +) або Rails (7K +), або навіть web.py.
Джек Ллойд

1
Синатра насправді досить популярна для різних легких завдань завдяки DSL. Його просто менше використовують, тому що MVC Rail надає більше. Рейки фактично побудовані на стійці - саме це робить Phusion Passenger можливим.
альтернатива

11

Безсоромно копіювати / вставляти з: Відповідь Алекса Мартеллі на тему " Що краще про Ruby ніж Python " із списку розсилки comp.lang.python .

18 серпня 2003 р., 10:50. Ерік Макс Френсіс написав:

"Брендон Дж. Ван Кожен" писав:

Що краще в Ruby ніж Python? Я впевнений, що щось є. Що це?

Чи не було б набагато більше сенсу запитати у людей Рубі, а не людей з Python?

Можливо, а може і не, залежно від своїх цілей - наприклад, якщо цілі включають "соціологічне дослідження" спільноти Python, то ставлення питань до цієї спільноти, швидше за все, виявить більше розкриття інформації про неї, ніж їх розміщення в іншому місці :-).

Особисто я із задоволенням скористався можливістю переглядати одноденний підручник Рубі Дейва Томаса нарешті OSCON. Внизу тонкого шпону різниць синтаксису я знаходжу Ruby та Python напрочуд схожими - якби я обчислював мінімальну розтягнуту ялинку серед майже будь-якого набору мов, я впевнений, що Python та Ruby були б першими двома листами, що об'єдналися в проміжний вузол :-).

Звичайно, мені в Рубі втомлюється вводити дурний "кінець" в кінці кожного блоку (а не просто розкручувати) - але тоді я отримую, щоб уникнути набору однаково нерозумно ":" чого вимагає Python у початок кожного блоку, так що майже мити :-). Інші відмінності в синтаксисі, такі як "@foo" проти "self.foo", або вища значимість випадку у Ruby vs Python, для мене насправді не мають жодного значення.

Інші, без сумніву, ґрунтують свій вибір мови програмування саме на таких питаннях, і вони породжують найгарячіші дебати - але, на мою думку, це лише приклад одного із законів Паркінсона в дії (сума для дискусій з певної проблеми обернено пропорційна питанням випуску фактичне значення).

Редагувати (від 19.06.2010 11:45): це також відоме як "малювання на велосипеді" (або, коротше кажучи, "велосипед", - знову ж таки, посилання на Northcote Parkinson, який давав "дебати" про те, яким кольором намалювати велосипед », як типовий приклад« гарячих дебатів на тривіальні теми ». (закінчення редагування).

Одна різниця синтаксису, яку я вважаю важливою, і на користь Python - але інші люди, без сумніву, думають просто навпаки - це "як ви називаєте функцію, яка не приймає ніяких параметрів". У Python (як у C) для виклику функції ви завжди застосовуєте "оператор виклику" - кінцеві дужки безпосередньо після об'єкта, який ви викликаєте (всередині цих кінцевих дужок йдуть аргументи, які ви передаєте під час виклику - якщо ви не передаєте аргументів, тоді дужки порожні). Це залишає лише згадку про будь-якеоб'єкт, без участі жодного оператора, що означає лише посилання на об'єкт - у будь-якому контексті, без особливих випадків, винятків, спеціальних правил тощо. У Ruby (як у Pascal) для виклику функції З аргументами ви передаєте аргументи (як правило, в дужках, хоча це не завжди), АЛЕ якщо функція не бере аргументів, то просто згадування про функцію неявно називає її. Це може виправдати очікування багатьох людей (принаймні, без сумніву, тих, чий єдиний попередній досвід програмування був з Pascal або іншими мовами з подібними "неявними дзвінками", такими як Visual Basic) - але для мене це означає проста згадка про об'єкт може ВСІМО означати посилання на об'єкт АБО виклик до об'єкта залежно від типу об'єкта - і в тих випадках, коли я можу ' не отримую посилання на об’єкт, просто згадуючи його, мені потрібно буде використовувати явне "дайте мені посилання на це, НЕ називайте!" операторів, які не потрібні інакше. Я відчуваю, що це впливає на "першокласність" функцій (або методів чи інших об'єктів, що дзвоняться) та можливість плавного обміну об'єктами. Тому для мене ця специфічна синтаксична різниця є серйозною чорною позначкою щодо Рубі - але я розумію, чому інші поступатимуться інакше, хоча я навряд чи можу з ними більше погодитися :-). функцій (або методів, або інших об'єктів, що дзвоняться) та можливості плавного обміну об'єктами. Тому для мене ця специфічна синтаксична різниця є серйозною чорною позначкою щодо Рубі - але я розумію, чому інші поступатимуться інакше, хоча я навряд чи можу з ними більше погодитися :-). функцій (або методів, або інших об'єктів, що дзвоняться) та можливості плавного обміну об'єктами. Тому для мене ця специфічна синтаксична різниця є серйозною чорною позначкою щодо Рубі - але я розумію, чому інші поступатимуться інакше, хоча я навряд чи можу з ними більше погодитися :-).

Нижче синтаксису ми стикаємося з деякими важливими відмінностями елементарної семантики - наприклад, рядки в Ruby - це змінні об'єкти (як у C ++), тоді як у Python вони не змінюються (як у Java, або я вважаю, C #). Знову ж таки, люди, які судять передусім за тим, що вони вже знайомі, можуть подумати, що це є плюсом для Рубі (якщо, звичайно, вони не знайомі з Java або C #, звичайно :-). Мені здається, непорушні рядки - це відмінна ідея (і я не здивований, що Java, незалежно, я думаю, переосмислила цю ідею, яка вже була в Python), хоча я не заперечувала б і з типом "змінний буфер струнів" (і в ідеалі - з кращою зручністю у використанні, ніж власні "рядкові буфери" Java); і я не висловлюю це судження через знайомство - перед вивченням Java, всі дані незмінні, усі мови, які я знав, мали мінливі рядки - але коли я вперше побачив ідею незмінної струни на Java (яку я навчився добре, перш ніж я пізнав Python), це одразу вразило мене чудовим, дуже гарним для референтна семантика мови програмування вищого рівня (на відміну від значення-семантики, яка найкраще підходить для мов, ближчих до машини та далі від додатків, таких як C) із рядками як першокласного, вбудованого (і досить вирішальний) тип даних.

У елементарної семантики у Рубі є деякі переваги - наприклад, вилучення «списків проти кортежів» Питона надзвичайно тонкою відмінністю. Але в основному оцінка (як я вважаю, простота, великий плюс і тонкі, розумні розрізнення, помітний мінус) проти Рубі (наприклад, з закритими і напіввідкритими інтервалами, з позначеннями a..b і .. .b [хтось хоче стверджувати, що очевидно, що є? -)], нерозумно - ІМХО, звичайно!). Знову ж таки, люди, які вважають, що в основі мови багато подібних, але тонко різних речей, ПЛЮС, а не МІНУС, звичайно, будуть рахувати це "навпаки" від того, як я їх рахую :-).

Нехай вас не вводить в оману ці порівняння думок, що ці дві мови є дужеінший, зауважте. Вони ні. Але якщо мене попросять порівняти "capelli d'angelo" з "spaghettini", після того, як зазначив, що ці два види макаронних виробів якраз не відрізняються ні від кого і є взаємозамінними в будь-якій страві, яку ви хочете приготувати, я б тоді неминуче мав перейти до мікроскопічного дослідження того, як непомітно відрізняються довжини і діаметри, як кінці пасм звужуються в одному випадку, а не в іншому, і так далі - спробувати і пояснити, чому я особисто вважаю за краще "ангело, як макаронні вироби в будь-якому вигляді бульйону, але вважає за краще спагеттіні, як макаронні вироби, щоб їхати з підходящими соусами для таких довгих тонких макаронних форм (оливкова олія, фарш з часнику, червоний перець з червоного перцю і дрібно натертий анчоус, наприклад - але якщо ви нарізали часник і перець замість того, щоб їх подрібнювати, то вам слід вибирати тіло спагетті, а не тоншу випаровуваність спагетіні, і було б радимо відмовитися від овочів і замість цього додати трохи свіжого весняного базиліка [ чи навіть - я єретик ...! - легка м'ята ...] листя - в самий останній момент перед подачею страви). Ой, вибачте, це свідчить про те, що я подорожую за кордон і певний час не маю макаронних виробів. Але аналогія все-таки досить хороша! -) - легка м'ята ...] листя - в самий останній момент перед подачею страви). Ой, вибачте, це свідчить про те, що я подорожую за кордон і певний час не маю макаронних виробів. Але аналогія все-таки досить хороша! -) - легка м'ята ...] листя - в самий останній момент перед подачею страви). Ой, вибачте, це свідчить про те, що я подорожую за кордон і певний час не маю макаронних виробів. Але аналогія все-таки досить хороша! -)

Отже, повертаючись до Python та Ruby, ми переходимо до двох великих функцій (з точки зору належної мови - залишення бібліотек та інших важливих допоміжних допоміжних засобів, таких як інструменти та середовища, як вставляти / розширювати кожну мову тощо, тощо) з це поки що - вони все одно не застосовуватимуться до всіх ВПРОВАДЖЕНЬ кожної мови, наприклад, Jython vs Classic Python є двома реалізаціями мови Python!):

  1. Ітератори та кодові блоки Ruby проти ітераторів та генераторів Python;

  2. ВСЬОГО Рубі, нестримна "динамічність", включаючи можливість
    "відкрити" будь-який існуючий клас, включаючи всі вбудовані, та змінити свою поведінку під час виконання - проти величезної, але обмеженої динаміки Python , яка ніколи не змінює поведінку існуючих вбудовані класи та їх екземпляри.

Особисто я вважаю 1 промиванням (відмінності настільки глибокі, що я міг легко бачити людей, що ненавидять або підходити, і повертатись до іншого, але на моїх особистих масштабах плюси і мінуси майже рівномірно); і 2 важливе питання - той, що робить Ruby набагато більш придатним для "майстерності", але Питон не менш придатний для використання у великих виробничих додатках. Це певним чином смішно, тому що обидві мови настільки динамічніші, ніж більшість інших, що врешті-решт ключова різниця між ними від моєї POV повинна залежати від цього - що Рубі "в цьому плані" переходить до одинадцяти "(посилання тут, звичайно, "Спинальний дотик". У Рубі,Я можу це зробити ! Тобто я можу динамічно змінити вбудований рядок рядків, щоб a = "Hello World" b = "привіт світ", якщо a == b друкується "рівний! \ N" інакше друкується "інше! \ N" кінець WILL print " рівний ". У python немає способу зробити це. Для метапрограмування, реалізації експериментальних рамок тощо, ця дивовижна динамічна здатність Рубі надзвичайно надзвичайна привабливий. АЛЕ - якщо ми говоримо про великі програми, розроблені багатьма людьми та підтримувані ще більше, включаючи всі види бібліотек з різних джерел, і потрібно запускати у виробництво на клієнтських сайтах ... ну, я НЕ ХОЧУ мова, ЯКА ЦІ ТИНА динамічна, дуже дякую. Я ненавиджу саму ідею, що деякі бібліотеки мимоволі ламають інші непов'язані між собою ті, що покладаються на те, що ці рядки відрізняються - ось такий тип "глибокого та глибоко прихованого" каналу "між фрагментами коду, який LOOK відокремлює, і ПОТРІБНО бути окремим, що заклинає смерть у широкомасштабне програмування. Дозволяючи будь-якому модулю впливати на поведінку будь-якого іншого "приховано", можливість мутувати семантику вбудованих типів є лише ідеєю BAD для програмування виробничих прикладних програм,

Якби мені довелося використовувати Ruby для такої великої програми, я б спробував покластися на обмеження стилю кодування, безліч тестів (щоб їх повторювати, коли що-небудь змінилося - навіть те, що повинно бути абсолютно не пов’язаним ...) тощо. заборонити використання цієї мовної функції. Але НЕ, маючи цю функцію в першу чергу, ще краще, на мій погляд - так само, як сам Python був би ще кращою мовою для програмування прикладних програм, якби певна кількість вбудованих модулів могла бути "прибитими", тому я знаю , наприклад, len ("ciao") - це 4 (замість того, щоб турбуватися підсвідомо про те, чи хтось змінив прив'язку імені 'len' у вбудованому модулі ...). Я сподіваюся, що врешті-решт Python "прибити" свої вбудовані модулі.

Але проблема незначна, оскільки перезавантаження вбудованих модулів є досить застарілою, а також рідкісною практикою в Python. У Ruby це вважає мене головним - так само, як занадто потужні макро-засоби інших мов (як, скажімо, Ділан) представляють подібні ризики на мою власну думку (я сподіваюся, що Python ніколи не отримає такої потужної макросистеми, ні Незважаючи на повагу "дозволити людям визначати свої власні доменні маленькі мови, вбудовані в саму мову" - це, IMHO, погіршить чудову корисність Python для програмування прикладних програм, представивши "привабливу неприємність" потенційному майстру, який ховається у серці кожного програміста ...).

Олексій


9

Деякі інші з:

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

(Якщо я неправильно пояснив що-небудь або щось із цього змінилося на стороні Ruby з моменту оновлення цієї сторінки, хтось може сміливо редагувати ...)

Струни змінюються в Ruby, а не в Python (де нові рядки створюються за допомогою "змін").

У Рубі є деякі примусові угоди, у Python цього немає.

У Python є як списки, так і кортежі (незмінні списки). У Ruby є масиви, відповідні спискам Python, але жодного незмінного їх варіанту.

У Python ви можете безпосередньо отримати доступ до атрибутів об'єкта. У Ruby це завжди за допомогою методів.

У Ruby дужки для викликів методів зазвичай є необов’язковими, але не в Python.

Ruby має публічний, приватний та захищений, щоб забезпечити доступ, замість того, щоб Python використовував підкреслення та назву mangling.

Пітон має багаторазове успадкування. У Рубі є "міксини".

І ще одне дуже релевантне посилання:

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

Що, зокрема, посилається на ще один хороший Алекс Мартеллі , який також опублікував багато чудових матеріалів тут на SO:

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


1
У рубіні ви можете просто заморозити свій масив, щоб змінити його на щось незмінне
user163365

Відмінний пост Алекса Мартеллі :)
Skilldrick

8

Я не впевнений у цьому, тому спочатку додаю це як відповідь.

Python розглядає незв'язані методи як функції

Це означає, що ви можете викликати метод як подобається, так theobject.themethod()і за допомогою TheClass.themethod(anobject).

Редагувати: Хоча різниця між методами та функціями невелика в Python, а неіснуюча в Python 3, вона також не існує в Ruby, просто тому, що у Ruby немає функцій. Визначаючи функції, ви фактично визначаєте методи на Object.

Але ви все одно не можете прийняти метод одного класу і викликати його як функцію, вам доведеться повторно пов’язати його з об'єктом, на який потрібно зателефонувати, що набагато більше затуманило.


У Ruby взагалі немає функцій. Це TheClass.instance_method(:themethod).bind(anobject).callбуло б рівнозначним рубіном.
Логан Капальдо

Ой. Отже, є якийсь основний клас магії, коли ви визначаєте функцію, яка не є в явному класі?
Леннарт Регебро

Так, методи, визначені на верхньому рівні, є приватними методами Object.
Логан Капальдо

1
FWIW, схоже, що в Python функції та методи насправді одного типу, а їхня інша поведінка походить від дескрипторів: users.rcn.com/python/download/… .
Бастієн Леонард

1
Але якщо прив’язати його до предмета, то це не є незв'язаним. Дух. :-) І вони теж саме в Python. Просто Рубі насправді не має функцій. А це означає, що моє твердження правильне. Ви можете назвати незв'язаний метод так, як якщо б це була функція в Python. І це насправді корисно, це означає, наприклад, що ви можете викликати метод, визначений для класу, на об'єкті, який не має цього класу, що іноді є корисним.
Леннарт Регебро

7

Я хотів би зазначити API дескриптора Python, який дозволяє налаштувати "зв'язок" об'єкта до атрибута. Примітно також, що в Python можна безкоштовно реалізувати альтернативний протокол через переосмислення стандартного за замовчуванням, що задається за допомогою програми за замовчуванням __getattribute__. Дозвольте розповісти детальніше про вищезазначене. Дескриптори регулярні заняття з __get__, __set__і / або __delete__методів. Коли перекладач стикається з чимось подібним anObj.anAttr, виконується наступне:

  • __getattribute__anObjвикликається метод
  • __getattribute__ отримує об’єкт anAttr з класу dict
  • він перевіряє, чи є об'єкт abAttr __get__, __set__або __delete__об'єкти, що викликаються
  • контекст (тобто об'єкт або клас абонента, і значення, замість останнього, якщо у нас є сетер) передається об'єкту, що викликається
  • результат повертається.

Як було сказано, це поведінка за замовчуванням. Один вільний змінити протокол шляхом повторної реалізації __getattribute__.

Ця техніка набагато потужніша, ніж декоратори.


6

Ruby створив підтримку продовження, використовуючи callcc.

Отже, ви можете реалізовувати круті речі, такі як amb-operator


Я б хотів, щоб я зрозумів callcc. Чи можете ви дати більш приземлений сценарій застосування, ніж неоднозначний оператор Маккарті, щоб оцінити його достоїнства? Я маю на увазі щось із реального світу, не такі прискіпливі речі CS ?!
ThomasH

"Funky CS речі" справжні. Знайдіть трохи часу, щоб дізнатися: intertwingly.net/blog/2005/04/13/Continuations-for-Curmudgeons
Стівен Ейлерт


5

У Python є docstrings, а рубін не має ... Або якщо цього немає, вони не доступні так просто, як у python.

Пс. Якщо я помиляюся, досить, будь ласка, залиште приклад? У мене є вирішення того, що я міг би маніпулювати в класи досить легко, але я хотів би мати docstring своєрідну функцію "рідним способом".


3
не має docstring, але має RDoc. Так що так, не настільки легкодоступні, але не на 100% приховані.
Омар Куреші

Рубі не використовує docstrings. Це робить документацію по-іншому.
Чак

1
Омар: так, я знаю про rdoc, але afaik, вони не такі "доступні", як доктринги пітона. Наприклад, якщо у мене є клас, і я хочу вивести документацію rdoc з класу, це його досить обтяжена робота. Що я зробив, це те, що я генерую документацію ri, яку намагаюся оновити2, а потім отримувати цю інформацію. Однозначно не до того ж рівня, що й
доктрини

Документи можна використовувати для надання докстестів. Чи є щось подібне для Рубі?
Леннарт Регебро

2
Так, це називається "Ruby Doctest". Що стосується doctests, то все, що насправді має значення, - це те, що ви десь маєте читану документацію, яка включає фрагменти тестового коду - це не має значення, чи є це в docstring чи в коментарі.
Чак

5

У Ruby є рядок за рядком через вхідні файли (прапор '-n') з командного рядка, щоб його можна було використовувати як AWK. Це одноразовий Ruby:

ruby -ne 'END {puts $.}'

буде рахувати рядки, як одноколірний AWK:

awk 'END{print NR}'

Рубі отримує це завдяки Perl, який взяв це з AWK як спосіб отримання сидсадмінів на борту з Perl без необхідності змінювати спосіб, яким вони займаються.


1
Я хотів би додати, що підтримка командного рядка Python досить слабка. Крім відсутнього автоматичного циклу, ви не можете помістити пару висловлювань в один рядок і передати його як аргумент командного рядка з одним рядком інтерпретатору. Принаймні мені цього не вдалося.
ThomasH

Звичайно, ви можете. Але вам (як і будь-якій мові otehr) потрібно вкласти це в лапки.
Леннарт Регебро

Python не використовується для використання в командному рядку, оскільки ви повинні бути чіткими щодо деяких речей (наприклад, sys.stdin), якщо ви хочете використовувати його таким чиномpython -c "import sys; print len(list(sys.stdin))"
u0b34a0f6ae

5

У Ruby є сигіли та гілочки, Python - ні.

Редагувати : І одна дуже важлива річ, яку я забув (зрештою, попередня була просто трохи розпалити :-p):

У Python є компілятор JIT ( Psyco ), помітно мова нижчого рівня для запису швидшого коду ( Pyrex ) та можливість додавати вбудований код C ++ ( Weave ).


Щоправда, але це просто синтаксис.
Леннарт Регебро

6
Ну, якщо ви хочете піти цією дорогою: обидва - Тюрінг-завершений. Все інше - це лише синтаксис.
Йорг W Міттаг

Так і різниця в синтаксисі importtax ;-)
fortran

1
Як це важливо, якщо ви пишете @foo або self.foo?
Леннарт Регебро

1
@ Йорг: Добре, тоді називайте це щось інше, ніж «синтаксис». Справа в тому, що @foo і self.foo роблять те саме, це насправді не функціонал, який має Ruby, а Python не має.
Леннарт Регебро

5

Мій пітон іржавий, тому деякі з них можуть бути в python, і я просто не пам'ятаю / ніколи не дізнався, але ось перші декілька, про які я подумав:

Пробіл

Рубін обробляє пробіл абсолютно іншим. Для початку вам нічого не потрібно відступати (це означає, що це не має значення, якщо ви використовуєте 4 пробіли або 1 вкладку). Він також продовжує розумне продовження рядків, тому дійсне наступне:

def foo(bar,
        cow)

В основному, якщо ви закінчите з оператором, він з’ясує, що відбувається.

Міксини

У Ruby є міксин, який може поширювати екземпляри замість повних класів:

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

Перелічує

Я не впевнений, чи це те саме, що і генератори, але як Ruby 1.9 ruby ​​як перерахунки, так

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

Довідка: http://blog.nuclearsquid.com/writings/ruby-1-9-what-s-new-what-s-changed

"Аргументи ключових слів"

Обидва перераховані там елементи підтримуються в Ruby, хоча ви не можете пропустити такі значення за замовчуванням. Можна або піти по порядку

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 фактично присвоює змінній c в області виклику значення 5 і встановлює параметру b значення 5.

або ви можете зробити це з хешами, які стосуються другого питання

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

Довідка: Посібник прагматичного прогмера до Рубі


Ваш другий приклад foo (1, c = 5) не робить те, що ви думаєте, що робить. Ruby не має названих параметрів.
horseyguy

5
Python має неявне продовження рядків у дужках (, [або{
u0b34a0f6ae,

5

Ви можете мати код у визначенні класу як у Ruby, так і в Python. Однак у Ruby у вас є посилання на клас (self). У Python у вас немає посилання на клас, оскільки клас ще не визначений.

Приклад:

class Kaka
  puts self
end

self у цьому випадку є класом, і цей код видав би "Kaka". Немає можливості роздрукувати ім'я класу або іншим способом отримати доступ до класу з тіла визначення класу в Python.


Чи можете ви надати більш детальну інформацію (наприклад, код) для своєї першої точки?
Loïc Wolff

Приклад коду - це гарна ідея, я додав це, хоча цей випадок є тривіальним.
Леннарт Регебро

@SilentGhost: Я не можу придумати той, який зараз насправді незрозумілий. :)
Леннарт Регебро

ви можете отримати доступ до назви класу всередині класу в python: class foo (): def init __ (self): print self .__ class .__ name__
txwikinger

1
@txwikinger: Так, але не в корпусі класу, який виконується одночасно із classзаявою.
Бастієн Леонард

4

Синтаксис - це незначна річ, він має прямий вплив на те, як ми думаємо. Це також безпосередньо впливає на правила, які ми створюємо для систем, які ми використовуємо. Як приклад, ми маємо порядок операцій через те, як пишемо математичні рівняння чи речення. Стандартне позначення математики дозволяє людям читати його не одним способом і дійти до різних відповідей із одним і тим же рівнянням. Якби ми використовували позначення префікса чи постфікса, ми створили б правила, щоб розрізнити, якими числами маніпулювати, а не лише правилами для порядку обчислення значень.

Стандартне позначення дає зрозуміти, про які цифри ми говоримо, одночасно встановлюючи порядок їх обчислення неоднозначним. Позначення префіксів та постфіксів встановлюють порядок обчислення простих, роблячи числа неоднозначними. У Python вже були б багатолінійні лямбда, якби не труднощі, спричинені синтаксичним пробілом. (Пропозиції існують для зняття подібних речей без обов'язкового додавання чітких роздільників блоків.)

Мені легше писати умови, коли я хочу, щоб щось сталося, якщо умова є помилковою, набагато простіше писати за допомогою оператора if, якщо не в секторі еквівалентної конструкції "якщо ні" в Ruby або інших мовах, наприклад. Якщо більшість мов, якими користуються люди сьогодні, рівні за силою, то як синтаксис кожної мови можна вважати дрібницею? Після таких специфічних функцій, як блоки та механізми успадкування тощо, синтаксис - це найважливіша частина мови, навряд чи поверхня.

Що є поверхневим - це естетичні якості краси, які ми приписуємо синтаксису. Естетика не має нічого спільного з тим, як працює наше пізнання, синтаксис.


Цей "коментар" тричі довший за те, що дозволено в коментарі, незалежно від реп.
Ендрю Грімм

Це насправді здається прекрасним як відповідь для мене. Відредагував біт "це коментар".
Білл Ящірка

3

Здивований, не побачивши нічого згаданого про механізм "методу відсутності" рубіну. Наведу приклади методів find_by _... в Rails, як приклад потужності цієї мовної функції. Я здогадуюсь, що щось подібне могло б бути реалізовано в Python, але, наскільки мені відомо, його там немає.


У Python є get_attribute , який виконує в основному те саме, що і метод Ruby's_missing.
mipadi

3
Чому розробники пітона завжди так боляче стикаються, коли рубін згадується ВСЕ? Ви не можете заперечити це неправда.
aarona

method_missingможна емулювати в Python в деяких випадках: class M(): def __getattr__(self, n): return lambda: "Missing! " + n; M().hi(). Однак є невеликі відмінності, і я сумніваюся, це ідіоматично в Python :-)

1
@DJTripleThreat: Я заперечую, що це правда.
Леннарт Регебро

3

Ще одна відмінність лямбда між Python і Ruby продемонстрована проблемою генератора акумуляторів акумуляторів Пол Грема . Передруковано тут:

Напишіть foo-функцію, яка приймає число n і повертає функцію, яка приймає число i, і повертає n з збільшенням i. Примітка: (a) це число, а не ціле число, (b), що збільшується на, не плюс.

У Ruby ви можете зробити це:

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

У Python ви б створили об'єкт, який підтримує стан n:

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

Деякі люди можуть вважати за краще чіткий підхід Python як концептуальніший, навіть якщо це трохи більш багатослівний. Ви зберігаєте стан, як і будь-що інше. Вам просто потрібно обмотати голову навколо ідеї дзвінких предметів. Але незалежно від того, якому підходу віддати перевагу естетично, він виявляє одну повагу, в якій ламбди Рубі є більш потужними конструкціями, ніж Пітон.


3
Ви не можете збільшувати числа в Python, тому обмеження не має сенсу. У Python числа незмінні. Якщо ми замінимо його на "плюс", то клас зайвий. Отже, це не свідчить про різницю лямбда, а різницю в тому, як працюють цифри. Якщо, звичайно, ви не створюєте змінний клас чисел. :)
Леннарт Регебро

2
Обмеження існує для уточнення бажаної поведінки. Проблема вимагає: f = foo (10) f (2) >> 12 f (3) >> 15 ... лямбда {| i | n + i} дає: f = foo (10) f (2) >> 12 f (3) >> 13 ... Цифри також незмінні в Ruby - наприклад, ви не можете сказати 2 + = 1. І n + = 1 добре в звичайній функції Python, але не лямбда. Отже, питання про те, що таке "n", це те, що він створюється, коли функція викликається і утворюється лямбда, що ви можете виконувати призначення в лямбда (замість просто виразів), і що вона може містити значення n через декілька дзвінків.
dormsbee

Я не думаю, що вам потрібно йти на такі рівні в Python. Функції можна визначити в межах інших функцій. def foo(n): def f(i): return n + i return f.
FMc

2
Це все ще не те саме, і ваш приклад еквівалентний лямбда Python у коментарі вище. Версія Ruby створює лямбда, яка зберігає стан між дзвінками. Приклад, який ви розмістили, дозволяє налаштувати початкове значення для n, але функція, яку повертає foo, завжди матиме це початкове значення. З кроком версії Ruby. Тож скажімо, f = foo (10). Версія Python: f (1) => 11, f (1) => 11. Версія Ruby 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 ви можете використовувати nonlocalключове слово.
jfs

3

python назвав необов'язкові аргументи

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 має лише аргументовані аргументи, оскільки b = 2 у оголошенні функції - це афект, який завжди додається.


3
що означає "Рубі лише розміщені аргументи, тому що b = 2 у оголошенні функції - це афект, який завжди додається", навіть означає?
horseyguy

3
Не знаю, на якій планеті ви живете, але def my_method(param1, optional = false)працює в Ruby 1.8.6, 1.8.7 та, імовірно, 1.9!
Роберт К

5
Злий Блоха та люди, які підтримали його коментар, ви не дивились на приклад досить близько. Він може пропустити bпараметр у funcвиклику, і він все ще підтримує його за замовчуванням. Тобто це bдругий аргумент у підписі, але він може пропустити його, префіксуючи другий параметр c=. Ruby використовує хеши, щоб імітувати це, але це не зовсім те саме.
maček

2

Ruby вбудувала документацію:

 =begin

 You could use rdoc to generate man pages from this documentation

 =end

5
Документи закінчуються як частина методів / класів, які ви їх встановили. Таким чином, ви можете допомогти (клас), і він покаже вам доктрини і т.д.
Lennart Regebro


2

У Ruby, коли ви імпортуєте файл із вимогою, всі речі, визначені у цьому файлі, опиняться у вашому глобальному просторі імен.

За допомогою 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 = імпорт ("foo-2.0.0")
>> Foo1 :: ВЕРСІЯ
=> "1.0.0"
>> Foo2 :: ВЕРСІЯ
=> "2.0.0"

Це, швидше, повинен бути коментарем, а не новою відповіддю.
Леннарт Регебро
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.