Python中类属性、实例属性和实例方法的区别

4
我知道类似的问题以前已经被问过了,但每个网站似乎都有不同的定义,我试图遵循官方文档: 就我目前所理解的:
- 类属性是指在class Classname:代码块中列出的所有内容,包括在__init__函数上面的变量声明、静态方法、类方法和涉及到实例并使用self的方法
更多信息请参见链接:https://docs.python.org/2/tutorial/classes.html#class-objects
- 实例属性既包括:1.) 在class Classname:代码块中列出的除变量声明以外的所有函数,也就是__init__函数上面的内容 & 2.) 数据属性,即当我们使用instance.attr并将其设置为某个值时
更多信息请参见链接:https://docs.python.org/2/tutorial/classes.html#instance-objects

假设我上面写的一切都正确,那么我可以说实例方法是class Classname:代码块中的任何函数,因为我们可以将每个方法应用于实例对象,或者只是涉及到self的函数。

我不确定我是哪里理解不正确,但Python文档的术语与我看过的其他网站完全不同。非常感谢您的帮助。谢谢!

4个回答

4

类属性是对于类的所有实例都相同的,而实例属性是每个实例特定的。实例属性用于每个实例的数据,而类属性则用于类的所有实例。

"实例方法"是一种特定的类属性,它接受类的实例作为第一个属性,并且可以用来操作该实例。

"类方法"是在类中定义的方法,其第一个属性为类本身而不是实例(这就是它们被称为类方法的原因)。

您可以通过访问A.__dict__轻松查看类属性:

class A:
   class_attribute = 10
   def class_method(self):
       self.instance_attribute = 'I am instance attribute'

print A.__dict__
#{'__module__': '__main__', 'class_method': <function class_method at 0x10978ab18>, 'class_attribute': 10, '__doc__': None}

实例属性可以使用A().__dict__来获取:

a = A()
a.class_method()
print a.__dict__
# {'instance_attribute': 'I am instance attribute'}

以下是官方 Python 文档和 Stack Overflow 上的一些有用链接,希望这些链接可以使你更加清晰地理解:


3
要回答这个问题,你需要先考虑Python如何查找属性。我假设你知道什么是实例。作为复习...
class SomeClass(object):

    class_attribute = 'This -- Defined at the class level.'

    def __init__(self):
        self.instance_attribute = 'This -- Defined on an instance.'

    def method(self):
        pass

instance = SomeClass()

类属性是在类级别上定义的。实例属性是在实例级别上定义的(通常通过self.xyz = ...)。实例属性也可以被“monkey patching”到实例上:

instance.another_instance_attribute = '...'

请注意,如果实例属性没有“遮盖”它,类属性可以在实例上查找。
print(instance.class_attribute)

现在来谈方法。方法是完全不同的东西。
SomeClass.method

is definitely an attribute on the class.

instance.method

这个有点棘手。实际上,当 Python 看到这个语句时,它实际上执行以下内容:

SomeClass.method.__get__(instance, SomeClass)

很奇怪。所以这里发生的事情是函数是“描述符”。由于它们有一个__get__方法,因此会调用该方法,并返回(在本例中)具有了self信息的新函数。正常术语是“实例方法”和“绑定方法”。我想有些人可能认为它是实例属性,但是我不确定这完全正确(尽管你通过实例访问它)。


0
类属性 - 是在类名:代码块中列出的所有内容,它可以在任何方法的上方或下方。
实例属性 - 通过使用instance.attr或self.attr创建(这里的self仅是实例对象)
class Base:
  cls_var = "class attribute"
  def __init__(self):
    self.var = "instance attribute"
  def method(self):
    self.var1 = "another instance attribute"
  cls_var1 = "another class attribute"

类属性和实例对象 - 您可以将类对象视为其所有实例对象的父级。因此,实例对象可以访问类对象的属性。但是,在类体中定义的任何内容都仅属于类属性。
class Base:
  cls_var = "class attribute"
  def __init__(self):
    self.var = "instance attribute"
b = Base()
print b.var                                     # it should print "instance attribute"
print b.cls_var                                 # it should print "class attribute"
print Base.cls_var                              # it should print "class attribute"
b.cls_var = "instance attribute"
print Base.cls_var                            # it should print "class attribute"
print b.cls_var                                # it should print "instance attribute"

实例方法 - 在类体内使用def语句创建的方法,实例方法是其第一个参数将是实例对象(self)的方法。 但是所有实例方法都是类属性,您可以通过实例对象访问它,因为实例是类对象的子类。
>>> class Base:
    def ins_method(self):
        pass


>>> b = Base()
>>> Base.__dict__
{'__module__': '__main__', '__doc__': None, 'ins_method': <function ins_method at 0x01CEE930>}
>>> b.__dict__
{}

你可以通过使用类对象并将实例作为其第一个参数来访问实例方法 -

Base.ins_method(Base())

您可以参考我写的这两篇关于同一主题的文章,其中有图解和解释。如果您有任何问题,请随时联系我:

http://www.pythonabc.com/python-class-easy-way-understand-python-class/ http://www.pythonabc.com/instance-method-static-method-and-class-method/

0

你似乎对这些概念有相当不错的掌握。很难找到以通用方式解释信息,特别是像 Python 这样广泛使用的语言。我大多数时候会 echo 你的正确假设,并在途中进行一些微小的调整。

类属性是所有从该类创建的对象共享的特征。例如,如果我们定义了一个 clock 类,我们将定义一个类属性作为时钟中可能的总小时数。

class Clock:
    class_hours = 12

它由类的所有实例共享,可以被任何实例访问以供参考。

类实例是我们用来定义从类创建的对象的个体特征的实际数据。再次使用clock类的示例,这将是我们在代码行中创建时设置时钟的实际小时数(我们还可以引用我们的类属性以确保它在可接受的参数范围内):

class Clock:
    class_hours = 12

    def __init__(self, hours):
        if (hours <= class_hours):
            self.hours = hours

请记住,在构造函数中使用if语句并不是一个好的实践,但这只是为了举例说明。如果您真的想要实现这个例子,您应该使用实例方法来确保小时数在定义的范围内。

实例方法是我们在类中定义的可以操作我们在构造函数中定义的类实例数据的方法。回到clock的例子中,我们可以定义一个方法来改变时钟的小时、分钟或秒:

class Clock:
    class_hours = 12
    class_minutes = 60
    class_seconds = 60

    def __init__(self, hours, minutes, seconds):
        self.hours = hours
        self.minutes = minutes
        self.seconds = seconds

    def setTime(new_hour, new_minute, new_second):
        self.hours = new_hour
        self.minutes = new_minute
        self.seconds = new_second

这使我们能够在代码的某个地方更改已经创建的clock实例。例如,调用clock.setTime(11,49,36)会将该特定时钟实例设置为11:49:36。

我希望这对您有所帮助,并且尽可能清晰明了。如果我表述不清或者涉及到您不理解的任何术语,请告诉我,以便我可以更新我的答案,让它尽可能清晰。


谢谢您的回复!我的主要问题是文档字面上有一行:“根据定义,类的所有属性都是函数对象,定义了其实例的相应方法。”而关于类属性的另一部分说,类属性是命名空间下类中的任何内容,包括涉及self的函数。那么类属性不就是类代码块中的所有内容,实例方法不就是类代码块中的所有函数吗?我理解您上面写的内容,但它似乎与网站上所写的有很大的不同。 - Slade

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