Last Updated on

前言

一般在代码编程中,为了使得代码更清晰可观等,会存在一些约定成俗的规范。比如驼峰命名法,注释格式等等。

在Python中也一样,Python的类中,关于类属性和类方法的定义时,存在一些Py约定,那就是单下滑线和双下划线开头的属性和方法。PS: 约定并没硬性规定

以下划线开头的有如下几种情况:

  • _var:单下划线开头,用来表示该变量私有。
  • __var:这个有真正的意义,用于避免父类方法被子类方法覆盖,解析器用_classname__var来代替这个名字。
  • var_:这是在你定义一些Python内置的单词的变量名称时,为了与Python内置方法做区分,如 type_ 属性或方法。

如上,就是常见的约定定义,除此之外,Python中还有__init__这种前后都是双下划线的方法,这是Python的内置方法,被称为魔法方法,非常有趣,这个我们在后面专门展开来讲,这里就不详细说了,官方建议我们自定义属性和方法时不要使用类似的命名方式。

下面我们对常见的几种单下划线和双下划线的方法详细说明一下。

_var

单下划线定义的属性方法为私有属性和方法,但是Python中并没有绝对意义上的私有,我们照样可以在外部调用私有属性和方法。

看下面示例:

class A(object):
    def __init__(self):
        self._name = 'Amos'

    def _work(self):
        print('{} is working'.format(self._name))

    def start(self):
        self._work()

a = A()
a.start()
a._work()
print(a._name)


# 输出结果:
Amos is working
Amos is working
Amos

如上所示,我们在定义类的时候,总是经常会有存在一些内置的方法和属性,这些方法和属性我们不希望被外部修改,所以就会通过单下划线来定义私有变量,以表示此方法属性为私有。

但实际上,我们还是能够在外部调用。

__var

双下划线定义的属性和变量,在外部调用时,会变为_类名__属性名这种形式,相当于跟类绑定了,这样就不会被子类继承并修改。

看下面示例:

class A(object):
    def __method(self):
        print("I'm a method in class A")

    def method_x(self):
        print("I'm another method in class A\n")

    def method(self):
        self.__method()
        self.method_x()


class B(A):

    def __method(self):
        print("I'm a method in class B")

    def method_x(self):
        print("I'm another method in class B\n")

a = A()
a.method()
a._A__method()

b = B()
b.method()


# 输出结果:
I'm a method in class A
I'm another method in class A
I'm a method in class A

I'm a method in class A
I'm another method in class B

如上所示,类B继承与类A,在执行类B的继承方法method()时,其中调用的self.__method() 方法还是类A中的方法,并不是类B中修改后的同名方法。

且注意,双下划线定义的属性,在类中直接引用时可以直接通过名称引用,但是如果要在外部调用,则需要变成 _class__var 的方式才能访问到。

要想其调用类B中的同名self.__method() 方法,则还需要重新定义method()方法。如下:

class A(object):
    def __method(self):
        print("I'm a method in class A")

    def method_x(self):
        print("I'm another method in class A\n")

    def method(self):
        self.__method()
        self.method_x()


class B(A):

    def __method(self):
        print("I'm a method in class B")

    def method_x(self):
        print("I'm another method in class B\n")

    def method(self):
        self.__method()
        self.method_x()

a = A()
a.method()

b = B()
b.method()


# 输出结果:
I'm a method in class A
I'm another method in class A

I'm a method in class B
I'm another method in class B

如上所示,双下划线的属性和方法则相当于跟类绑定,只要在此类中定义的,那么其只能访问此类中的对应的属性和方法,继承时,需要特别注意

var_

此种最为简单,并没有特别意思,仅仅只是在Python已经占用了对应的名称时,通过此方式,来区别开而已。

看下面示例:

def type():
    print('改变了内置方法')


class A(object):
    def type_(self):
        print(type(123))

a = A()
a.type_()

# 输出结果:
报错:TypeError: type() takes 0 positional arguments but 1 was given

如上所以,当我在文件中,定义一些与内置方法同名的变量或方法时,内置的方法就会失效,导致报错。

所以在编写代码时,注意一下就行了。

大致就讲到这里,有任何问题,欢迎留言交流