python isinstance()与type()的区别

本文围绕Python编程展开,介绍了继承和派生,指出继承可提高代码复用但可能导致类爆炸式增长,还阐述了派生的概念。同时讲解了组合,对比了继承和组合的使用场景。此外,对接口和归一化设计、抽象类及其与接口的区别进行了说明。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

isinstance()会认为子类是一种父类类型,考虑继承关系。

type()不会认为子类是一种父类类型,不考虑继承关系。

如果要判断两个类型是否相同推荐使用isinstance()

isinstance(object, classinfo)
Parameter:
    object    --实例对象
    classinfo --可以是直接或间接类名、基本类型或者由它们组成的元素

二、python的继承和派生

继承是一种创建类的方法,在python中,一个类可以继承来自一个或多个父类、原始类称为基类和超类。

class ParentClass1: #定义父类
    pass

class ParentCalss2: #定义父类
    pass

class SubClass1(ParentClass1): #单继承,基类是ParentClass1,派生类是SubClass
    pass

class SubClass2(ParentClass1,ParentClass2): # python 支持多继承,用逗号分隔开多个继承的类
    pass


查看继承:
>>> SUbClass2.__bases__
(<class '__main__.ParentClass1>, <class '__main__.ParentClass2'>)

2.1加入已经有几个类,而类与类之间的共同变量属性和函数属性,那就可以把这几个变量属性和函数属性提取出来作为基类的属性。而特殊的变量属性和函数属性,则在本类中定义,这样只需要继承这个基类,就可以访问基类的变量属性和函数属性。可以提高代码的可扩展性。

class Riven:
    camp = 'Noxus'
    def __init__(self, nickname,
                    script,
                    aggressivity = 54,
                    life_value = 414,
                 ):
        self.nickname = nickname
        self.aggressivity = aggressivity
        self.life_value = life_value
        self.script = script
    
    def attack(self, enemy):
        print(self.script)
        enemy.life_value -= sefl.aggressivity


class Garen:
    camp = 'Demacia'
    def __init__(self, nickname,
                    script,
                    aggressivity=58,
                    life_value = 455,
                ):
        self.nickname = nickname
        self.aggressivity =aggressivity
        self.life_value = life_value
        self.script = script
        
    def attack(self, enenmy):
        print(self.script)
        enemy.life_value -= self.aggressivity

g1 = Garen("德玛西亚","人在塔在")
g1.camp="诺克萨斯"
r1=Riven("瑞文","断剑重铸之日,骑士归来之时")
g1.attack(r1)
print(r1.life_value)



result:

人在塔在
356

Garen类和Riven类都有nickname,aggressivity,life_value,script四个白能量属性和attack()函数属性,这里可以抽象出一个Hero类

class Hero:
    
    def __init__(self, nickname,
                    script,
                    aggressivity ,
                    life_value ,
                 ):
        self.nickname = nickname
        self.aggressivity = aggressivity
        self.life_value = life_value
        self.script = script
    
    def attack(self, enemy):
        print("Hero.attack")
        enemy.life_value -= sefl.aggressivity


class Riven(Hero):
    camp = 'Noxus'
    def __init__(self, nickname,
                    script,
                    aggressivity=54,
                    life_value = 414,
                ):
       Hero.__int__(self,nickname,script,aggressivity,life_value)
        
    def attack(self, enenmy):
        print(self.script)
        Hero.attack(self,enemy)

class Garen(Hero):
    camp = 'Demacia'
    def __init__(self, nickname,
                    script,
                    aggressivity=58,
                    life_value = 455,
                ):
       Hero.__init__(self,nickname,script,aggressivity,life_value)
        
    def attack(self, enenmy):
        print(self.script)
        Hero.attack(self,enemy)

g1 = Garen("德玛西亚","人在塔在")
g1.camp="诺克萨斯"
r1=Riven("瑞文","断剑重铸之日,骑士归来之时")
g1.attack(r1)
print(r1.life_value)



result:
人在塔在
Hero.attack
356

**严格来说,上述Hero.__init__(self,...),不能算作子类调用父类的方法。因为我们如果去掉(Hero)这个继承关系,代码仍能得到预期的结果。
总结python中继承的特点:
1. 在子类中,并不会自动调用基类的__init__(),需要在派生类中手动调用。
2. 在调用基类的方法时,需要加上基类的类名前缀,且需要带上self参数变量。
3. 先在本类中查找调用的方法,找不到才去基类中找。**

继承的好处

提高代码的复用。

继承的弊端

     可能特殊的本类又有其他特殊的地方,又会定义一个类,其下也可能再定义类,这样就会造成继承的那条线越来越长,使用继承的话,任何一点小的变化也需要重新定义一个类,很容易引起类的爆炸式增长,产生一大堆有着细微不同的子类. 所以有个“多用组合少用继承”的原则。

什么是派生

     派生就是子类在继承父类的基础上衍生出新的属性。子类中独有的,父类中没有的;或子类定义与父类重名的东西。子类也叫派生类。

 组合

代码复用的重要的方式除了继承,还有组合。
组合,在一个类中以另一个类的对象作为数据属性,称为类的组合。

 

class Skill:
    def fire(self):
        print("release Fire skill")

class Riven:
    camp='Noxus'
    def __init__(self,nickname):
        self.nickname=nickname
        self.skill5=Skill().fire()#Skill类产生一个对象,并调用fire()方法,赋值给实例的skill5属性

r1=Riven("瑞雯")



result:

release Fire skill

组合和继承的使用场景

  • 继承的方式
    通过继承建立了派生类与基类之间的关系,它是一种'是'的关系,比如白马是马,人是动物。
  • class Animal:
        def walk(self):
            print("Animal is walking")
        def eat(self):
            print("Animal is eating")
    
    class Person(Animal):
        pass
    
    p1=Person()
    p1.walk()   #Animal is walking

     

  • 组合的方式
    用组合的方式建立了类与组合的类之间的关系,它是一种‘有’的关系,比如老师有生日,老师教python课程。
class Teacher:
    def __init__(self,name,sex,course):
        self.name=name
        self.sex=sex
        self.course = course

class Course:
    def __init__(self, name, period):
        self.name = name
        self.period = period

co=Course("python","7 m")
t1=Teacher("zhang","male",co)
print(t1.course.name)



result:
 python

当类之间有显著不同,并且较小的类是较大的类所需要的组件时,用组合比较好。

接口和归一化设计

什么是接口?接口就是对外只提供抽象的方法的集合。

继承的两种用途:

  1. 继承基类的方法,并且做出自己的改变或者扩展(代码复用)
  2. 声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子类继承接口类,并且实现接口中的功能。
class Interface:#定义接口Interface类来模仿接口的概念,python中没有interface关键字来定义一个接口。
    def read(self): #定接口函数read
        pass
        #raise AttributeError("read function must be implemented")    #如果不重写read函数就报错
        
    def write(self): #定义接口函数write
        pass
        #raise AttributeError("wirte function must be implemented")    #如果不重写write函数就报错
        
class Txt(Interface): #文本,具体实现read和write
    def read(self):
        print('文本数据的读取方法')

    def write(self):
        print('文本数据的读取方法')

class Sata(Interface): #磁盘,具体实现read和write
    def read(self):
        print('硬盘数据的读取方法')

    def write(self):
        print('硬盘数据的读取方法')

 实践中,继承的第一种含义意义并不很大,甚至常常是有害的。因为它使得子类与基类出现强耦合。
     继承的第二种含义非常重要。它又叫“接口继承”。
     接口继承实质上是要求“做出一个良好的抽象,这个抽象规定了一个兼容接口,使得外部调用者无需关心具体细节,可一视同仁的处理实现了特定接口的所有对象”——这在程序设计上,叫做归一化。
     归一化使得高层的外部使用者可以不加区分的处理所有接口兼容的对象集合——就好象linux的泛文件概念一样,所有东西都可以当文件处理,不必关心它是内存、磁盘、网络还是屏幕(当然,对底层设计者,当然也可以区分出“字符设备”和“块设备”,然后做出针对性的设计:细致到什么程度,视需求而定)。

抽象类

什么是抽象类

     与java一样,python也有抽象类的概念,但是需要借助模块实现。抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化。
     抽象类与普通类的不同之处在于:抽象类中只能有抽象方法(没有实现功能),该类不能被实例化,只能被继承,且子类必须实现抽象方法。

class Interface(metaclass=abc.ABCMeta):  # 定义接口Interface类来模仿接口的概念,python中没有interface关键字来定义一个接口。
    @abc.abstractclassmethod
    def read(self):  # 定接口函数read
        pass

    @abc.abstractclassmethod
    def write(self):  # 定义接口函数write
        pass

class Txt(Interface):  # 文本,具体实现read和write
    def read(self):
        print('文本数据的读取方法')

    def write(self):
        print('文本数据的读取方法')

class Sata(Interface):  # 磁盘,具体实现read和write
    def read(self):
        print('硬盘数据的读取方法')

    def write(self):
        print('硬盘数据的读取方法')

抽象类与接口

     抽象类的本质还是类,抽象类的本质还是类,指的是一组类的相似性,包括数据属性(如all_type)和函数属性(如read、write),而接口只强调函数属性的相似性。
     抽象类是一个介于类和接口直接的一个概念,同时具备类和接口的部分特性,可以用来实现归一化设计 。

<think>好的,我现在需要回答用户关于Pythontypeisinstance区别的问题。首先,我得回忆一下这两个函数的基本用法区别。根据我之前学过的知识,type()用于获取对象的类型,而isinstance()则检查对象是否是某个类或其子类的实例。不过用户可能想知道更详细的区别使用场景,所以我得整理一下。 首先,我需要确认typeisinstance在语法上的不同。type通常只有一个参数,比如type(obj),返回的是对象的类型。而isinstance需要两个参数,对象类信息,比如isinstance(obj, int)。接下来,根据引用中的信息,特别是引用3提到的,type可以用于判断变量是否属于某个类型,并且可以得到未知变量的类型,而isinstance只能判断是否属于已知类型。这一点很重要,可能需要详细说明。 然后,引用3中的例子显示,当处理继承关系时,isinstance会认为子类实例属于父类,而type不会。例如,如果B是A的子类,那么isinstance(B(), A)返回True,而type(B()) == A返回False。这说明在继承结构中使用isinstance更合适,因为它考虑到了继承关系,而type严格检查类型是否完全一致。这部分需要强调,因为这是两者在面向对象编程中的一个关键区别。 接下来,用户可能想知道使用场景。根据引用4,isinstance常用于检查对象是否是特定类或其子类的实例,适用于需要多态性的情况。而type更适合精确的类型检查,比如确定对象的确切类型,不考虑继承。例如,当需要严格区分intbool时,虽然bool是int的子类,但type可以区分它们,而isinstance可能会认为bool对象也是int的实例,这可能需要特别注意。 还需要提到性能方面,虽然用户的问题中没有直接问到,但根据一些资料,isinstance可能稍微快一点,因为它是直接检查实例关系,而type需要返回整个类型对象进行比较。不过这点可能不是主要区别,但如果有引用支持的话可以提一下。 另外,引用2提到isinstance的第二个参数可以是元组,这样能检查对象是否是多个类型中的一个,这增加了灵活性。而type无法直接做到这一点,需要多次使用type或者结合其他方法。这也是isinstance的一个优势。 在总结时,应该分点列出区别,比如语法、继承处理、多类型检查、使用场景等,并结合实际例子说明。同时,引用中的例子解释要正确应用,比如引用3中的代码示例,需要确保正确性。最后,生成相关问题,帮助用户深入理解,比如关于继承中的类型检查、性能比较、替代方法等。 可能需要注意的误区是,用户可能认为typeisinstance在大多数情况下可以互换,但实际上在继承结构中有不同的行为,需要明确指出。此外,当检查是否为特定类型时,如果考虑子类,应使用isinstance;如果严格排除子类,使用type。 现在把这些点组织成一个结构清晰的回答,分步骤说明区别,并给出使用场景的建议。同时确保所有的数学表达式代码块符合格式要求,比如行内代码用反引号,独立代码块用三个反引号,并正确引用来源。</think>### Python中`type()``isinstance()`的区别使用场景 #### 1. **基本语法差异** - **`type()`**:接收一个参数,返回对象的类型。 ```python num = 10 print(type(num)) # <class 'int'> ``` - **`isinstance()`**:接收两个参数,检查对象是否是某类(或其子类)的实例。 ```python print(isinstance(10, int)) # True ``` #### 2. **继承关系处理** - **`isinstance()`** 会考虑继承关系,而 **`type()`** 不会。 例如,子类实例会被 `isinstance()` 识别为父类类型,但 `type()` 严格匹配: ```python class A: pass class B(A): pass obj = B() print(isinstance(obj, A)) # True [^3] print(type(obj) == A) # False [^3] ``` #### 3. **多类型检查** - **`isinstance()`** 支持检查多个类型(通过元组传入): ```python value = 3.14 print(isinstance(value, (int, float))) # True [^2] ``` - **`type()`** 需手动遍历或结合其他方法实现类似功能。 #### 4. **使用场景** - **需要精确类型匹配时用 `type()`** 例如,严格区分 `int` `bool`(虽然 `bool` 是 `int` 的子类): ```python flag = True print(type(flag) == int) # False print(isinstance(flag, int)) # True(因为bool继承自int) ``` - **需要兼容子类或多态性时用 `isinstance()`** 例如,函数参数检查是否属于某个基类: ```python def process(obj): if isinstance(obj, A): # 兼容A及其子类 print("Valid object") ``` #### 5. **性能灵活性** - **性能**:`isinstance()` 通常略快,因为它直接检查实例关系[^4]。 - **灵活性**:`isinstance()` 支持元组类型参数,更适合动态类型检查。 --- ### 总结对比表 | **特性** | **`type()`** | **`isinstance()`** | |-------------------|-------------------------------|-----------------------------------| | 继承关系处理 | 严格匹配类型 | 兼容父类 | | 多类型检查 | 不支持 | 支持(通过元组) | | 返回值 | 返回类型对象(如 `<class 'int'>`) | 返回布尔值(True/False) | | 典型应用场景 | 精确类型判断、获取未知变量类型 | 多态性检查、参数合法性验证 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值