类__init __()函数内部和外部的变量

Tei*_*ion 173 python oop class

我试图理解,除了这个名字之外,这些类之间是否有任何区别?如果我在声明变量"value"时使用或不使用__init __()函数会有什么不同吗?

class WithClass ():
    def __init__(self):
        self.value = "Bob"
    def my_func(self):
        print(self.value)

class WithoutClass ():
    value = "Bob"

    def my_func(self):
        print(self.value)
Run Code Online (Sandbox Code Playgroud)

我主要担心的是,我将以一种方式使用它,因为这将导致我的问题进一步发展(目前我使用init调用).

S.L*_*ott 215

外部的变量集__init__属于该类.它们由所有实例共享.

内部__init__(和所有其他方法函数)创建的变量和前面的变量self.属于对象实例.

  • 这有点误导.__init__外部的`varname`variable集合属于该类,可以通过`self.varname`读取,为所有实例生成相同的值.但是,当通过实例引用分配值时(如在`self.varname = X`中),将为该实例only_创建_new_ self.varname,隐藏类变量.类var仍然可以通过类引用来访问(例如:`WithClass.varname`).类变量也可以通过任何方法设置,方法是使用类名(`WithClass.myvar = X`)而不是实例引用(`self.myvar = X`). (32认同)
  • 这不是python为我所做的。如果您不在 `__init__()` 中创建列表/dicts/etc 在所有实例之间共享。 (3认同)
  • @too很多php:类方法中的所有变量(不论可变性 - 列表和dicts都是可变的)都是共享的.对于不可变对象,共享并不有趣.对于可变对象(列表和dicts),共享非常重要. (3认同)

nor*_*ben 75

没有自我

创建一些对象:

class foo(object):
    x = 'original class'

c1, c2 = foo(), foo()
Run Code Online (Sandbox Code Playgroud)

我可以更改c1实例,它不会影响c2实例:

c1.x = 'changed instance'
c2.x
>>> 'original class'
Run Code Online (Sandbox Code Playgroud)

但是如果我更改了foo类,那么该类的所有实例也将被更改:

foo.x = 'changed class'
c2.x
>>> 'changed class'
Run Code Online (Sandbox Code Playgroud)

请注意Python范围如何在这里工作:

c1.x
>>> 'changed instance'
Run Code Online (Sandbox Code Playgroud)

随着自我

更改类不会影响实例:

class foo(object):
    def __init__(self):
        self.x = 'original self'

c1 = foo()
foo.x = 'changed class'
c1.x
>>> 'original self'
Run Code Online (Sandbox Code Playgroud)

  • 请注意,此示例仅适用于新类型类,对于旧类型,它们将具有相同的结果 (2认同)

ale*_*dro 13

我想在我的线程和这个线程(引用这个线程)中读到的响应中添加一些内容.

免责声明:本评论来自我的实验

外面的变量__init__:

实际上,它们是静态类变量,因此可以访问类的所有实例.

里面的变量__init__:

这些实例变量的值只能访问手头的实例(通过self引用)

我的贡献:

程序员在使用静态类变量时必须考虑的一件事是它们可以被实例变量遮蔽(如果你通过引用访问静态类变量self).

说明:

以前,我认为声明变量的两种方式完全相同(愚蠢的我),这部分是因为我可以通过self引用访问这两种变量.现在,当我遇到麻烦时,我研究了这个话题并将其清理干净.

通过 引用访问静态类变量的问题self是,如果没有具有相同名称的实例变量,它只引用静态类变量,并且更糟糕的是,尝试通过引用重新定义静态类变量不起作用,因为创建一个实例变量,然后隐藏先前可访问的静态类变量.self

要解决此问题,应始终通过的名称引用静态类变量.

示例:

#!/usr/bin/env python

class Foo:
    static_var = 'every instance has access'

    def __init__(self,name):
        self.instance_var = 'I am %s' % name

    def printAll(self):
        print 'self.instance_var = %s' % self.instance_var
        print 'self.static_var = %s' % self.static_var
        print 'Foo.static_var = %s' % Foo.static_var

f1 = Foo('f1')

f1.printAll()

f1.static_var = 'Shadowing static_var'

f1.printAll()

f2 = Foo('f2')

f2.printAll()

Foo.static_var = 'modified class'

f1.printAll()
f2.printAll()
Run Code Online (Sandbox Code Playgroud)

输出:

self.instance_var = I am f1
self.static_var = every instance has access
Foo.static_var = every instance has access
self.instance_var = I am f1
self.static_var = Shadowing static_var
Foo.static_var = every instance has access
self.instance_var = I am f2
self.static_var = every instance has access
Foo.static_var = every instance has access
self.instance_var = I am f1
self.static_var = Shadowing static_var
Foo.static_var = modified class
self.instance_var = I am f2
self.static_var = modified class
Foo.static_var = modified class
Run Code Online (Sandbox Code Playgroud)

我希望这对某人有帮助

  • 这是这里最重要的答案 (4认同)

Nei*_*eil 5

在S.Lott的回复中,类变量被传递给元类方法,并且可以在定义元类时通过字典访问.因此,即使在创建和实例化类之前,也可以访问类变量.

例如:

class meta(type):
    def __new__(cls,name,bases,dicto):
          # two chars missing in original of next line ...
          if dicto['class_var'] == 'A':
             print 'There'
class proxyclass(object):
      class_var = 'A'
      __metaclass__ = meta
      ...
      ...
Run Code Online (Sandbox Code Playgroud)