본문 바로가기

Python

20210128_Python 와 Ruby 비교05 - 객체와 모듈, 다중상속, mixin, 패키지 매니저

Python vs Ruby (루비 위주)

Object & Module (객체와 모듈)

모듈내 클래스 객체에 할당하기

  • Ruby

  • lib.rb라는 모듈 파일을 생성한 상태에서 실행(루비의 경우엔 파일안에서 모듈 자체 이름을 붙여 주어야 함)

  • Ruby에서는 객체에 할당시에는 ::를 사용하여 모듈 이름을 붙여주고 클래스를 같이 할당함

"lib.rb 파일"
module Lib
    class A 
        def a()
            return 'a'
        end
    end
end

"작업 하고자 하는 파일"
require_relative 'lib'
obj = Lib::A.new() # 모듈에 속한 클래스를 가져올 경우 ::을 씀
p obj.a()

  • Python

  • lib.py 파일을 만들고 클래스 할당시 모듈이름.클래스이름() 의 형식으로 할당

"lib.py 파일"
class A:
    def a(self):
        return 'a'

"작업 하고자 하는 파일"
import lib
obj = lib.A()
print(obj.a())


Multiple Inheritance (다중 상속)

  • 다중 상속은 여러 부모의 기능을 상속하여 사용하는 것이다. -> 단, 신중히 사용해야한다. 안그러면 복잡성이 증가하게 됨
  • Python의 경우에는 다중상속을 지원하지만 Ruby의 경우에는 다중상속을 지원하지 않는다.
  • 대신, Ruby에서는 mixin 기능을 통해 대체 되어진다.
  • 그리고 다중 상속에서도 부모들의 메소드 이름이 같은 경우가 발생할 수 도 있다. -> python에서 실행 순서는 상속 부모들의 기입 순서에 따라 우선순위가 적용된다.

1. Python의 다중 상속

  • Python
  • python의 경우에는 C1, C2 클래스가 부모들이 되고 C3클래스가 자식으로 설정하여 테스트 해보았다. -> C3클래스를 c인스턴스에 할당하여 C1,C2 인스턴스 메서드들을 호출 시켜 보니 잘 작동하였다.
  • 그리고 동일 함수명일 경우를 위해서 각 클래스 마다 m이라는 메서드을 만들었고 c인스턴스를 통해서 m의 인스턴스 메서드를 호출해 보니 상속 기입 순서에 따라 우선순위가 달라졌다.
  • 클래스.__mro__ 는 해당 클래스의 우선순위를 보여준다.
class C1():
    def c1_m(self):
        print("c1_m")

    def m(self):
        print("c1 m")


class C2():
    def c2_m(self):
        print("c2_m")

    def m(self):
        print("c2 m")


class C3(C2, C1):
    # def m(self):
    #     print("C3 m")
    pass


c = C3()
c.c1_m()
c.c2_m()
c.m()  # 부모 들이 같은 메소드 이름이 있으면 비슷하게 동작하지만 정확하게 동작하지 않아 심각한 문제 발생할 수 있다.
# 실행 순서는 상속 부모의 기입 순서에 따라 우선순위 적용
print(C3.__mro__)  # C3라는 클래스를 사용할때 우선 순위가 어떻게 되는지 보여줌

2. 계산기 예제에 다중 상속 활용

  • python

  • __init__ 관련하여 실행 오류는 발생하지 않지만 Intellisense error (빨간 밑줄) 발생하기 때문에 __init__을 중복하여 상단에 먼저 정의 되도록 하였다.

  • 그런데 ruby의 경우에서는 initialize 문제가 생기지 않았다. python에서만 발생하는 것 같기도 하다.

class CalMultiply():
    def __init__(self, v1, v2):
        self.v1 = v1
        self.v2 = v2

    def multiply(self):
        return self.v1*self.v2


class CalDivide():
    def __init__(self, v1, v2):
        self.v1 = v1
        self.v2 = v2

    def divide(self):
        return self.v1/self.v2


class Cal(CalMultiply, CalDivide):

    def add(self):
        return self.v1+self.v2

    def subtract(self):
        return self.v1-self.v2


c = Cal(100, 10)
print(c.add())
print(c.divide())
print(c.multiply())

3. Ruby의 mixin 기능

  • Ruby의 경우 다중상속을 지원하지 않지만 mixin(믹스인) 기능이 있다.

  • 믹스인 기능은 클래스의 다중상속을 지원하지 않고 모듈의 다중상속을 지원한다.

  • 즉, 모두 모듈화로 만들어야 다중상속을 하여 함수들을 사용할 수 있다.

  • 다중 상속을 받고자 하는 클래스의 경우 include를 사용한다.

  • Ruby

module M1
    def m1_m
        p "m1_m"
    end
end

module M2
    def m2_m
        p "m2_m"
    end
end


class C
    include M1, M2
end

c = C.new()
c.m1_m()
c.m2_m()

4. 계산기 예제에서 mixin 활용

  • Ruby
module Multiply
    def multiply()
        return @v1*@v2
    end
end

module Divide
    def divide()
        return@v1/@v2
    end
end

class Cal
    include Multiply, Divide
    def initialize(v1,v2) 
        @v1 = v1
        @v2 = v2          
    end
    def add()      
        return @v1+@v2
    end
    def subtract()
        return @v1-@v2
    end
end


c = Cal.new(100, 10)
p c.add()
p c.multiply()
p c.divide()


Packgae Manager (패키지 매니저)

  • 패키지 매니저는 각 필요한 기능들을 담고 있는 모듈의 패키지들을 관리하고 있으며 사람들이 opensource로 올려서 기능을 받고 사용하는 식으로 되어 있다.

  • 종류는 언어에 따라서 다르게 존재한다.
  • python - pip - pypi.python.org
  • ruby - rubygems - rubygems.org
  • nodejs - npm - npmjs.com
  • php - composer - packagist.org

  • 설치방법과 확인 -> cmd를 통해서 가능
  • python은 커맨드가 pip -> pip 만 쳐도 pip 관련 커맨드가 나타난다.
  • ruby는 커맨드가 gem -> gem 만 쳐도 gem 관련 커맨드가 나타난다.
  • 그리고 설치 방법 및 사용법은 보통 필요한 패키지 문서에 나와있으니 구글링을 통해서 알아보자

패키지 매니저 활용 예시

  • Python
  • 사이트의 html 불러오기 구글링 python3 http download library
  • 사이트의 html 분석을 목적으로 하여 구글링 python3 http parser library
import requests
from bs4 import BeautifulSoup
r = requests.get('https://codingeverybody.github.io/scraping_sample/1.html')
print(r.text)
# 패키지 다운 받았음
soup = BeautifulSoup(r.text, 'html.parser')
print(soup.title)
print(soup.title.string)

print()

print("Title : {0}".format(soup.title.string))
articles = soup.findAll('div', {'class': 'em'})
# print(articles)
# print(articles[0])
# print(articles[0].text)
print("Articles : {0}".format(articles[0].text))

print()

r = requests.get('https://codingeverybody.github.io/scraping_sample/2.html')
soup = BeautifulSoup(r.text, 'html.parser')
print("Title : {0}".format(soup.title.string))
articles1 = soup.findAll('div', {'class': 'strong'})
print("Articles : {0}".format(articles1[0].text))

이로서 생활코딩의 "python & ruby" 수업은 종료!