1. 程式人生 > >論python3下“多態”與“繼承”中坑

論python3下“多態”與“繼承”中坑

ict for all order section 有意思 back ani eve

1、背景:

近日切換到python3後,發現python3在多態處理上,有一些比較有意思的情況,特別記載,供大家參考。。。

以廖老師的python3教程中的animal 和dog的繼承一節的代碼做例子,上代碼先:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

class Animal(object):
    def run1(self):
        print(Animal is running 1...)
    def run2(self):
        self.run1()
        print
(Animal is running 2...) class Cat(Animal): def run1(self,name): print([%s] Cat is running1... %name) def run2(self,name=""): super().run2() print([%s] cat is running2... %name) def run_twice(animal): animal.run1("1") animal.run2(
"2") if __name__==__main__: c = Cat() run_twice(c)

輸出結果:

[1] Cat is running1...

報錯信息如下:

? File "d:\python\tensf\clstest.py", line 28, in <module>
  run_twice(c)
? File "d:\python\tensf\clstest.py", line 23, in run_twice
  animal.run2("2")
? File "d:\python\tensf\clstest.py
", line 17, in run2 super().run2() ? File "d:\python\tensf\clstest.py", line 8, in run2 self.run1() builtins.TypeError: run1() missing 1 required positional argument: name

2、分析原因:

1、父類animal中run2()調用了run1()

2、子類cat中覆蓋了run1(),增加了name參數,並覆蓋了run2(),同樣增加了name參數,並調用父類animal中run2()

3、理想中的狀態,父類的run2()應該是調用父類的run1(),實際卻是調用子類的run1(),所以導致參數匹配錯誤。

builtins.TypeError: run1() missing 1 required positional argument: name

解決方案要分情況,就本例而言給name賦上默認值即可。


3、延伸

問題來源於自己寫了configparser的擴展包,實現給get(),getint(),set()加默認值的方法,在python2中好用,移到python3中突然不好用了,有點發懵。

不過仔細分析,還是python3中configparser的get()有修改。

困擾了我接近一天,還是基本功有問題,貼上我寫的簡單代碼。

補充一點:python3下默認有configparser,無需額外用pip安裝,而且大寫改成了小寫。

#coding=utf-8
‘‘‘
Date    :2016.10.8
Author  : joshua zou

Purpose : 
    configparser 的擴展類,增加默認值,兼容key不存在的情況。
Use exap: 
    import eConfig as eTax
    INICONFIG=eTax.eConfig()
    #讀取配置文件中配置
    debuglevel = INICONFIG.get(‘default‘,‘debuglevel‘)
‘‘‘
try:
    from configparser import OrderedDict as _default_dict
except ImportError:
    # fallback for setup.py which hasn‘t yet built _collections
    _default_dict = dict
    
from configparser import RawConfigParser

class eConfig(RawConfigParser ):
    def __init__(self, defaults=None, dict_type=_default_dict, 
                allow_no_value=False):
        super().__init__(defaults, dict_type,allow_no_value)
        
    def get(self, section, option, default=‘‘,**kwargs):
        try :
            sRet =  super().get(section, option,**kwargs)
        except:
            sRet = default 
        return sRet
    
    def getint(self, section, option,default=None,**kwargs):
        try :          
            sRet =  super().getint(section, option,**kwargs)
        except Exception as e :
            sRet = default 
        return sRet

    def getfloat(self, section, option,default=None,**kwargs):
        try :
            sRet = super().getfloat(section, option)
        except:
            sRet = default 
        return sRet

    def getboolean(self, section, option,default=None,**kwargs):
        try :
            sRet = super().getboolean(section, option)
        except:
            sRet = default 
        return sRet
    
    def set(self, section, option,value):
        if not super().has_section(section):
            sRet =  super().add_section(section)
        sRet = super().set(section, option, value)    
        return sRet    
    
if __name__ == "__main__":
    #讀取配置
    filename = rzhbook.ini
    sf=eConfig()
    sf.read(filename)
    
    print (sf.get(name, lastchp,1))
    print (sf.getint(name, lastchp,0))
    print (sf.get(default, taskcount1, 1))
    print (sf.get(default, taskcount1))
    print (sf.getint(default, taskcount1))
    print (sf.getboolean(default, taskcount1))
    print (sf.getfloat(default, taskcount1))
    print (sf.set(default2, taskcount1,u2222))
    
    #保存配置
    fp = open(filename,"w")
    sf.write(fp)
    fp.close()
    print (sf.get(default, taskcount1))
    sf.remove_option(default,taskcount1)
    fp = open(filename,"w")
    sf.write(fp)
    fp.close()
    

論python3下“多態”與“繼承”中坑