Python|Python基础知识必备:最强字符——下划线,你的编程小帮手( 二 )



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

四. 数字字面中的单下划线(例如 100_000)PEP 515 指数建议扩展 Python 的语法 , 以便下划线可以用作整体、浮点和复杂数字文本中数字分组的可视分隔符 。
我们可以执行以下操作::
# 十进制数按千分组
amount = 10_000_000.0

# 按字对十六进制地址进行分组
addr = 0xCAFE_F00D

# 用二进制文字将位分组为半字节
flags = 0b_0011_1111_0100_1110

#相同 , 用于字符串转换
flags = int('0b_1111_0000' 2)

五. 姓名前的双下划线(例如__total)【Python|Python基础知识必备:最强字符——下划线,你的编程小帮手】在名称(特别是方法名称)前使用双下划线(__)不是约定 , 只是对解析程序有特殊的意义 。 双下划线前缀会导致Python解释器重写属性名称 , 以避免子类中的命名冲突 。
>>> class A(object):
...def _internal_use(self):
...pass
...def __method_name(self):
...pass
...
>>> dir(A())
['_A__method_name' ... '_internal_use'


这听起来很抽象 。因此 , 我组合了一个小小的代码示例来予以说明:
class Test:
def __init__(self):
self.foo = 11
self._bar = 23
self.__baz = 23

让我们用内置的dir()函数来看看这个对象的属性:
>>> 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'


以上是这个对象属性的列表 。让我们来看看这个列表 , 并寻找我们的原始变量名称foo , _bar和__baz - 我保证你会注意到一些有趣的变化 。

  • self.foo变量在属性列表中显示为未修改为foo 。
  • self._bar的行为方式相同 - 它以_bar的形式显示在类上 。就像我之前说过的 , 在这种情况下 , 前导下划线仅仅是一个约定 。给程序员一个提示而已 。
  • 然而 , 对于self.__baz而言 , 情况看起来有点不同 。当你在该列表中搜索__baz时 , 你会看不到有这个名字的变量 。

__baz出什么情况了?
如果你仔细观察 , 你会看到此对象上有一个名为_Test__baz的属性 。这就是Python解释器所做的名称修饰 。它这样做是为了防止变量在子类中被重写 。
让我们创建另一个扩展Test类的类 , 并尝试重写构造函数中添加的现有属性:
class ExtendedTest(Test):
def __init__(self):
super().__init__()
self.foo = 'overridden'
self._bar = 'overridden'
self.__baz = 'overridden'

现在 , 你认为foo , _bar和__baz的值会出现在这个ExtendedTest类的实例上吗? 我们来看一看:
>>> t2 = ExtendedTest()
>>> t2.foo
'overridden'
>>> t2._bar
'overridden'
>>> t2.__baz
AttributeError: \"'ExtendedTest' object has no attribute '__baz'\"

等一下 , 当我们尝试查看t2 .__ baz的值时 , 为什么我们会得到AttributeError? 名称修饰被再次触发了! 事实证明 , 这个对象甚至没有__baz属性:
>>> dir(t2)
['_ExtendedTest__baz' '_Test__baz' '__class__' '__delattr__'
'__dict__' '__dir__' '__doc__' '__eq__' '__format__' '__ge__'