首页 > 解决方案 > 多态性和 with 语句

问题描述

给定一个将 .csv 文件导出到数据库的类:

import luigi
import csv

class CsvToDatabase(luigi.Task):
  # (...)
  
  def run(self):    
    ## (...)
    
    with open(self.input().some_attribute, 'r', encoding='utf-8') as some_dataframe:
      y = csv.reader(some_dataframe, delimiter=';')
      
      ### (...) <several lines of code>
  
  # (...)

我在尝试使用 ISO-8859-1 编码导出文件时遇到问题。

encoding当我从 then函数中排除参数时open(),一切正常,但我无法对类定义进行永久性更改(公司的其他部门使用它)。于是我想到了用多态来解决它的可能性,比如:

from script_of_interest import CsvToDatabase

class LatinCsvToDatabase(CsvToDatabase):
  # code that uses everything in `run()` except the `some_dataframe` definition in the with statement

这种可能性真的存在吗?我怎么能在不重复语句中的“几行代码”的情况下处理它?

标签: pythonoopinheritancepolymorphismcontextmanager

解决方案


在您发布答案后,我认为最好发布一些替代方案。所以,这是你当前的课程,最小的例子

class A:
    def run(self):
        # some code
        with open('some_file.csv' , encoding='utf-8'):
            pass
        # more code

我的想法,在评论中建议 - 更改类 A 并将参数添加encodingA.run()默认值utf-8。这样,更改不会影响其他人(他们使用 A 类的现有代码)。

class A:
    def run(self, encoding='utf-8'):
        # some code
        with open('some_file.csv' , encoding=encoding):
            pass
        # more code

然后在你的代码中

a=A() # create instance of A
a.run(encoding=None)

现在,您添加类属性的想法。这就是您决定更改 A 类的方式:

class A:
    encoding='utf-8'
    
    def run(self):
        # some code
        with open('some_file.csv', encoding=self.encoding):
            pass
        # more code

我认为你不需要子类。有了这个新的 A 类,你可以做到

a=A() # create instance of the new class A
a.encoding=None # note, in run() you use self.encoding and this will work. still A.encoding is utf-8 and others will not be affected.

如果你坚持要继承新的 A 类

class B(A):
    encoding=None

然后在您的代码中,您可以使用 B 类的实例。


推荐阅读