Python类中的类属性阴影

贾格

我正在学习此内容这是为了了解类属性。但是与以下代码段的输出混淆了。

class A:
    aliases = None
    name = None

    def __init__(self,name):
        self.name = name
        self.aliases = set([name])

    def add_aliases(self,a):
        self.aliases.add(a)

    def __repr__(self):
        return str(self.name) + str(self.aliases)

arr = []
for i in range(3):
    arr.append(A(i))
    arr[-1].add_aliases(i+1)

for item in arr:
    print item

A.aliases = set([]) ##Modify the static element of class
for item in arr:
    print item  

Python解释器:2.7.9

和输出是

0set([0, 1])
1set([1, 2])
2set([2, 3])
0set([0, 1])
1set([1, 2])
2set([2, 3])

我期待这样的输出。

0set([2, 3])
1set([2, 3])
2set([2, 3])
0set([])
1set([])
2set([])
贾格

而解释是,当我们写self.aliases = set([])我们实际上是在创建一个新的实例属性,遮蔽类属性

因此,如果我们使__init__函数如下所示,我们将获得预期的输出。

def __init__(self,name):
    self.name = name
    A.aliases = set([name])  #using the class attribute directly

还请考虑以下代码段:

class A:
    aliases = set([])
    name = None

    def __init__(self,name):
        self.name = name
        self.aliases.add(name) # using the class attribute indirectly.

    def add_aliases(self,a):
        self.aliases.add(a)

    def __repr__(self):
        return str(self.name) + str(self.aliases)

由于在这种情况下,我们没有创建实例属性,所以没有阴影。问题中的测试代码将产生以下输出:

0set([0, 1, 2, 3])
1set([0, 1, 2, 3])
2set([0, 1, 2, 3])
0set([])
1set([])
2set([])

这是预期的,因为在所有实例之间共享类属性。

这里A.alias也可以称为self.alias内部init函数或任何其他函数。并且由于它没有遮盖静态属性,因此提供了预期的输出-所有对象共享一个公共属性的情况。

一个人不知道这个概念的同时,将使用类似一成不变的数据结构不通知任何东西string等,但像数据结构的情况下,listdictionary此可能会感到惊讶。

还要考虑以下的定义init

def __init__(self,name):
    self.name = name
    self.aliases.add(name) # referring to class attribute
    self.aliases = set([]) # creating a instance attribute

而且在这种情况下,它最终instance attribute通过测试代码创建和产生的输出是:

0set([1])
1set([2])
2set([3])
0set([1])
1set([2])
2set([3])

因此,我的学习是:

始终用类名引用类属性,用对象名引用实例属性,即A.aliases在您指类属性时aliases,不要写self.aliases间接引用self.aliases

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

在Python中列出类属性及其类型

来自分类Dev

如何在PHP扩展类中设置静态类属性?

来自分类Dev

何时收集python类和类属性垃圾?

来自分类Dev

Python 2.7类属性奇怪的行为

来自分类Dev

从Swift中的超类访问子类属性

来自分类Dev

类在类属性中引用自身的最佳方法是什么?

来自分类Dev

如何在@Immutable类中设置超类属性?

来自分类Dev

Python类中的类属性阴影

来自分类Dev

Python:在基类中使用派生类属性

来自分类Dev

Flutter Dart:如何更改“类”列表中的类属性的值

来自分类Dev

在Python中调用类属性

来自分类Dev

在Python中处理许多参数/类属性

来自分类Dev

在Python中命名常量类属性

来自分类Dev

Python的“类属性”和“类函数”

来自分类Dev

在Python中的多个类之间共享类属性

来自分类Dev

Python-自动更新继承的类中的基类属性(别名)

来自分类Dev

Python 2.7类属性的异常行为

来自分类Dev

在Python中,如何从类方法的返回值初始化类属性?

来自分类Dev

Python:类本身的静态类属性

来自分类Dev

难以理解类中的私有属性和Python 3中的类属性方法

来自分类Dev

在父类中获取子类属性

来自分类Dev

Python 中类方法的长参数列表:本地、参数还是类属性?

来自分类Dev

如何从 Python 中的类中访问类属性

来自分类Dev

Python:类方法参数和类属性的名称相同

来自分类Dev

python (2.7):使用类装饰器访问类属性

来自分类Dev

在python的主类中使用子类属性

来自分类Dev

在python中创建和调用类属性

来自分类Dev

自己的类中的类属性

来自分类Dev

如何在 Python 中创建类之间的共享类属性