-
Ruby VS Python 뭐가 다를까? [2부]💻 프로그래밍/Ruby On Rails 2021. 3. 13. 15:25
안녕하세요! 이번에는 Ruby VS Python 비교 두 번째 포스팅입니다.
이번 포스팅에서는 method, class, exception(예외처리) 등 에 대해 비교해보고 느낀 점을 공유해보겠습니다.
👨💻 문법 비교
1. method (함수)
- Ruby♦️
def test_method(temp = "default")return "hello world! #{temp}"endputs test_methodputs test_method('무야호!')puts test_method '무야호~'cs - Python🐍
def test_method(temp="default"):return f"hello world! {temp}"print(test_method())print(test_method('무야호!'))cs 일단은 함수의 선언도 크게 다르지는 않은 것 같아요. Ruby는 특이한 게 파라미터를 함수에 전달할 때 괄호를 사용하지 않아도 되더군요. 역시 Ruby는 최대한 간결하게 사용하려는 게 문법에서 많이 드러나는 것 같습니다.
2. class (클래스)
- Ruby♦️
class Companyattr_writer :name # 인스턴스 변수에 수정하기 위해 사용attr_reader :name # 인스턴스 변수를 접근하기 위해사용attr_accessor :sector #인스턴스 변수에 접근하고 수정하기 위해 사용@@count = 0def initialize(name, sector)@name = name@sector = sector@@count += 1 # 회사 카운트enddef describeputs "저희 회사의 이름은 #{@name} 이며, 업종은 #{@sector} 입니다"enddef self.print_intro # 클래스 메소드 (인스턴스 선언을 하지 않아도 사용가능)puts "이것은 Company class 입니다"enddef self.get_company_countreturn @@countendendCompany.print_intro # 클래스 메소드 호출 (인스턴스 선언 없이 호출 가능)jay_company = Company.new('jay', 'game')jay_company.describejay_company.name = 'new_jay'jay_company.describezzeri_company = Company.new('jay', 'game')puts Company.get_company_countcs - Python🐍
# Ruby에서도 클래스의 부모 클래스는 object Python에서는 명시해주는 걸 선혼# class Company(object):class Company:count: int = 0 # 클래스 변수def __init__(self, name, sector): ## __xxx__ 매직 메서드에서 사용되는 컨벤션self.name = name # 인스턴스 변수(self)self.sector = sector # 인스턴스 변수(self)Company.count += 1def describe(self):print(f"저희 회사의 이름은 {self.name} 이며, 업종은 {self.sector} 입니다")@classmethod # 클래스 메소드 선언 데코레이터def print_intro(cls):print("이것은 Company class 입니다")@classmethoddef get_company_count(cls):return cls.countCompany.print_intro() # 클래스 메소드 호출 (인스턴스 선언 없이 호출 가능)jay_company = Company('jay', 'game')jay_company.describe()jay_company.name = 'new_jay'jay_company.describe()zzeri_company = Company('jay', 'game')print(Company.get_company_count())cs class 선언은 두 언어가 많이 다른 것 같습니다. 일단 첫 번째로는 class변수, instance 변수의 선언입니다.
python의 경우 self로 선언한 변수는 인스턴스 변수, class 내부에서 선언된 변수는 class변수입니다.
ruby는 반면에 @변수가 instance 변수, @@변수는 class 변수입니다. 그리고 ruby는 attr_writer, attr_reader, attr_accessor 같은 걸로 인스턴스 변수 접근에 대한 권한을 줄 수도 있습니다.
또 한 가지 다른 점은 class method의 경우 python에서는 @classmethod로 선언을 하게 되는데, ruby는 함수 앞에 self를 붙이는 게 class method의 선언입니다. class method는 별도의 instatnce 생성 없이 사용 가능합니다.
두 언어가 기능은 비슷한데, 선언하는 방법과 문법의 차이가 확실히 다르네요. python만 사용하다가 ruby를 보니까 살짝 헷갈리기도 하네요:D
3. class (클래스) 상속
- Ruby♦️# 클래스 상속class Animaldef barkputs "부모 클래스"endprivate # private 선언하면 외부 접근 불가def ageendpublic # 메소드는 기본적으로 publicdef nameendendclass Dog < Animaldef barksuper()puts "멍멍"endenddog = Dog.new()dog.barkputs Dog.superclass # 부모클래스 확인dog.namecs - Python🐍
from abc import abstractmethod, ABCMetaclass Animal(metaclass=ABCMeta): # 추상 메소드 구현을 강제하기 위해@abstractmethod # 이 데코레이터를 붙이면, 상속받는 클래스에서 오버라이딩을 꼭 해줘야한다def bark(self):print("부모 클래스")def __age(self): # __(언더스코어 2개)가 private이라는 컨벤션passdef name(self):passclass Dog(Animal):def bark(self):super().bark()print("멍멍")dog = Dog()dog.bark()print(Dog.__bases__)dog.namecs class의 상속도 두 언어 비슷하나 private, public 선언이 살짝 다릅니다. python은 __(언더스코어 2개)로 private이라는 표현을 컨벤션으로 할 수 있고, ruby의 경우 private이라고 함수 위에 데코레이터(?)처럼 선언을 해줘야 한다. (실제로 이게 데코레이터 같은 역할인지는 좀 더 찾아봐야 할 것 같습니다.)
추가로 python에서는 metaclass=ABCMeta를 선언하고 메서드에 @abstractmethod 데코레이터를 사용하면, 상속받는 자식 클래스에 오버라이등을 강제할 수 있습니다. ruby에도 이런 데코레이터가 있는지 찾아봐야겠네요.
4. 싱클톤 메서드
- Ruby♦️
class Fooendnew_foo = Foo.new()new_foo2 = Foo.new()def new_foo.print_helloputs "hello!"endnew_foo.print_hellonew_foo2.print_hellocs ruby는 class에서 정의한 메서드 이외에 추가로 인스턴스 고유의 메서드를 가질 수 있습니다.
5. 예외처리
위에서 선언한 Dog 클래스를 사용해서 예외처리에 대해 알아보겠습니다.
- Ruby♦️
dog = Dog.new()begindog.age # private method erroedrescue => e# 예외 발생puts "------------------"puts "Error : #{e.class}" #standard Errorputs "Error : #{e.message}" # 에러 메세지puts "Error : #{e.backtrace}" # 콜스택 배열puts "------------------"else# 예외가 발생하지 않은 경우 실행puts "예외 발생되지 않음"ensure# 예외 유무 상관없이 실행puts "무야호!"endcs - Python🐍
dog = Dog()try:dog.age() # private method erroedexcept Exception as e:# 예외 발생print("------------------")print(f"Error : {e.__class__}") #standard Errorprint(f"Error : {e.__str__()}") # 에러 메세지print(f"Error : {e.__traceback__.tb_frame}") # 콜스택 배열print("------------------")else:# 예외가 발생하지 않은 경우 실행print("예외 발생하지 않음")finally:# 예외 유무 상관없이 실행print("무야호!")cs python, ruby 두 언어 모두 예외처리를 똑같이 할 수 있습니다. 다만, 문법적 차이는 있습니다. 신기하게 ruby에서는 except를 rescue라고 하더라고요. 예외처리를 구출(?)하라는 의미인가 ㅋㅋㅋ 다른 언어에서도 저렇게 사용하는지 확인해보는 것 도 재밌겠네요.
그 외 다른 점은 ensure, finally가 다르네요.
6. yield
- Ruby♦️# yielddef check_yieldif block_given?yield puts "block"elseputs "no block"endendchekc_yieldchekc_yield {"block"}puts "------------------------"#파라미터가 있는 yielddef check_yield_with_param(item)puts "before yield"yield(item)puts "after yield"endcheck_yield_with_param("block") { |item| puts "#{item}" }cs - Python🐍
def check_yield():yield print("block")return '더이상 호출 할게 없음'try:check_yield = check_yield()next(check_yield)next(check_yield)except StopIteration as e:print(e)cs yield 키워드를 python을 사용하면서 많이 사용해보진 않았는데요. 제너레이터를 만들 때 사용합니다. 둘 다 비슷하긴 한데 ruby의 경우 내부에 yield가 있는 경우 block을 공급해야 한다고 합니다. 그리고 block_given? 메서드로 block이 공급되었는지도 확인 가능합니다.
# yielddef check_yieldif block_given?yield puts "block"endyieldendcheck_yieldcs block을 전달하지 않고 yield를 만나게 되면 이렇게 오류가 나옵니다.
👋 마치며
이번 포스팅에서는 python, ruby의 함수, 클래스, 상속, 예외처리 등에 대해 비교해봤습니다. 좀 더 깊게 파고들면 더 많은 내용을 알아야 하지만, 일단 가볍게 비교해 보기만 했습니다.
python, ruby를 비교해보면서 두 언어가 비슷한 점도 많고 다른 점도 있다고 느꼈습니다. 가장 크게 느낀 점은 python도 매우 간결하고 읽기 쉬운 코드를 지향하지만 ruby는 좀 더 간결한 문법을 지향하는 것 같습니다.
특히 user_score.select { |k| k.size == 4 }와 같은 select와 익명 함수를 이용한 문법은 python보다 더 간결하게 로직을 구현할 수 있다는 점이 인상 깊었습니다.
그럼 오늘도 좋은 하루 보내시길 바랍니다!
'💻 프로그래밍 > Ruby On Rails' 카테고리의 다른 글
Ruby On Rails 맛보기 - model (0) 2021.03.14 Ruby On Rails 맛보기 - controller, view (0) 2021.03.14 Ruby VS Python 뭐가 다를까? [1부] (0) 2021.03.12