在_init__中定义成员与在python的类体中定义成员之间的区别?

在_init__中定义成员与在python的类体中定义成员之间的区别?,python,class,init,Python,Class,Init,这两者的区别是什么 class a: def __init__(self): self.val=1 做 class a: val=1 def __init__(self): pass 这就创建了一个类(在Py2中,一个粗糙的、遗留的、老式的,不要这样做!类;在Py3中,讨厌的旧遗留类终于消失了,所以这将是唯一的一种类-**good*类,需要Py2中的类a(对象):)这样,每个实例都以自己对integer对象的引用开始1 class a: v

这两者的区别是什么

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

class a:
   val=1
   def __init__(self):
       pass
这就创建了一个类(在Py2中,一个粗糙的、遗留的、老式的,不要这样做!类;在Py3中,讨厌的旧遗留类终于消失了,所以这将是唯一的一种类-**good*类,需要Py2中的
类a(对象):
)这样,每个实例都以自己对integer对象的引用开始
1

class a:
   val=1
   def __init__(self):
       pass
这将创建一个类(同类),该类本身具有对integer对象的引用
1
(其实例开始时没有每个实例引用)

对于像
int
值这样的不可变值,很难看到实际的区别。例如,在任何一种情况下,如果您稍后对
a
的一个实例执行
self.val=2
,这将成为一个实例引用(现有答案在这方面大错特错)

这种区别对于可变对象很重要,因为它们有mutator方法,所以知道某个列表是每个实例唯一的还是在所有实例之间共享的是非常关键的。但是对于不可变的对象,由于您永远不能更改对象本身,只能分配(例如,to
self.val
,它将始终进行每个实例的引用),所以它非常小


几乎是不可变的唯一相关区别:如果以后分配
a.val=3
,在第一种情况下,这将影响每个实例所看到的
self.val
(分配了自己的
self.val
的实例或等效操作除外);在第二种情况下,它不会影响任何实例所看到的
self.val
(除了您已执行
del self.val
或等效操作的实例)。

如其他人所述,在一种情况下,它是类上的属性,而在另一种情况下,它是实例上的属性。这有关系吗?是的,有一次是这样。正如Alex所说,如果值是可变的。最好的解释是代码,所以我将添加一些代码来显示它(这就是这个答案的全部功能,真的):

首先是定义两个实例属性的类

>>> class A(object):
...     def __init__(self):
...         self.number = 45
...         self.letters = ['a', 'b', 'c']
... 
>>> class B(object):
...     number = 45
...     letters = ['a', 'b', 'c']
... 
然后是定义两个类属性的类

>>> class A(object):
...     def __init__(self):
...         self.number = 45
...         self.letters = ['a', 'b', 'c']
... 
>>> class B(object):
...     number = 45
...     letters = ['a', 'b', 'c']
... 
现在我们使用它们:

>>> a1 = A()
>>> a2 = A()
>>> a2.number = 15
>>> a2.letters.append('z')
一切都很好:

>>> a1.number
45
>>> a1.letters
['a', 'b', 'c']
现在使用类属性变体:

>>> b1 = B()
>>> b2 = B()
>>> b2.number = 15
>>> b2.letters.append('z')
一切都是……嗯

>>> b1.number
45
>>> b1.letters
['a', 'b', 'c', 'z']
是的,请注意,当您更改时,所有类的可变类属性都会更改。这通常不是你想要的


如果您使用的是ZODB,那么您会使用大量的类属性,因为这是一种使用新属性升级现有对象或添加不持久化的类级别信息的便捷方法。否则,您几乎可以忽略它们。

其他人已经解释了技术差异。我将尝试解释为什么您可能希望使用类变量

如果只实例化一次类,那么类变量实际上就是实例变量。然而,如果您正在制作许多副本,或者希望在几个实例之间共享状态,那么类变量非常方便。例如:

class Foo(object):
    def __init__(self):
        self.bar = expensivefunction()

myobjs = [Foo() for _ in range(1000000)]
将导致expensivefunction()被调用一百万次。如果每次返回相同的值,比如从一个数据库中获取一个配置参数,那么你应该考虑把它移到类定义中,这样它只能调用一次,然后在所有实例中共享。 在记录结果时,我也经常使用类变量。例如:

class Foo(object):
    bazcache = {}

    @classmethod
    def baz(cls, key):
        try:
            result = cls.bazcache[key]
        except KeyError:
            result = expensivefunction(key)
            cls.bazcache[key] = result
        return result
在这种情况下,baz是一个类方法;其结果不依赖于任何实例变量。这意味着我们可以在类变量中保留结果缓存的一个副本,这样1)就不会多次存储相同的结果,2)每个实例都可以从其他实例缓存的结果中获益

举例来说,假设您有一百万个实例,每个实例都在谷歌搜索结果上运行。您可能更希望所有这些对象共享这些结果,而不是让每个对象执行搜索并等待答案


所以我不同意Lennart的观点。类变量在某些情况下非常方便。当它们是工作的合适工具时,请毫不犹豫地使用它们。

在几天内重复相同的问题?家庭作业?请看一看我发布的其他问题,例如:或者这个:(我怀疑有多少学校有fogbugz帐户:))还有,如果有任何地方可以看到用户的IP-我很确定另一个人和我不是来自同一个国家。