我觉得你正在投入实际上并不存在的差异。实际上并没有这样的等级制度。在 python中,一切都是对象。这不是一些抽象的概念,但对于您应该如何考虑使用 python 时创建的构造非常基础。一个对象只是一堆其他对象。是否使用新式类有一点微妙之处,但如果没有充分的理由,请使用并假设新式类。下面的一切都是假设新式的类。
如果一个对象是callable,你可以使用一对大括号的调用语法来调用它,其中包含参数:my_callable(arg1, arg2)
。为了可调用,对象需要实现该__call__
方法(或者在其 C 级类型定义中设置正确的字段)。
在 python 中,一个对象有一个type
与之关联的对象。类型描述了对象是如何构造的。因此,例如,列表对象是 type list
,而函数对象是 type function
。类型本身是 type type
。您可以使用内置函数找到类型type()
。所有内置类型的列表可以在 python文档中找到。类型实际上是可调用对象,用于创建给定类型的实例。
对,现在已经确定了,给定对象的性质由它的类型定义。这描述了它所包含的对象。然后回到你的问题:
首先,构成某个对象的一堆对象称为该对象的属性。这些属性可以是任何东西,但它们通常由方法和某种存储状态的方式(可能是诸如int
or之类的类型list
)组成。
函数是类型的对象function
。至关重要的是,这意味着它具有该__call__
方法作为属性,这使其成为可调用的(该__call__
方法也是一个本身具有该__call__
方法的对象。它__call__
一直向下;)
在 python 世界中,一个class可以被视为一种类型,但通常用于引用非内置类型。这些对象用于创建其他对象。您可以使用 class 关键字定义自己的类,并创建一个必须继承自object
(或其他一些新样式类)的新样式类。当你继承时,你创建了一个类型,它获取了父类型的所有特征,然后你可以覆盖你想要的位(你可以覆盖任何你想要的位!)。当您通过调用一个类(或更一般地,一个类型)来实例化它时,会返回另一个由该类创建的对象(通过修改类对象可以以奇怪和疯狂的方式更改返回对象的创建方式)。
方法是使用属性表示法调用的特殊类型的函数。也就是说,当它被创建时,两个额外的属性被添加到方法中(记住它是一个对象!),称为im_self
和im_func
。im_self
我会用几句话来描述。im_func
是实现该方法的函数。当方法被调用时,例如 ,foo.my_method(10)
这相当于调用foo.my_method.im_func(im_self, 10)
。这就是为什么当你定义一个方法时,你用你似乎没有使用的额外的第一个参数来定义它(as self
)。
当你在定义一个类的时候写了一堆方法,这些就变成了未绑定的方法。当您创建该类的实例时,这些方法将变为bound。当您调用绑定方法时,im_self
会为您添加参数作为绑定方法所在的对象。您仍然可以调用类的未绑定方法,但您需要显式添加类实例作为第一个参数:
class Foo(object):
def bar(self):
print self
print self.bar
print self.bar.im_self # prints the same as self
我们可以展示当我们调用 bar 方法的各种表现时会发生什么:
>>> a = Foo()
>>> a.bar()
<__main__.Foo object at 0x179b610>
<bound method Foo.bar of <__main__.Foo object at 0x179b610>>
<__main__.Foo object at 0x179b610>
>>> Foo.bar()
TypeError: unbound method bar() must be called with Foo instance as first argument (got nothing instead)
>>> Foo.bar(a)
<__main__.Foo object at 0x179b610>
<bound method Foo.bar of <__main__.Foo object at 0x179b610>>
<__main__.Foo object at 0x179b610>
综合以上所有内容,我们可以定义一个类,如下所示:
class MyFoo(object):
a = 10
def bar(self):
print self.a
这将生成一个具有 2 个属性的类:(a
它是一个值为 10 的整数)和bar
,它是一个未绑定的方法。我们可以看到MyFoo.a
只有 10 个。
我们可以在运行时在类方法内部和外部创建额外的属性。考虑以下:
class MyFoo(object):
a = 10
def __init__(self):
self.b = 20
def bar(self):
print self.a
print self.b
def eep(self):
print self.c
__init__
只是从类创建对象后立即调用的方法。
>>> foo = Foo()
>>> foo.bar()
10
20
>>> foo.eep()
AttributeError: 'MyFoo' object has no attribute 'c'
>>> foo.c = 30
>>> foo.eep()
30
此示例显示了在运行时(即在从其类创建对象之后)向类实例添加属性的 2 种方法。
我希望你能看到,TestCase 和 TestSuite 只是用于创建测试对象的类。它们没有什么特别之处,只是它们碰巧有一些用于编写测试的有用功能。您可以根据自己的喜好对它们进行子类化和覆盖!
关于您的具体观点,方法和函数都可以返回他们想要的任何内容。
您对模块、包和套件的描述似乎很合理。请注意,模块也是对象!