繁体   English   中英

Python 2和3兼容`super`和类在Py2中是旧式的,但在Py3中变成了新式

[英]Python 2 & 3 compatibility with `super` and classes who were old-style in Py2 but became new-style in Py3

我有一个使用SafeConfigParser 的项目 ,我希望它与Python2和3兼容。 现在,从Python 3.2开始不推荐使用SafeConfigParser ,我发现弃用警告很烦人。 所以我开始做我的事来解决这个问题。

首先(和更老的,已经解决的问题): SafeConfigParserSafeConfigParser中的旧式类,所以我不能在我的后代类中调用super 为了获得更一致的行为,我写了以下内容:

try:
    # Python 2
    class ConfigResolverBase(object, SafeConfigParser):
        """
        A default "base" object simplifying Python 2 and Python 3
        compatibility.
        """
        pass
except TypeError:
    # Python 3
    class ConfigResolverBase(SafeConfigParser):
        """
        A default "base" object simplifying Python 2 and Python 3
        compatibility.
        """
        pass

如果有必要,这样可以使课程成为新式。 为了摆脱DeprecationWarning我将代码更改为:

if sys.hexversion < 0x030000F0:
    # Python 2
    class ConfigResolverBase(object, SafeConfigParser):
        """
        A default "base" object simplifying Python 2 and Python 3
        compatibility.
        """
        pass
else:
    # Python 3
    class ConfigResolverBase(ConfigParser):
        """
        A default "base" object simplifying Python 2 and Python 3
        compatibility.
        """
        pass

一路上我还修了一条我错过了之前改变的路线:

@@ -275,7 +276,7 @@ class Config(ConfigResolverBase):
             have_default = False

         try:
-            value = SafeConfigParser.get(self, section, option, **kwargs)
+            value = super(Config, self).get(section, option, **kwargs)
             return value
         except (NoSectionError, NoOptionError) as exc:
             if have_default:

这一变化引发了一个有趣的错误:

AttributeError: 'Config' object has no attribute '_sections'

让我相信ConfigParser __init__没有被调用。 确实做出以下修改:

- class ConfigResolverBase(object, SafeConfigParser):
+ class ConfigResolverBase(SafeConfigParser, object):

我的代码现在对Python 2和3都运行良好,但我不确定的是: super返回的代理总是一样的吗?“在我的情况下,我继承了objectSafeConfigParser 。在我的类中交换两个SafeConfigParser定义使super返回正确的。但这是否保证在所有平台上的所有Python实现中都是稳定的?或者我应该明确地调用SafeConfigParser.get(self, ...) ?这是所有的“老方法”呼唤基地......

是的,它在Python版本中保证稳定。 搜索顺序称为方法解析顺序(MRO),此顺序与Python 2.3相同。

有关如何确定订单的更多详细信息,请参阅Python 2.3方法解析订单文档

您可以通过查看给定类的.__mro__属性来检查MRO; 它是方法解析顺序中的类的元组。

我也在使用SafeConfigParser做一些工作。 为了使它适用于旧式和新式类,两者都可以检查它是否是object的子类。 新式类继承自object ,而旧式类则不继承。

例:

class MyClass(SafeConfigParser):
    def __init__(self):
        if issubclass(SafeConfigParser, object):
            # new style class, call super
            super(MyClass, self).__init__()
        else:
            # old style class, call __init__ manually
            SafeConfigParser.__init__(self)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM