【问题标题】:Static variables in python classespython类中的静态变量
【发布时间】:2018-03-09 18:00:20
【问题描述】:

我在理解 Python 类中的静态变量的概念方面存在问题。根据Static class variables in Python,每当我们在方法外部和python 类内部定义变量时,该变量都是静态的。这意味着无需从类中实例化对象就可以访问该变量,并且可以直接通过类名访问该变量。 例如:

class my_class:

     i=12

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


instance=my_class(10)

my_class.i:
>12
instance.i:
>12
instance.i=13
instance.i:
>13
my_class.i:
>12 

可以看到我们可以通过实例对象和类名来访问静态变量i。但是,当我们更改 i 的值时,它不会影响类的值(my_class.i 仍然是 12)。 另一方面,如果我们使用数组静态变量,事情就会完全改变。 考虑类似的例子:

class my_class:

     i=[]

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


instance=my_class(10)

my_class.i:
>[]
instance.i:
>[]
instance.i.append(13)
instance.i:
>[13]
my_class.i:
>[13]

您可以看到,当我更改实例对象数组的变量时,它也会影响类值。这里发生了什么?如果有人能帮助我更好地理解这个问题,我将不胜感激,因为这对我来说并不是那么明显。顺便说一句,我有 Java 背景。

【问题讨论】:

  • 为什么标记为 Java?

标签: python class object instance


【解决方案1】:

分配给实例属性通常设置实例属性。一旦有实例属性,它就会屏蔽类属性。

所以在你执行instance.i=13之前,实例上没有i属性,只有类上。然后将实例上的名称i 绑定到13,下次查找instance.i 时会找到该属性,并且不再尝试查找my_class.i

但操作一个可变对象与分配给一个类或实例属性不同。您没有分配给instance.i,而是更改了my_class.i 引用的列表对象,并通过instance.i 可见。 instance.i 仍然会找到my_class.i 属性,您从未使用= 来创建instance.i 属性。

那是因为您只阅读对列表的instance.i 引用,以便打印它并找到list.append() 方法。您绝不会为 instance.i 属性引用设置新值。

列表对象是它自己的对象,您可以通过添加、删除或替换列表的索引 引用的值来更改它。什么名称或属性引用该列表无关紧要,您可以对同一个列表有任意数量的此类引用,并且更改列表不会更改这些引用。

尝试创建更多对列表的引用,看看会发生什么:

>>> list_named_i = instance.i
>>> list_named_i
[13]
>>> my_class.i.append(42)
>>> list_named_i
[13, 42]
>>> list_named_i[0] = 81
>>> instance.i
[81, 42]

instance.imy_class.ilist_named_i 都是对同一个列表对象的不同引用,您可以通过这些引用中的任何一个来修改(变异)该列表对象。

我建议您阅读 Python 名称、属性和列表等工作原理;请参阅 Ned Batchelder 的 Facts and myths about Python names and values

【讨论】:

  • 多么棒的答案。你太棒了!
【解决方案2】:
instance.i.append(13)

这不会改变变量,它会改变列表对象。变量仍然设置为同一个对象。

如果将变量设置为新列表:

instance.i = [13]

然后你会看到你所期待的。

【讨论】:

    【解决方案3】:

    在实例化期间,对象在实例化时接收(或多或少)每个类属性的副本。这就是为什么您可以在不影响类和签证/反之的情况下访问和改变实例上的值的原因。

    list 被修改的第二点,从实例到类似乎是相反的,这是由于 list 的可变性,并且类似于使用默认参数时经常遇到的问题,described here

    【讨论】:

    • 这是错误的。类属性根本不被复制;相反,当a.x 无法在对象a 上找到属性x 时,Python 接下来会尝试按照对象的方法解析顺序在每个类中查找类属性x。您完全可以通过该类的实例来修改可变类属性。
    • @chepner 是一个可变的,当然。但是对于新手开发人员(就像 OP 似乎一样),它看起来很像复制,因为对实例属性的分配没有反映“向上”到类属性。但可以肯定的是,如果您想对此持迂腐态度,并且对新手问题过于具体。那么是的,它不是字面意义上的复制。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-14
    • 1970-01-01
    • 2014-12-25
    相关资源
    最近更新 更多