论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()
    

原文地址:https://www.cnblogs.com/zhongtang/p/8111636.html

时间: 2024-11-08 21:41:52

论python3下“多态”与“继承”中坑的相关文章

四. Java继承和多态3. 继承中的方法的覆盖和重载

在类继承中,子类可以修改从父类继承来的方法,也就是说子类能创建一个与父类方法有不同功能的方法,但具有相同的名称.返回值类型.参数列表. 如果在新类中定义一个方法,其名称.返回值类型和参数列表正好与父类中的相同,那么,新方法被称做覆盖旧方法. 参数列表又叫参数签名,包括参数的类型.参数的个数和参数的顺序,只要有一个不同就叫做参数列表不同. 被覆盖的方法在子类中只能通过super调用. 注意:覆盖不会删除父类中的方法,而是对子类的实例隐藏,暂时不使用. 请看下面的例子: public class D

【探索】VS下实现虚继承的方法-2

上篇讲到VS下实现虚继承中成员变量的二义性与数据冗余的解决方案是怎样的,今天我们来看看虚继承的成员函数会如何. 首先,虚继承会不会重写成员函数?我们看一看如下代码: #include<iostream> using namespace std; class A { public: void fun() { cout << "this is fun of A"<<endl; } }; class B1 : public A { public: void

python3下安装aiohttp遇到过的那些坑

python3下安装aiohttp遇到过的那些坑 最近需要用到aiohttp这个库,在安装过程中遇到很多坑.google.baidu后,依然没有找到合适的解决方案. 后来通过去python官方的PyPI查看aiohttp库,才发现一些问题,几经折腾,最后终于成功的在python3下安装’aiohttp’. 在这里跟大家分享一下被坑的过程. 先说一下环境.win7,64位.电脑里安装的python有3.5和3.6两个版本. 1. python3.6下安装aiohttp python3.6环境下,已

Java多态机制和继承中重写重载

关于Java中多态机制 http://www.cnblogs.com/chenssy/p/3372798.html 这篇博文讲的很透彻 大体意思是 多态定义: 多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定.因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上

多态公有继承

多态公有继承:所谓多态公有继承,就是同一个方法在派生类和基类中的行为不同. 实现多态公有继承的机制:1,在派生类重新定义基类的方法.(用于对象)2,使用虚方法(多用于指针和引用),虚方法在基类用关键字virtual声明,在派生类中会自动识别基类中声明的虚方法.所以,在派生类中可以用(也可以不用)virtual显式标出哪个方法是虚方法.通俗来讲:为了实现一种方法可以在派生类和基类中的行为不同,于是在派生类中重新定义基类函数的方法(比如基类有方法A, 但又在派生类中重新定义了方法A, 它们名字一样,

面向对象语言成员变量方法可见性在继承中的变化

最近做得的有点杂,接触到几种面向对象的语言,C#,C++,JAVA .在一个情景下,软件的框架已经写好了,我们要对其功能实现增加和修改,这种情况是经常发生的,那么在面向对象的程序设计中我们要怎么做呢.我们都知道面向对象语言有几个特点,多态,封装,继承,既然框架已经写好了,我们修改功能可以考虑用继承的方法去实现新的功能,那么这样做对原有的功能会有影响么?这就涉及到成员变量成员方法可见性在继承中的变化了. 首先,我们看C++ 派生类通过继承,将基类的成员作为自己的一部分,但不同的继承方式导致基类的成

七:Java之封装、抽象、多态和继承

本文章介绍了关于Java中的面向对象封装.抽象.继承.多态特点 Java面向对象主要有四大特性:封装.抽象.继承和多态. 一.封装 封装就是将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体,也就是将数据与操作数据的源代码进行有机的结合,形成"类",其中数据和函数都是类的成员. 在面向对象语言中,封装特性是由类来体现的,我们将现实生活中的一类实体定义成类,其中包括属性和行为(在Java中就是方法),就好像人类,可以具有name,sex,age等属性,同时也具有eat(),sle

深入理解OOP(二):多态和继承(继承)

本文是深入浅出OOP第二篇,主要说说继承的话题. 深入理解OOP(一):多态和继承(初期绑定和编译时多态) 深入理解OOP(二):多态和继承(继承) 深入理解OOP(三):多态和继承(动态绑定和运行时多态) 深入理解OOP(四):多态和继承(C#中的抽象类) 深入理解OOP(五):C#中的访问修饰符(Public/Private/Protected/Internal/Sealed/Constants/Static and Readonly Fields) 深入理解OOP(六):枚举(实用方法)

day10 Python作用域 Python2.7与Python3.x的类继承的区别及其他

一.Python作用域   1.Python中无块级作用域 if 1 == 1: name = 'test' print(name) #输出会报错,因为name的作用域仅限于if下的代码块,而不属于全局   2.Python中以函数为作用域 def func(): func_name = 'func_test' print(func_name) #这里同样会报错,因为变量func_name的作用于func函数中   3.Python作用域链,层层嵌套,使用时从内向外找   4.Python的作用