栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

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

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

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

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__
bar
,和
bar_list

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

instance = SomeClass()

发生这种情况时,将执行

SomeClass
__init__
方法,并在其
self
参数中接收新实例。此方法创建两个实例属性:
foo
foo_list
。然后将此实例分配到
instance
变量中,因此将其绑定到具有这两个实例属性的事物:
foo
foo_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_listprint sc1.bar_listprint sc2.foo_listprint 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 = fooclassdict = {'__init__': __init__, 'z': 28 }Foo = type('Foo', (baseFoo,) classdict)

并且它将安排所有内容

classdict
成为要创建的对象的属性。

因此,看到您可以

Class.attribute
像一样轻松地访问class属性变得微不足道
i = Class();i.attribute
。这两个
i
Class
的对象,对象也有属性。这也使您易于理解在创建类后如何修改它。只需像对待其他对象一样分配属性即可!

实际上,实例与用于创建实例的类没有特殊的特殊关系。Python知道在哪个类中搜索实例中未找到的
__class__
属性的方式是通过hidden属性。与其他任何属性一样,您可以阅读以了解其是哪个类的实例`c

some_instance.class

。现在,您已经有了一个
c`绑定到类的变量,即使它的名称可能与该类的名称不同。您可以使用它来访问类属性,甚至可以调用它来创建它的更多实例(即使您不知道它是什么类!)。

您甚至可以分配

i.__class__
更改其实例的类!如果执行此操作,则不会立即发生任何特别的事情。这不是惊天动地。这意味着,当您查找实例中不存在的属性时,Python会查看的新内容
__class__
。由于其中包括大多数方法,并且方法通常希望它们所操作的实例处于特定状态,因此,如果您随机执行操作,通常会导致错误,这非常令人困惑,但是可以做到。如果您非常小心,请存放在里面的东西
__class__
甚至不必成为类对象;Python要做的所有事情就是在特定情况下查找属性,因此您所需要的只是具有正确种类的属性的对象(除了一些警告,Python确实对类或特定类的实例有些挑剔)。

现在可能就足够了。希望(如果您还读过这么远的话)我没有对您感到困惑。当您了解Python的工作原理时,Python十分简洁。:)



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/660706.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号