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


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 = r'zhbook.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',u'2222'))
    
    #保存配置
    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()
    

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM