[英]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
,我發現棄用警告很煩人。 所以我開始做我的事來解決這個問題。
首先(和更老的,已經解決的問題): SafeConfigParser
是SafeConfigParser
中的舊式類,所以我不能在我的后代類中調用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
返回的代理總是一樣的嗎?“在我的情況下,我繼承了object
和SafeConfigParser
。在我的類中交換兩個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.