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("")
animal.run2("") 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("")
 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',''))
print (sf.getint('name', 'lastchp',0))
print (sf.get('default', 'taskcount1', ''))
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'')) #保存配置
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()