python中的”type”和”object”有什么区别

What is the difference between a 'Type' and an 'Object' in Python

本问题已经有最佳答案,请猛点这里访问。

我是在阅读有关super关键字的python文档时发现的:

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

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

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

谢谢您。


python的super函数根据参数的不同执行不同的操作。下面是使用它的不同方法的演示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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)

测试输出:

1
2
3
4
5
6
7
8
9
10
11
12
>>> b1 = Base(0)
>>> b1.val
0
>>> b2 = Base.make_obj(0)
>>> b2.val
1
>>> d1 = Derived(0)
>>> d1.val
2
>>> d2 = Derived.make_obj(0)
>>> d2.val
3

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

注意,只使用一个参数就可以调用super来获得一个"未绑定"的超级对象,这显然不太有用。没有任何理由这样做,除非你想搞砸python的内部结构,并且你真的知道你在做什么。

在python 3中,也可以不带参数地调用super(这相当于将当前类和self作为两个参数提供,但更神奇)。


下面是对这两个函数的简单探索。我发现这项练习很有启发性。我经常会创建一个简单的程序来探索简单函数的输入和输出,并将其保存以供参考:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#
# 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可能会检查对象是否是字典,即使该对象支持字典样式的访问:被认为是有害的

编辑2:

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

在测试上述代码之后,它告诉我第二个参数必须是类型。因此,在以下情况下:

1
checkInstanceType(c1, b1)

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

1
checkInstanceType(c1, type(b1))

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


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