# python下划线\_命名

refer:<https://blog.csdn.net/tcx1992/article/details/80105645>

python的几种下划线意义：

* 单前 `_var`：约定、非强制，起提示作用
* 单后 `var_`：约定、非强制，避免关键字
* 双前 `__var`：特殊意义，会触发修饰名称
* 前后 `__var__`：特殊方法定义

## 单前 `_var`：

```python
# 变量中使用，你看，他能直接访问里面的变量
class Test:
   def __init__(self):
       self.foo = 11
       self._bar = 23

>>> t = Test()
>>> t.foo
11
>>> t._bar
23


# 函数使用，你看，前下划线的时候，从模块中*通配符*导入，既然报错
# my_module.py:
def external_func():
   return 23

def _internal_func():
   return 42

>>> from my_module import *
>>> external_func()
23
>>> _internal_func()
NameError: "name '_internal_func' is not defined"

# 函数使用，你看，前下划线的时候，从模块中指名道姓，才不会出问题
>>> import my_module
>>> my_module.external_func()
23
>>> my_module._internal_func()
42
```

## 单后 `var_`

主要（约定）用于避免关键字

```python
>>> def make_object(name, class):
SyntaxError: "invalid syntax"

>>> def make_object(name, class_):
...    pass
```

## 双前 `__var`：

特殊意义，会触发修饰名称，不能在外面直接访问

```python
class Test:
   def __init__(self):
       self.foo = 11
       self._bar = 23
       self.__baz = 23

# 会自动修饰 双前下划线变量 名称，变成 _Test__baz
>>> t = Test()
>>> dir(t)
['_Test__baz', '__class__', '__delattr__', '__dict__', '__dir__',
'__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
'__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__',
'__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__sizeof__', '__str__', '__subclasshook__',
'__weakref__', '_bar', 'foo']

# 访问定义的 双前下划线变量，无法访问（变成了 _Test__baz）
>>> t2 = ExtendedTest()
>>> t2.foo
'overridden'
>>> t2._bar
'overridden'
>>> t2.__baz
AttributeError: "'ExtendedTest' object has no attribute '__baz'"

# 可以这样访问
>>> t2._Test__baz
42
```

```python
# 继承之前的Test，全部重写变量定义
class ExtendedTest(Test):
   def __init__(self):
       super().__init__()
       self.foo = 'overridden'
       self._bar = 'overridden'
       self.__baz = 'overridden'

# 双前下划线变量 的无法访问，其它可以访问且被重写了
>>> t2 = ExtendedTest()
>>> t2.foo
'overridden'
>>> t2._bar
'overridden'
>>> t2.__baz
AttributeError: "'ExtendedTest' object has no attribute '__baz'"

# 查看变量，多了 _ExtendedTest__baz, _Test__baz
>>> dir(t2)
['_ExtendedTest__baz', '_Test__baz', '__class__', '__delattr__',
'__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__',
'__getattribute__', '__gt__', '__hash__', '__init__', '__le__',
'__lt__', '__module__', '__ne__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__',
'__subclasshook__', '__weakref__', '_bar', 'foo', 'get_vars']

# 可以这样访问
>>> t2._ExtendedTest__baz
'overridden'
>>> t2._Test__baz
42
```

在程序内部编程时，`__`定义的是可以直接调用的

```python
# 定义的 __变量
class ManglingTest:
   def __init__(self):
       self.__mangled = 'hello'

   def get_mangled(self):#直接.__mangled调用
       return self.__mangled

>>> ManglingTest().get_mangled()
'hello'
# 但是类外面就是之前的样子
>>> ManglingTest().__mangled
AttributeError: "'ManglingTest' object has no attribute '__mangled'"


# 定义的 __函数 
class MangledMethod:
   def __method(self):
       return 42

   def call_it(self):
       return self.__method()

>>> MangledMethod().__method()
AttributeError: "'MangledMethod' object has no attribute '__method'"
>>> MangledMethod().call_it()
42
```

直接定义

```python
_MangledGlobal__mangled = 23

class MangledGlobal:
   def test(self):
       return __mangled

>>> MangledGlobal().test()
23
```

## 前后 `__var__`

不会修饰变量名称，用于特殊方法定义，如python的魔术方法，`__init`，这类命名风格最好不要自己定义，避免混乱

```python
class PrefixPostfixTest:
   def __init__(self):
       self.__bam__ = 42

>>> PrefixPostfixTest().__bam__
42
```

PS：\_ 单下划线，用于不考虑的填充变量

```python
# 不想使用的充当占位
a,_ =call(a,b)
for _ in range(32):
    print('Hello, World.')


# 未定义的会赋值给_
>>> 20 + 3
23
>>> _
23
>>> print(_)
23

>>> list()
[]
>>> _.append(1)
>>> _.append(2)
>>> _.append(3)
>>> _
[1, 2, 3]
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://im-qianuxn.gitbook.io/pytorch/ji-suan-ji/python/2.2-shi-yong-yuan-zu/xia-hua-xian.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
