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

28

我在阅读Python 文档 中的 super 关键字时发现了这篇文章:

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

请问是否能举例说明传递类型作为第二个参数和传递对象作为第二个参数之间的区别?

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

非常感谢。


9
这应该会给你一些视角:http://www.cafepy.com/article/python_types_and_objects/python_types_and_objects.html#object-type-example - karthikr
@karthikr 同意,好文章。 - jamylak
3
请看这个问题https://dev59.com/WnVD5IYBdhLWcg3wE3Ro?rq=1和精彩回答,虽然它是关于元类的,但它详细介绍了类型和对象来构建元类的描述——非常好的阅读材料。 - Tim Hoffman
真是个很棒的问题。我一直在尝试在 Python(我的唯一语言)中自学面向对象编程,努力使用继承和调用超类方法。我读了有关 super 的解释,也有同样的疑问。 - cfwschmidt
这并不完全是一个重复的问题。从技术上讲,它是,但从人体工程学的角度来看,我不这么认为。我认为这个答案应该有一个不同的重点,而不仅仅是关于元类的解释。例如,它可以引导我们讨论为什么对象被评估为类型的实例,而类型也被评估为对象的实例。@MartijnPieters - user4396006
我认为这是一个更好的重复问题 https://stackoverflow.com/questions/44835369/what-are-the-relations-between-classes-type-and-object - user4396006
3个回答

11

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)

测试输出:

>>> 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(这相当于上面函数中的调用,但更神奇)。


super是帮助函数调用记忆化的一种方式吗?我有一个对象,通过检查函数是否存在并将属性分配给直接调用该函数的对象来加速对另一个解释器的调用。因此,我基本上只查找一次函数并将其记忆到可调用属性中。为了防止循环/调用“__settr__”重新定义,我必须使用object.setattr(self, "attribute", callableObj)。super是否也可以做同样的事情? - Demolishun
@Demolishun:不,你使用super来获取被覆盖的方法的继承版本。请查看文档 - Blckknght
好的,所以它很相似,但它允许动态引用基类,但不是通过名称。这是一个用例。http://rhettinger.wordpress.com/2011/05/26/super-considered-super/感谢参考。 - Demolishun

0

对象可以是任何Python类实例,可能是用户定义的,也可能不是。但是,当你谈论一个类型时,它指的是默认的对象/集合,比如列表/元组/字典/整数/字符串等。


就此而言,我不同意,它并不仅限于内置类型。每个人都可以并且确实定义自己的类型。 - user395760
@smitkpatel,我认为你可能在考虑“内置”类型。 - Demolishun
内置 - 默认土豆 - 土豆 - smitkpatel

0

这里是两个函数的简单探索。通过这个练习,我发现它很有启发性。我经常会创建一个简单的程序来探索简单函数的内部结构,并将它们保存作为参考:

#
# 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:

请问有人能够举出传递 Type 作为第二个参数和传递 Object 之间的区别的例子吗?

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

checkInstanceType(c1, b1)

调用将失败。它可以这样写:

checkInstanceType(c1, type(b1))

因此,如果您想将一个实例的类型与另一个实例进行比较,您必须使用type()内置调用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接