重難點 | Python基礎知識點9 Python的封裝繼承多態,推薦收藏

  • 2019 年 10 月 6 日
  • 筆記

今天是基礎系列的最後一篇文章,也是一些新手甚至是老手容易忽略的知識點,面向對象。

所有面向對象語言都有三大特徵:封裝繼承多態.那Python中面向對象怎麼做?

下面的內容只是我的經驗總結,與官方講解應該是大同小異,有自己的理解會更好些.

封裝: 描述某個對象的屬性以及方法。 比如狗,狗的大小,顏色,這些東西就是他的屬性,狗會叫,這是他的方法。 一般來說描述特徵的都是這個對象的屬性,描述行為就是方法。

繼承:Python語言也支援繼承,並且支援多繼承,所有對象的都繼承

Object

class Spider(object):

上面這個Spider就繼承了object類

什麼時候可以用到繼承呢?如果兩個對象有共同的部分,我們就可以把共同的部分抽取出來,作為父類讓子類去繼承於他.

class Spider(object):  # 定義一個抽象類      __metaclass__ = abc.ABCMeta    def __init__(self):          self.rows_title = [u'招聘標題', u'公司名稱', u'公司地址', u'待遇', u'發布日期', u'招聘鏈接', u'招聘要求描述']          sheet_name = u'51job_Python招聘'          return_execl = ExeclUtils.create_execl(sheet_name, self.rows_title)          self.execl_f = return_execl[0]          self.sheet_table = return_execl[1]          self.job_info = []  # 存放每一條數據中的各元素,          self.count = 0  # 數據插入從1開始的    def crawler_data(self):  '''          開始爬取數據          :return:          '''  for i in range(1, 5):              url = 'http://search.51job.com/list/000000,000000,0000,00,9,99,python,2,{}.html?lang=c&stype=1&postchannel=0000&workyear=99&cotype=99&degreefrom=99&jobterm=99&companysize=99&lonlat=0%2C0&radius=-1&ord_field=0&confirmdate=9&fromType=&dibiaoid=0&address=&line=&specialarea=00&from=&welfare='.format(                  i)              self.request_job_list(url)  # 採集不要太快了,否則容易造成ip被封或者網路請求失敗              time.sleep(2)    def request_job_list(self, page_url):  '''          獲取工作列表          :param page_url:          :return:          '''  try:              headers = {  'Referer': 'http://www.51job.com/',  'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.104 Safari/537.36 Core/1.53.4549.400 QQBrowser/9.7.12900.400'              }              response = requests.get(page_url, headers=headers)              response.encoding = 'gbk'  # 如果請求失敗,則不能繼續進行  if response.status_code != 200:  return              self.parse_job_list(response.text)  except Exception as e:  print 'nn出現錯誤,錯誤資訊是:{}nn'.format(e.message)        @abc.abstractmethod  def parse_job_list(self, text):  '''          解析工作列表的抽象類,具體實現在子類中          :param text:          :return:          '''  pass    def request_job_detail(self, job_href):  '''          獲取工作詳情          :param job_href: 招聘工作的鏈接          :return:          '''  try:              headers = {  'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.104 Safari/537.36 Core/1.53.4549.400 QQBrowser/9.7.12900.400'              }              response = requests.get(job_href, headers=headers)              response.encoding = 'gbk'  # 如果請求失敗,則不能繼續進行  if response.status_code != 200:  return ''                self.parse_job_detail(response.text)    except Exception as e:  print 'nn出現錯誤,錯誤資訊是:{}nn'.format(e.message)        @abc.abstractmethod  def parse_job_detail(self, text):  '''          定義工作詳情的抽象類          :param text:          :return:          '''  pass

比如上面我定義了一個爬蟲類,下面我用了子類SpiderBs4來繼承父類Spider, 這裡面我就可以直接用了父類的一些屬性與方法而不用聲明。

  # coding:utf-8  from bs4 import BeautifulSoup  from ExeclUtils import ExeclUtils  from Spider import Spider  import time      class SpiderBs4(Spider):    def __init__(self):          super(SpiderBs4, self).__init__()    def parse_job_list(self, text):  try:              soup = BeautifulSoup(text, 'html.parser')              results = soup.select('div.dw_table > div.el')[1:]  for result in results:                  job_title = result.select('p.t1 span a')                  job_href = result.select('p.t1 span a')                  job_company = result.select('span.t2  a')                  job_address = result.select('span.t3')                  job_salary = result.select('span.t4')                  job_date = result.select('span.t5')                    job_title = job_title[0].attrs['title'] if len(job_title) > 0 else ''                  job_href = job_href[0].attrs['href'] if len(job_href) > 0 else ''                  job_company = job_company[0].attrs['title'] if len(job_company) > 0 else ''                  job_address = job_address[0].text if len(job_address) > 0 else ''                  job_salary = job_salary[0].text if len(job_salary) > 0 else ''                  job_date = job_date[0].text if len(job_date) > 0 else ''                    self.job_info.append(job_title)                  self.job_info.append(job_company)                  self.job_info.append(job_address)                  self.job_info.append(job_salary)                  self.job_info.append(job_date)                  self.job_info.append(job_href)                    self.request_job_detail(job_href)                  time.sleep(1)  except Exception as e:  print 'nn出現錯誤,錯誤資訊是:{}nn'.format(e.message)    def parse_job_detail(self, text):  try:              soup = BeautifulSoup(text, 'html.parser')  try:  # 工作描述                  job_statements = soup.select('div.job_msg')                  job_statement = job_statements[0].text.strip(' ').replace(' ', '').replace('n', '')  except Exception as e:  print e.message                  job_statement = '職位無明確描述'                self.job_info.append(job_statement)              self.count = self.count + 1              ExeclUtils.write_execl(self.execl_f, self.sheet_table, self.count, self.job_info, u'bs4_51job招聘.xlsx')  print '採集了{}條數據'.format(self.count)  # 清空集合,為再次存放數據做準備              self.job_info = []  except Exception as e:  print 'nn出現錯誤,錯誤資訊是:{}nn'.format(e.message)    #  #  # if __name__ == '__main__':  #     x = SpiderBs42()  #     x.crawler_data()

多態:某個對象會有相同的行為,但具體這些行為又有所不同。 比如說吃飯,大人吃飯使用筷子,小孩吃飯用勺子,吃放的行為有所不同. 這個時候我們把吃飯的行為抽象出來,放在父類里。

  @abc.abstractmethod  def parse_job_list(self, text):  '''          解析工作列表的抽象類,具體實現在子類中          :param text:          :return:          '''  pass          @abc.abstractmethod  def parse_job_detail(self, text):  '''          定義工作詳情的抽象類          :param text:          :return:          '''  pass

比如上面我在父類里寫了兩個抽象方法,我並沒有直接去實現它,而是在他們的子類中去實現,因為他們各自實現是不同的。

好了今天的封裝繼承多態就講這些,而這些東西一定要靈活運用,死記硬背是不行的,一定要多想想。你又是如何使用封裝繼承多態的呢?

【完】