当通过传递的对象调用不同的方法时,使用 isinstance 是否合理
Is usage of isinstance is justified when calling different methods by passed object
我正在开发能够读取文件低级数据(即映射等)并将结果存储到 sqlite DB 的小工具,使用 python 的内置 sqlite API。
对于解析的文件数据,我有 3 classes:
class GenericFile: # general file class
# bunch of methods here
...
class SomeFileObject_A: # low level class for storing objects of kind SomeFileObject_A
# bunch of methods here
...
class SomeFileObject_B: # low level cass for storing objects of kind SomeFileObject_A
# bunch of methods here
...
sqlite 接口实现为单独的 class:
class Database:
def insert(self, object_to_insert):
...
def _insert_generic_file_object(self, object_to_insert):
...
def _insert_file_object_a(self, object_to_insert):
...
def _insert_file_object_b(self, object_to_insert):
...
# bunch of sqlite related methods
当我需要向数据库中插入一些对象时,我正在使用 db.insert(object)
。
现在我认为在我的 insert
方法中使用 isinstance
可能是个好主意,因为它会处理任何插入的对象,而无需为每个对象显式调用合适的方法,看起来更优雅。
但是在看了更多isinstance
之后,我开始怀疑,我的设计不是很好。
下面是通用 insert
方法的实现:
class Database:
def insert(self, object_to_insert):
self._logger.info("inserting %s object", object_to_insert.__class__.__name__)
if isinstance(object_to_insert, GenericFile):
self._insert_generic_file_object(object_to_insert)
elif isinstance(object_to_insert, SomeFileObject_A):
self._insert_file_object_a(object_to_insert)
elif isinstance(object_to_insert, SomeFileObject_B):
self._insert_file_object_b(object_to_insert)
else:
self._logger.error("Insert Failed. Bad object type %s" % type(object_to_insert))
raise Exception
self._db_connection.commit()
那么,在我的情况下是否应该避免 isinstace
,如果应该,这里有什么更好的解决方案?
谢谢
OO 的基本原则之一是用多态分派替换显式开关。在您的情况下,解决方案是使用双重分派,因此 FileObect
有责任知道要调用哪个 Database
方法,即:
class GenericFile: # general file class
# bunch of methods here
...
def insert(self, db):
return db.insert_generic_file_object(self)
class SomeFileObject_A: # low level class for storing objects of kind SomeFileObject_A
# bunch of methods here
...
def insert(self, db):
return db.insert_file_object_a(self)
class SomeFileObject_B: # low level cass for storing objects of kind SomeFileObject_A
# bunch of methods here
...
def insert(self, db):
return db.insert_file_object_b(self)
class Database:
def insert(self, obj):
return obj.insert(self)
我正在开发能够读取文件低级数据(即映射等)并将结果存储到 sqlite DB 的小工具,使用 python 的内置 sqlite API。
对于解析的文件数据,我有 3 classes:
class GenericFile: # general file class
# bunch of methods here
...
class SomeFileObject_A: # low level class for storing objects of kind SomeFileObject_A
# bunch of methods here
...
class SomeFileObject_B: # low level cass for storing objects of kind SomeFileObject_A
# bunch of methods here
...
sqlite 接口实现为单独的 class:
class Database:
def insert(self, object_to_insert):
...
def _insert_generic_file_object(self, object_to_insert):
...
def _insert_file_object_a(self, object_to_insert):
...
def _insert_file_object_b(self, object_to_insert):
...
# bunch of sqlite related methods
当我需要向数据库中插入一些对象时,我正在使用 db.insert(object)
。
现在我认为在我的 insert
方法中使用 isinstance
可能是个好主意,因为它会处理任何插入的对象,而无需为每个对象显式调用合适的方法,看起来更优雅。
但是在看了更多isinstance
之后,我开始怀疑,我的设计不是很好。
下面是通用 insert
方法的实现:
class Database:
def insert(self, object_to_insert):
self._logger.info("inserting %s object", object_to_insert.__class__.__name__)
if isinstance(object_to_insert, GenericFile):
self._insert_generic_file_object(object_to_insert)
elif isinstance(object_to_insert, SomeFileObject_A):
self._insert_file_object_a(object_to_insert)
elif isinstance(object_to_insert, SomeFileObject_B):
self._insert_file_object_b(object_to_insert)
else:
self._logger.error("Insert Failed. Bad object type %s" % type(object_to_insert))
raise Exception
self._db_connection.commit()
那么,在我的情况下是否应该避免 isinstace
,如果应该,这里有什么更好的解决方案?
谢谢
OO 的基本原则之一是用多态分派替换显式开关。在您的情况下,解决方案是使用双重分派,因此 FileObect
有责任知道要调用哪个 Database
方法,即:
class GenericFile: # general file class
# bunch of methods here
...
def insert(self, db):
return db.insert_generic_file_object(self)
class SomeFileObject_A: # low level class for storing objects of kind SomeFileObject_A
# bunch of methods here
...
def insert(self, db):
return db.insert_file_object_a(self)
class SomeFileObject_B: # low level cass for storing objects of kind SomeFileObject_A
# bunch of methods here
...
def insert(self, db):
return db.insert_file_object_b(self)
class Database:
def insert(self, obj):
return obj.insert(self)