• 论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	ensfclstest.py", line 28, in <module>
      run_twice(c)
     File "d:python	ensfclstest.py", line 23, in run_twice
      animal.run2("2")
     File "d:python	ensfclstest.py", line 17, in run2
      super().run2()
     File "d:python	ensfclstest.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()
        
  • 相关阅读:
    Git常用操作命令
    android快速入门
    使用Jsoup 抓取页面的数据
    js面向对象组件
    js事件详解
    图解TCP-IP协议
    error: linking with `cc` failed: exit code: 1
    git——'fatal: cannot do a partial commit during a merge'
    git add 而未 commit 的文件丢失后找回
    为rust配置国内/科大源
  • 原文地址:https://www.cnblogs.com/zhongtang/p/8111636.html
Copyright © 2020-2023  润新知