Python中的“Type”和“Object”有什么区别

2024-06-13 03:17:11 发布

您现在位置:Python中文网/ 问答频道 /正文

我在阅读super关键字上的pythondocumentation时偶然发现:

如果省略第二个参数,则返回的超级对象是未绑定的。如果第二个参数是对象,则isinstance(obj,type)必须为true。如果第二个参数是类型,则issubclass(type2,type)必须为true(这对于类方法很有用)。

有人能给我举个例子来说明将类型作为第二个参数传递与传递对象之间的区别吗?在

文档是否在讨论一个对象的实例?在

谢谢。在


Tags: 对象方法trueobj类型参数type关键字
3条回答

Python的super函数根据参数的不同而执行不同的操作。以下是使用不同方法的演示:

class Base(object):
    def __init__(self, val):
        self.val = val

    @classmethod
    def make_obj(cls, val):
        return cls(val+1)

class Derived(Base):
    def __init__(self, val):
        # In this super call, the second argument "self" is an object.
        # The result acts like an object of the Base class.
        super(Derived, self).__init__(val+2)

    @classmethod
    def make_obj(cls, val):
        # In this super call, the second argument "cls" is a type.
        # The result acts like the Base class itself.
        return super(Derived, cls).make_obj(val)

测试输出:

^{pr2}$

3的结果是前面修饰语的组合:1(来自Base.make_obj)加上2(来自Derived.__init__)。在

请注意,只需一个参数就可以调用super以获得“未绑定”的超级对象,这显然用处不大。没有任何理由这样做,除非你想搞乱Python的内部结构,而且你知道自己在做什么。在

在python3中,还可以不带参数调用super(这相当于上面函数中的调用,但更神奇)。在

对象可以是任何Python类实例,这些实例可能是用户定义的,也可能不是用户定义的。但是, 当你谈论类型时,它指的是默认的对象/集合,比如list/tuple/dict/int/str等

下面是对这两个函数的简单探讨。我觉得做这个练习很有启发性。我经常会创建一个简单的程序来探索简单函数的来龙去脉,并将它们保存起来以供参考:

#
# Testing isinstance and issubclass
#

class C1(object):
    def __init__(self):
        object.__init__(self)

class B1(object):
    def __init__(self):
        object.__init__(self)

class B2(B1):
    def __init__(self):
        B1.__init__(self)

class CB1(C1,B1):
    def __init__(self):
        # not sure about this for multiple inheritance
        C1.__init__(self)
        B1.__init__(self)

c1 = C1()
b1 = B1()
cb1 = CB1()

def checkInstanceType(c, t):
    if isinstance(c, t):
        print c, "is of type", t
    else:
        print c, "is NOT of type", t

def checkSubclassType(c, t):
    if issubclass(c, t):
        print c, "is a subclass of type", t
    else:
        print c, "is NOT a subclass of type", t

print "comparing isinstance and issubclass"
print ""

# checking isinstance
print "checking isinstance"

# can check instance against type
checkInstanceType(c1, C1)
checkInstanceType(c1, B1)
checkInstanceType(c1, object)

# can check type against type
checkInstanceType(C1, object)
checkInstanceType(B1, object)

# cannot check instance against instance
try:
    checkInstanceType(c1, b1)
except Exception, e:
    print "failed to check instance against instance", e

print ""

# checking issubclass
print "checking issubclass"

# cannot check instance against type
try:
    checkSubclassType(c1, C1)
except Exception, e:
    print "failed to check instance against type", e

# can check type against type
checkSubclassType(C1, C1)
checkSubclassType(B1, C1)
checkSubclassType(CB1, C1)
checkSubclassType(CB1, B1)

# cannot check type against instance
try:
    checkSubclassType(C1, c1)
except Exception, e:
    print "failed to check type against instance", e

编辑: 还应考虑以下问题,因为isinstance可能会破坏API实现。例如,一个对象的行为类似于字典,但不是从dict派生的。isinstance可能会检查对象是否是字典,即使该对象支持字典样式的访问: isinstance considered harmful

编辑2:

Can someone please give me an example of a distinction between passing a Type as a second argument versus passing an Object?

在测试了上面的代码之后,它告诉我第二个参数必须是一个类型。所以在以下情况下:

^{pr2}$

呼叫将失败。可以这样写:

checkInstanceType(c1, type(b1))

因此,如果要检查一个实例与另一个实例的类型,则必须使用type()内置调用。在

相关问题 更多 >