Python:self vs type(self)和类变量的正确使用

Python: self vs type(self) and the proper use of class variables

在python中使用类变量时,可以通过"self"(由于引用)或"type(self)"(直接)访问和(如果它是可变的)直接操作它,而不可变的变量(例如整数)显然会在使用"self"时被新的实例对象隐藏。

所以,在处理python类变量时,最好还是使用"type(self)"来处理类方法中引用的类变量?

(我知道类变量有时不受欢迎,但当我使用它们时,我希望以一致的方式访问它们(如果它们是不可变类型,则以一种方式访问;如果它们是可变类型,则以另一种方式访问。)

编辑:是的,如果修改不可变的值,则会得到一个新对象。修改可变对象的值的副作用就是导致这个问题的原因-"self"将给您一个引用,您可以使用它来更改类变量而不隐藏它,但是如果为它分配一个新对象,它将隐藏它。使用classname.classvar或type(self).classvar或self.uuu class_uuu确保始终使用类变量,而不仅仅是隐藏它(尽管子类会使这一点变得复杂,如下所述)。


您可能希望使用实际类型名访问它们,而不是使用selftype(self)

你看到的效果与变异性无关。如果你愿意的话

1
2
3
4
class Foo(object):
    x = []
    def __init__(self):
        self.x = [1]

__init__中的赋值将创建一个新的列表,并将其分配给实例属性x,忽略类属性,即使Foo.x是一个可变的对象。每当您想要分配给一个属性时,您需要使用它实际定义的对象。

注意,在继承的情况下,通过type(self)修改属性失败:

1
2
3
4
5
6
7
8
9
class Foo(object):
    x = 1
    def modify_x(self, x):
        type(self).x = x

class Bar(Foo): pass

Foo().modify_x(2) # modifies Foo.x
Bar().modify_x(3) # modifies Bar.x, the wrong attribute


在与其他人离线交谈后(并根据@wwiii对其中一个答案的评论),不显式嵌入类名的最佳方法是使用self.u classuuu.attribute。

(有些人使用type(self).attribute时,它会导致其他问题。)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
python -c 'import this'
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you'
re Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let'
s do more of those!

我建议这些作为参考

1
2
3
4
5
6
Beautiful is better than ugly.
Simple is better than complex.
Readability counts.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
If the implementation is hard to explain, it'
s a bad idea.

我的建议是使用直接属性引用,因为它可能是语言设计者想要的。


https://bitback.org/larry/cpython350/pull-requests/15/issue-24912-prevent-class-assignment/diff

在常见情况下,它们的工作原理是相同的(可能应该使用youclass.nameattribute来避免以后继承出现问题)。简而言之,差异一直持续到python 3.5。问题是问题24912(在所有情况下都不允许协助)。示例:像int这样的不可变类型被分配了staticalli,而heaptype规则意外地从分配类停止。