代码之家  ›  专栏  ›  技术社区  ›  Phillip B Oldham

Python和对象/类属性-发生了什么?

  •  1
  • Phillip B Oldham  · 技术社区  · 14 年前

    >>> class Foo(object):
    ...   bar = []
    ...
    >>> a = Foo()
    >>> b = Foo()
    >>> a.bar.append(1)
    >>> b.bar
    [1]
    >>> a.bar = 1
    >>> a.bar
    1
    >>> b.bar
    [1]
    >>> a.bar = []
    >>> a.bar
    []
    >>> b.bar
    [1]
    >>> del a.bar
    >>> a.bar
    [1]
    

    太让人困惑了!

    6 回复  |  直到 14 年前
        1
  •  0
  •   mikej heading_to_tahiti    14 年前

    正如其他人所说,编写的代码创建了类变量而不是实例变量。你需要分配 __init__ 创建实例变量。

    希望这段代码的注释副本有助于解释每个阶段的情况:

    >>> class Foo(object):
    ...   bar = []          # defines a class variable on Foo (shared by all instances)
    ...
    >>> a = Foo()
    >>> b = Foo()
    >>> a.bar.append(1)     # appends the value 1 to the previously empty list Foo.bar
    >>> b.bar               # returns the value of the class variable Foo.bar
    [1]
    >>> a.bar = 1           # binds 1 to the instance variable a.bar, masking the access
    >>> a.bar               # you previously had to the class variable through a.bar
    1
    >>> b.bar               # b doesn't have an instance variable 'bar' so this still
    [1]                     # returns the class variable
    >>> a.bar = []          # bind a's instance variable to to an empty list
    >>> a.bar
    []
    >>> b.bar               # b doesn't have an instance variable 'bar' so this still
    [1]                     # returns the class variable
    >>> del a.bar           # unbinds a's instance variable unmasking the class variable
    >>> a.bar               # so a.bar now returns the list with 1 in it.
    [1]
    

    同时,打印出 Foo.bar

        2
  •  7
  •   danben    14 年前

    bar 是类变量而不是实例变量。

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

    请注意,它现在属于 Foo ( self )而不是

        3
  •  0
  •   Michael Aaron Safyan    14 年前

    当您在类中这样声明一个元素时,它将由类的所有实例共享。要分别创建属于每个实例的适当类成员,请按如下所示在\uuu init\uuuuu中创建它:

    class Foo(object):
        def __init__(self):
            self.bar = []
    
        4
  •  0
  •   sth ACP    14 年前

    一开始, bar 是一个类变量,在 a b ,两者 a.bar b.bar 引用同一对象。

    a、 酒吧 ,这不会覆盖类变量,而是向 对象,在访问时隐藏类变量 a、 酒吧 . 如果删除 a、 酒吧 (实例变量),然后 a、 酒吧 再次解析为类变量。

    b、 酒吧 酒吧 对象或指定给该对象的任何值。

    要设置类变量,可以通过类本身访问它:

    Foo.bar = 1
    
        5
  •  0
  •   Oli    14 年前
    >>> class Foo(object):
    ...   bar = []
    ...
    

    bar 是共享类变量,而不是实例变量。我相信这能解决你大部分的困惑。要使其成为实例变量,请在类的 __init__

    >>> a = Foo()
    >>> b = Foo()
    >>> a.bar.append(1)
    >>> b.bar
    [1]
    

    >>> a.bar = 1
    >>> a.bar
    1
    >>> b.bar
    [1]
    

    a.bar

    >>> a.bar = []
    >>> a.bar
    []
    >>> b.bar
    [1]
    >>> del a.bar
    >>> a.bar
    [1]
    

    又是一样的。 b.bar 仍然是共享类变量。

        6
  •  0
  •   Wayne Werner    14 年前

    class A:
       def __init__(self, mylist = []):
          self.mylist = mylist
    
    
    a = A()
    a2 = A()
    
    a.mylist.append(3)
    print b.mylist #prints [3] ???
    

    这让很多人感到困惑,并与代码的解释方式有关。Python实际上首先解释函数标题,因此它会计算 __init__(self, mylist = []) 并将对该列表的引用存储为默认参数。这意味着遗嘱的所有实例(除非提供了自己的清单)都引用了原始清单。这样做的正确代码是

    class A:
       def __init__(self, mylist=None):
          if mylist:
             self.mylist = mylist
          else:
             self.mylist = []
    

    或者,如果您想要一个较短的表达式,可以使用三元语法:

    self.mylist = mylist if mylist else []
    
    推荐文章