关于Python:Python – 在本地变量中存储实例变量以避免“自我”的不良做法?

Python - Bad practice to store instance vars in local vars to avoid “self”?

我主要是用Java编程,我发现Python显式的自引用给类成员是丑陋的。我真的不喜欢所有的"self",它把我的方法弄得一团糟,所以我发现自己想把实例变量存储在局部变量中,只是为了摆脱它。例如,我将替换这个:

1
2
3
4
5
6
def insert(self, data, priority):
    self.list.append(self.Node(data, priority))
    index = len(self)-1
    while self.list[index].priority < self.list[int(index/2)].priority:
        self.list[index], self.list[int(index/2)] = self.list[int(index/2)], self.list[index]
        index = int(index/2)

有了这个:

1
2
3
4
5
6
7
def insert(self, data, priority):
    l = self.list
    l.append(self.Node(data, priority))
    index = len(self)-1
    while l[index].priority < l[int(index/2)].priority:
        l[index], l[int(index/2)] = l[int(index/2)], l[index]
        index = int(index/2)

通常我会将局部变量命名为与实例变量相同的名称,但是"list"是保留的,所以我使用"l"。我的问题是:这在Python社区中被认为是不好的实践吗?


先简单回答。在Python中,下划线用于避免与关键字和内置项发生冲突:

1
list_ = self.list

这将被Python程序员理解为正确的方法。

至于属性的局部变量,它取决于。对plone(甚至是标准库)的代码库进行grepping显示,使用x=self.x,尤其是,

1
context = self.context

正如注释中指出的,它可能容易出错,因为将另一个值绑定到局部变量不会影响属性。

另一方面,如果方法中的某些属性是只读的,那么它会使代码更具可读性。所以,如果变量的使用足够局部,比如函数编程语言中的let子句,就可以了。

有时属性实际上是函数,所以self.property将每次计算。(这是"pythonic"如何为属性getter进行广泛计算的另一个问题)(感谢python@property,而不是getter和setter提供了一个现成的示例):

1
2
3
4
5
6
7
8
9
class MyClass(object):
    ...        
    @property
    def my_attr(self):
        ...

    @my_attr.setter
    def my_attr(self, value):
        ...

总之,谨慎使用,不要将其作为规则。


我同意,明确地添加"self"(或其他语言的"this")对眼睛不是很有吸引力。但正如人们所说,Python遵循"显胜于隐"的哲学。因此,它确实希望您表示要访问的变量的范围。

Java不会让你使用你没有声明的变量,所以没有混淆的机会。但在python中,如果"self"是可选的,那么对于赋值a = 5,将不清楚是创建成员变量还是局部变量。因此在某些地方需要明确的self。不过,访问也同样有效。请注意,Java还需要一个显式的EDCOX1与2的名称冲突。

我只是在我的一些意大利面条代码中计算了一下self。对于1000行代码,有500多个self的外观。现在代码确实不那么可读,但问题不在于重复使用self。对于上面的代码示例:第二个版本的行长度较短,这使得理解起来更容易和/或更快。我认为你的例子是可以接受的。