Python

OOP - 상속,변수, 초기화- Crawling/Custom Exceptions

foxlee 2022. 1. 13. 18:04
  • 클래스 변수 - 모든 인스턴스가 변경, 모든 클래스에서 공유
  • 인스턴스 변수 - 인스턴스 마다 사용, 해당 인스턴스만 사용, 클래스 객체에서 접근 불가능
  • 클래스 변수에 접근할 때는 특별히 이유가 없다면
    • '인스턴스.클래스변수' 나 'self.클래스변수'와 같이 접근하는 것을 피해야함
    • 방법
      • cls.변수(클래스메소드 안에서),
      • Class.변수(클래스 외부에서)
      • type(self).변수(메소드내)
    • 인스턴스 변수를 인스턴스 객체로부터 생성하는 것이 가능하므로 의도치 않게 클래스 변수를 인스턴스 변수로 은폐해버릴 수 있음 -> 인스턴스 변수와 클래스 변수 혼용하지 말것
class Crawler:

	# 크롤링을 하며 인스턴스마다 다른/저장하는 데이터들은 인스턴스 변수에 저장
    def __init__(self, logging):
        self._logging = logging
        self._parse_url = ""
        self._doc = None
        self._definitions = []
        self._examples = []
    
    # Class variable 접근 시 type(self).variable 로 접근
    def parse(self):
        dictionary_cards = self.find_elements(type(self)._dictionary_cards)
        for dict_card in dictionary_cards:
            self._examples.extend(
                self.find_text_contents(dict_card, type(self)._example_element)
            )
            self._definitions.extend(
                self.find_text_contents(dict_card, type(self)._definition_element)
            )
        self._logging.info(
            f"parsed from {type(self)._site}, count : definition {len(self._definitions)}, example {len(self._examples)}"
        )
         
    def print_data(self):
        print(f"""
            url: {self._parse_url}
            keyword: {self._keyword}
            definitions: {len(self._definitions)}
            examples: {len(self._examples)}
        """)



class CrawlerCambridge(Crawler):
	# 사이트별로 정해진 변수값들은 클래스 변수에 저장
    _site = "Cambridge"
    _url = "https://dictionary.cambridge.org/dictionary/english/"
    _dictionary_cards = [["div", "dictionary"]]
    _definition_element = ["div", ["def", "ddef_d", "db"]]
    _example_element = ["span", "eg"]

    def __init__(self, logging):
        self._logging = logging # 지금 코드에서는 없어도 가능. _logging을 이 클래스에서 정의한 메서드에서 실행(접근)한다면 필요
        Crawler.__init__(self, logging) # 부모 클래스를 초기화 해줌으로써 위에 _parse_url, _doc, 등의 변수를 인스턴스 생성시 같이 만들어짐
    
    # 오버라이드 - 부모 함수 호출하여 반복 하지 않고 로직 추가 가능
    def print_data(self):
        print(f"site: {type(self)._site}")
        super().print_data()

 

class FileError(Exception):
    def __init__(self, filename="", message="File related error occurred"):
        self.filename = filename
        self.message = message
        super().__init__(self.message)

    def __str__(self):
        if self.filename:
            return f"{self.message}, file name : {self.filename}"
        return f"{self.message}"


class FileSaveError(FileError):
    def __init__(self, filename="", message="Fail to save the file"):
        super().__init__(filename, message)


class FileRemoveError(FileError):
    def __init__(self, filename="", message="Fail to remove the file"):
        super().__init__(filename, message)


class FileExtractExtentionError(FileError):
    def __init__(self, filename="", message="Fail to extract file extention"):
        super().__init__(filename, message)


try:
    raise FileError()
    raise FileSaveError(filename="test.txt")
    raise FileRemoveError()
    raise FileError(filename="test.txt")
except Exception as e:
    print(e.__str__())