类变量和实例变量有什么区别?

2025-02-20 09:25:00
admin
原创
27
摘要:问题描述:Python 中的类变量和实例变量有什么区别?class Complex: a = 1 和class Complex: def __init__(self): self.a = 1 使用调用:x = Complex().a在两种情况下都将 x 分配给 1。如能提供更深...

问题描述:

Python 中的类变量和实例变量有什么区别?

class Complex:
    a = 1

class Complex:
    def __init__(self):
        self.a = 1

使用调用:x = Complex().a在两种情况下都将 x 分配给 1。

如能提供更深入的解答__init__(),我们self将不胜感激。


解决方案 1:

编写类块时,会创建类属性(或类变量)。您在类块中指定的所有名称(包括您定义的方法)都def将成为类属性。

创建类实例后,任何引用该实例的对象都可以在其上创建实例属性。在方法内部,“当前”实例几乎总是与名称绑定self,这就是您将这些视为“自变量”的原因。通常在面向对象的设计中,附加到类的代码应该可以控制该类实例的属性,因此几乎所有实例属性分配都是在方法内部完成的,使用self方法参数中收到的对实例的引用。

类属性通常与Java、C# 或 C++ 等语言中的静态变量(或方法)进行比较。但是,如果您想更深入地理解,我会避免将类属性视为与静态变量“相同”。虽然它们通常用于相同的目的,但底层概念却截然不同。有关此内容的更多信息,请参阅下面的“高级”部分。

一个例子!

class SomeClass:
    def __init__(self):
        self.foo = 'I am an instance attribute called foo'
        self.foo_list = []

    bar = 'I am a class attribute called bar'
    bar_list = []

执行此块后,有一个类SomeClass,具有3个类属性:__init__,,barbar_list

然后我们将创建一个实例:

instance = SomeClass()

发生这种情况时,将执行SomeClass__init__方法,并在其参数中接收新实例self。此方法创建两个实例属性:foofoo_list。然后将此实例分配给instance变量,因此它与具有这两个实例属性的事物绑定:foofoo_list

但:

print instance.bar

给出:

I am a class attribute called bar

这是怎么发生的?当我们尝试通过点语法检索属性时,如果该属性不存在,Python 会执行一系列步骤来尝试满足您的请求。它接下来会尝试查看实例的类的类属性bar。在本例中,它在 中找到了一个属性SomeClass,因此返回了该属性。

顺便说一下,这也是方法调用的工作原理。mylist.append(5)例如,当您调用 时,mylist没有名为 的属性append。但是的mylist有,并且它绑定到方法对象。该方法对象由位返回mylist.append,然后(5)位使用参数 调用该方法5

这样做的好处是,所有的实例都SomeClass可以访问同一个bar属性。我们可以创建一百万个实例,但我们只需要将一个字符串存储在内存中,因为它们都可以找到它。

但你得小心一点。看看下面的操作:

sc1 = SomeClass()
sc1.foo_list.append(1)
sc1.bar_list.append(2)

sc2 = SomeClass()
sc2.foo_list.append(10)
sc2.bar_list.append(20)

print sc1.foo_list
print sc1.bar_list

print sc2.foo_list
print sc2.bar_list

您认为这会打印出什么?

[1]
[2, 20]
[10]
[2, 20]

这是因为每个实例都有自己的 副本foo_list,因此它们被分别附加到 。但所有实例共享对同一个 的访问权限bar_list。因此当我们这样做时,sc1.bar_list.append(2)它会影响sc2,即使sc2它还不存在!同样sc2.bar_list.append(20)会影响bar_list通过 检索的sc1。这通常不是您想要的。


接下来是高级研究。:)

为了真正理解 Python,从 Java 和 C# 等传统静态类型 OO 语言开始,您必须学会重新思考一些类。

在 Java 中,类本身并不是一个真正的事物。当你编写一个类时,你更多的是在声明该类的所有实例都具有的一堆共同点。在运行时,只有实例(和静态方法/变量,但这些实际上只是与类关联的命名空间中的全局变量和函数,与 OO 无关)。类是你在源代码中写下实例在运行时的样子的方式;它们只“存在”在你的源代码中,而不是在正在运行的程序中。

在 Python 中,类并没有什么特别之处。它就像其他任何东西一样,是一个对象。因此,“类属性”实际上与“实例属性”完全相同;实际上只有“属性”。进行区分的唯一原因是我们倾向于以不同的方式使用属于类的对象和非属于类的对象。底层机制都是一样的。这就是为什么我说将类属性视为其他语言中的静态变量是错误的。

但 Python 类与 Java 风格的类的真正不同之处在于,就像任何其他对象一样,每个类都是某个类的实例

在 Python 中,大多数类都是内置类的实例,称为type。这个类控制类的常见行为,并使所有 OO 内容都按照它的方式进行。默认的 OO 方式是让类的实例具有自己的属性,并具有由其类定义的常见方法/属性,这只是 Python 中的一种协议。您可以根据需要更改它的大部分方面。如果您听说过使用元类,那么它就是定义一个类,该类是 之外的另一个类的实例type

关于类,唯一真正“特殊”的事情(除了所有使它们按照默认方式工作的内置机制之外)是类块语法,它使您可以更轻松地创建实例type。这:

class Foo(BaseFoo):
    def __init__(self, foo):
        self.foo = foo

    z = 28

大致相当于以下内容:

def __init__(self, foo):
    self.foo = foo

classdict = {'__init__': __init__, 'z': 28 }

Foo = type('Foo', (BaseFoo,), classdict)

并且它将安排的所有内容classdict成为所创建对象的属性。

因此,很容易看出,您可以通过Class.attribute轻松访问类属性i = Class(); i.attributei和都是Class对象,而对象具有属性。 这也使您很容易理解如何在创建类后对其进行修改;只需像分配其他对象一样分配其属性即可!

实际上,实例与用于创建它们的类没有特别特殊的关系。Python 通过隐藏__class__属性来知道在哪个类中搜索实例中未找到的属性。您可以读取它以找出这是哪个类的实例,就像任何其他属性一样:c = some_instance.__class__。现在您有一个c绑定到类的变量,即使它可能与类的名称不同。您可以使用它来访问类属性,甚至可以调用它来创建更多实例(即使您不知道它是什么类!)。

您甚至可以分配给i.__class__来更改它是哪个类的实例!如果您这样做,不会立即发生任何特别的事情。这并不是惊天动地的。它的全部含义是,当您查找实例中不存在的属性时,Python 将会查看 的新内容__class__。由于这包括大多数方法,并且方法通常期望它们操作的实例处于某些状态,因此如果您随机执行此操作,通常会导致错误,并且这非常令人困惑,但这是可以做到的。如果您非常小心,您存储的东西__class__甚至不必是一个类对象;Python 要做的就是在特定情况下查找属性,因此您所需要的只是一个具有正确类型属性的对象(除了一些警告,Python 确实会挑剔事物是类还是特定类的实例)。

现在可能就够了。希望(如果你已经读到这里)我没有让你感到太困惑。当你了解了 Python 的工作原理后,你会发现它很棒。:)

解决方案 2:

你所说的“实例”变量实际上并不是一个实例变量;它是一个类变量。请参阅有关类的语言参考。

在您的示例中,它a似乎是一个实例变量,因为它是不可变的。当您分配一个可变对象时,可以看到它作为类变量的性质:

>>> class Complex:
>>>    a = []
>>>
>>> b = Complex()
>>> c = Complex()
>>> 
>>> # What do they look like?
>>> b.a
[]
>>> c.a
[]
>>> 
>>> # Change b...
>>> b.a.append('Hello')
>>> b.a
['Hello']
>>> # What does c look like?
>>> c.a
['Hello']

如果使用self,那么它将是一个真正的实例变量,因此每个实例都有自己独特的。创建新实例时,将调用a对象的函数,并且是该实例的引用。__init__`self`

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1267  
  IPD(Integrated Product Development)即集成产品开发,是一套先进的、成熟的产品开发管理理念、模式和方法。随着市场竞争的日益激烈,企业对于提升产品开发效率、降低成本、提高产品质量的需求愈发迫切,IPD 项目管理咨询市场也迎来了广阔的发展空间。深入探讨 IPD 项目管理咨询的市场需求与发展,...
IPD集成产品开发流程   27  
  IPD(Integrated Product Development)产品开发流程是一套先进的、被广泛应用的产品开发管理体系,它涵盖了从产品概念产生到产品推向市场并持续优化的全过程。通过将市场、研发、生产、销售等多个环节紧密整合,IPD旨在提高产品开发的效率、质量,降低成本,增强企业的市场竞争力。深入了解IPD产品开发...
IPD流程中TR   31  
  IPD(Integrated Product Development)测试流程是确保产品质量、提升研发效率的关键环节。它贯穿于产品从概念到上市的整个生命周期,对企业的成功至关重要。深入理解IPD测试流程的核心要点,有助于企业优化研发过程,打造更具竞争力的产品。以下将详细阐述IPD测试流程的三大核心要点。测试策略规划测试...
华为IPD   26  
  华为作为全球知名的科技企业,其成功背后的管理体系备受关注。IPD(集成产品开发)流程作为华为核心的产品开发管理模式,在创新管理与技术突破方面发挥了至关重要的作用。深入剖析华为 IPD 流程中的创新管理与技术突破,对于众多企业探索自身发展路径具有重要的借鉴意义。IPD 流程概述IPD 流程是一种先进的产品开发管理理念和方...
TR评审   26  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用