Python文件中的下划线”_”是如何工作的?
在Python的开发中,经常可以看到下划线”_ “出现在变量、函数和方法的命名中。它们有不同的含义和用途,但是它们都是必要的,因为它们可以使代码更加易于理解和维护。
阅读更多:Python 教程
单下划线
在Python中,单个下划线”_”通常作为一个惯例,用于指示该名称是私有的或内部的。当变量、函数或方法的名称以单个下划线开头时,它被视为不能在从模块外部引用时被引用的“内部”名称。
例如:
class MyClass:
def __init__(self):
self._foo = 0
def _bar(self):
print("This is a private method.")
mc = MyClass()
print(mc._foo) # This works, but not recommended
mc._bar() # This works, but not recommended
类中的变量_foo和方法_bar由于以下划线开头而被认为是私有的,不能直接从类外部引用。然而,它们实际上是可以从类外部引用的,但是不建议这么做。 Python并没有强制执行单下划线的访问约定。 这只是一种以一致的方式表示名称不应从模块外部引用的方式。
双下划线
另一个用下划线来表示变量、函数和方法是私有的约定是双下划线”__”。当对象被定义为双下划线的名称时,它们形成了命名语义上的“保护”机制。这种保护的方式是通过在变量名前加上类名和一个下划线,然后再加上变量名重新组合成一个新的名称来实现的。这种组合的属性是伪私有的。只要知道正确的方法名,任何人都可以从对象外部访问该属性。
例如:
class MyClass:
def __init__(self):
self.__foo = 0
def __bar(self):
print("This is a private method.")
mc = MyClass()
print(mc._MyClass__foo) # This works, but is not recommended
mc._MyClass__bar() # This works, but is not recommended
在这种情况下,变量__foo和方法__bar被认为是私有的,并且不能直接从类外部引用。 它们被编译成_MyClass__foo和_MyClass__bar。 特别值得注意的是,经过编译的名称中的第一个下划线和类名并不是保护的,不应当被依赖。 这只是一个有助于防止名称冲突的解决方案。
单下划线和双下划线
当在一个名称开头和结尾都使用下划线时,这表示名称是有特殊含义的。 例如,许多用于测试的框架使用以“test”命名的函数。
def test_something():
assert something == something_else
如果你想在意外的情况下避免覆盖Python的内置功能,则可以使用前导下划线。 比如:
def _sum(a, b):
return a + b
这样可以避免覆盖Python内置的sum函数。
单下划线的惯例
在Python中,单下划线的命名惯例被用于几个目的。当使用下划线作为名称的前缀时,通常有以下几个原因:
1.用作内部使用的变量或方法。 这种做法表明该变量或方法是模块、类或方法中不应被外部使用的。
2.避免与保留关键字冲突。例如,您不能将变量命名为class或for,因为它们是Python保留关键字。
3.命名约定。许多Python程序员使用下划线作为变量名的分隔符,以更容易阅读。例如,我的变量名可能为first_name而不是firstname。
双下划线的用途
在Python中,双下划线的命名约定被用于名称重整(Name Mangling),它实际上是一种机制,用于避免子类意外地覆盖其父类的属性。 当子类和父类都存在同名属性时,Python会使用名称重整的方式将属性名称更改为类名和属性名称的组合,以确保其唯一性。
例如:
class MyClass:
def __init__(self):
self.__foo = 0
class MyOtherClass(MyClass):
def __init__(self):
super().__init__()
self.__foo = 1
moc = MyOtherClass()
print(moc._MyClass__foo) # 0
print(moc._MyOtherClass__foo) # 1
在这个例子中,MyOtherClass继承了MyClass中的__foo
属性。 但是,MyOtherClass也有自己的__foo
属性。 在打印moc._MyClass__foo
时,输出为0,因为MyClass中的__foo
属性被”name mangling”改名为了_MyClass__foo。
而当打印moc._MyOtherClass__foo
时,输出为1因为这是MyOtherClass自身的__foo
属性。
结论
在Python文件中,下划线并不仅仅只是一个字符,它有不同的含义和用途。 在Python没有强制实施下划线的规则,只是一种以一致的方式表示名称不应从模块外部引用的方式。