我在阅读Python 文档 中的 super
关键字时发现了这篇文章:
如果第二个参数被省略,则返回未绑定的super对象。如果第二个参数是一个对象,则必须为isinstance(obj, type)。如果第二个参数是一个类型,则必须为issubclass(type2, type),这对于类方法很有用。
请问是否能举例说明传递类型作为第二个参数和传递对象作为第二个参数之间的区别?
这份文档是否在讨论对象的实例?
非常感谢。
我在阅读Python 文档 中的 super
关键字时发现了这篇文章:
如果第二个参数被省略,则返回未绑定的super对象。如果第二个参数是一个对象,则必须为isinstance(obj, type)。如果第二个参数是一个类型,则必须为issubclass(type2, type),这对于类方法很有用。
请问是否能举例说明传递类型作为第二个参数和传递对象作为第二个参数之间的区别?
这份文档是否在讨论对象的实例?
非常感谢。
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
(这相当于上面函数中的调用,但更神奇)。
对象可以是任何Python类实例,可能是用户定义的,也可能不是。但是,当你谈论一个类型时,它指的是默认的对象/集合,比如列表/元组/字典/整数/字符串等。
这里是两个函数的简单探索。通过这个练习,我发现它很有启发性。我经常会创建一个简单的程序来探索简单函数的内部结构,并将它们保存作为参考:
#
# 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()内置调用。