假设我在一个类中定义了:
import stuff
import more stuff
import stuff that takes a long time to import
class Foo(object):
def __init__(self, arg1, arg2 etc.):
self.arg1 = arg1
self.arg2 = arg2
# Lots of other stuff
# Lots of methods
在另一个文件里我有这样的代码:
^{pr2}$假设由于我无法控制的原因,Foo文件需要很长时间才能导入。如何重构此代码以不导入Foo,但仍然可靠地检查类型?我认为鸭子打字不适合我的特殊情况。在
例如,我是否应该检查obj
基的字符串表示形式?或者还有其他更规范的方法吗?在
如果
big_file
确实因为任何非标准的原因而需要很长时间导入,那么您确实可以使用str
表示。下面是一个相当健壮的实现:isFoo
函数测试传递的obj
是否是在名为big_file
的模块中定义的某个名为Foo
的类的实例。原则上,如果您有多个同名的模块,例如在不同的包中,这可能会失败,但当然这对您来说很可能不是问题。在编辑,处理Foo
的子类正如sytech指出的,上面的解决方案在子类上失败了。也就是说,},如果}。以下代码是上述代码的通用版本,用于解决此问题:
^{pr2}$isFoo(obj)
返回{obj
是Foo
的子类的实例,而isinstance(obj, Foo)
返回{这使用了与以前相同的测试,但现在不仅对
obj
的class
进行了测试,而且还对其所有的超类进行了测试。在编辑,使想法不会失败
上面唯一需要注意的是,我们只测试模块名称而不是绝对路径。如前所述,只有当您的项目包含多个同名的模块,并且包含同名的类时,这才是一个问题。我们可以测试路径,当然这需要您在代码中指定模块的绝对路径:
为了使函数完全类似于内置的}是否是{}或{})的实例。在
isinstance
,它现在还支持多个类作为输入(例如tuple
,形式为(('/path/to/module1.py', 'Foo'), ('/path/to/module2.py', 'Bar'))
,用于检查{虽然这个版本是防弹的,但我个人更喜欢前面的
isFoo
,因为指定模块的绝对路径有点难看。在通常,这不是问题。如果您有一个
big_file.Foo
的实例,那么它的父模块已经在早些时候导入了,即使没有从其他文件显式引用。Python模块只在第一次导入时加载一次(前提是您没有进行任何显式的重新加载或弄乱sys.modules
)。因为它已经被导入,所以在另一个文件中执行import big_file
操作应该立即运行。在但是,如果您的另一个文件在某些情况下只会遇到}只在实际需要时导入到其他地方,那么您可以这样检查对象的类(这不支持子类):
big_file.Foo
,而{因为您已经指出
^{pr2}$big_file.Foo
可以在应用程序中的任何时候导入,并且您希望支持子类,所以可以检查它的模块是否已导入,并有条件地检查类型。在相关问题 更多 >
编程相关推荐