Python类语法 - 这是一个好主意吗?

Luc*_*ucy 4 python syntax

我很想定义我的Python类:

class MyClass(object):
    """my docstring"""

    msg = None
    a_variable = None
    some_dict = {}

    def __init__(self, msg):
        self.msg = msg
Run Code Online (Sandbox Code Playgroud)

声明对象变量(msg,a_variable等)在顶部,如Java好还是坏或无关紧要?我知道这是不必要的,但仍然很有诱惑力.

Yac*_*oby 8

在类定义中定义变量就像这样,使得变量可以在该类的每个实例之间访问.在Java术语中,它有点像使变量静态.但是,如下所示,存在重大差异.

class MyClass(object):
    msg = "ABC"

print MyClass.msg     #prints ABC
a = MyClass()
print a.msg           #prints ABC
a.msg = "abc"
print a.msg           #prints abc
print MyClass.msg     #prints ABC
print a.__class__.msg #prints ABC
Run Code Online (Sandbox Code Playgroud)

从上面的代码可以看出,它并不完全相同,因为变量可以是via self.msg,当它被赋值时,它不被赋值给类范围定义的变量.

通过你所做的方法做到这一点的一个缺点是,它会导致错误,因为它会增加类的隐藏状态.假设有人self.msg = "ABC"从构造函数中遗漏了(或者更真实的代码被重构,只有一个定义被改变了)

a = MyClass()
print a.msg   #prints ABC

#somewhere else in the program
MyClass.msg = "XYZ"

#now the same bit of code leads to a different result, despite the expectation that it
#leads to the same result.
a = MyClass()
print a.msg   #prints XYZ
Run Code Online (Sandbox Code Playgroud)

最好避免在类级别定义msg然后避免问题:

class MyClass(object):
    pass

print MyClass.msg #AttributeError: type object 'MyClass' has no attribute 'msg'
Run Code Online (Sandbox Code Playgroud)


And*_*Dog 6

直接在类定义中声明变量使它们成为类变量而不是实例变量.类变量有点类似于Java中的静态变量,应该像MyClass.a_variable.但它们也可以像使用一样self.a_variable,这是一个问题,因为天真的程序员可以将它们视为实例变量.例如,您的"some_dict"变量将由每个实例共享MyClass,因此如果您向其添加键"k",则任何实例都可以看到该变量.

如果你总是记得重新分配类变量,那么实例变量几乎没有区别.只MyClass保留最初的定义.但无论如何,这不是一个好习惯,因为在不重新分配这些变量时可能会遇到麻烦!

最好像这样编写类:

class MyClass(object):
    """
    Some class
    """

    def __init__(self, msg):
        self.__msg = msg
        self.__a_variable = None
        self.__some_dict = {}
Run Code Online (Sandbox Code Playgroud)

使用两个下划线表示"私有"变量(伪私有!)是可选的.如果变量应该是公共的,只需保留其名称不带__前缀.