zoukankan      html  css  js  c++  java
  • python技巧之下划线(一)

    1、python的moudles文件中__all__作用

    Python的moudle是很重要的一个概念,我看到好多人写的moudle里都有一个__init__.py文件。有的__init__.py中是空白,有的却会有__all__参数。搜索了下总结下__all__参数的作用。

    如果其他页面import *的时候如果__init__.py是空白的,可以直接import到moudle的所有函数。而如果__init__.py中定义了__all__,则import *的时候只会导入__all__部分定义的内容。

    例如:__all__ = ['User', 'UserCode', 'Tweet', ]

    2、__slots__用于限定类属性,如:

    class A(object):
      __slots__ = ['var']

    此时外部调用时,如:
    a = A()
    a.var = 4    #不会报错
    a.other = 4  #此时则会抛出异常AttributeError

    3、下面的小技巧可以获取私有变量:

    Python没有真正的私有变量。内部实现上,是将私有变量进程了转化,规则是:_<类名><私有变量>

    复制代码
    1 class Test(object):
    2     def __init__(self):
    3         self.__zzz=111
    4 
    5 if __name__ == '__main__':
    6     a =  Test()
    7     print a._Test__zzz
    复制代码

    同样,通过a._Test__zzz=222的方式,可以修改私有变量的值。

    4、下划线种类

    单个下划线(_

    主要有三种情况:

    1. 解释器中

    _符号是指交互解释器中最后一次执行语句的返回结果。这种用法最初出现在CPython解释器中,其他解释器后来也都跟进了。

    >>> _
    Traceback (most recent call last):
      File "", line 1, in 
    NameError: name '_' is not defined
    >>> 42
    >>> _
    42
    >>> 'alright!' if _ else ':('
    'alright!'
    >>> _
    'alright!'
    

    2. 作为名称使用

    这个跟上面有点类似。_用作被丢弃的名称。按照惯例,这样做可以让阅读你代码的人知道,这是个不会被使用的特定名称。举个例子,你可能无所谓一个循环计数的值:

    n = 42
    for _ in range(n):
        do_something()

    3. i18n

    _还可以被用作函数名。这种情况,单下划线经常被用作国际化和本地化字符串翻译查询的函数名。这种惯例好像起源于C语言。举个例子,在 Django documentation for translation 中你可能会看到:

    from django.utils.translation import ugettext as _
    from django.http import HttpResponse
    
    def my_view(request):
        output = _("Welcome to my site.")
        return HttpResponse(output)

    第二种和第三种用法会引起冲突,所以在任意代码块中,如果使用了_作i18n翻译查询函数,就应该避免再用作被丢弃的变量名。

    单下划线前缀的名称(例如_shahriar

    以单下划线做前缀的名称指定了这个名称是“私有的”。在 有些 导入import * 的场景中,下一个使用你代码的人(或者你本人)会明白这个名称仅内部使用。Python documentation里面写道:

    a name prefixed with an underscore (e.g. _spam) should be treated as a non-public part of the API (whether it is a function, a method or a data member). It should be considered an implementation detail and subject to change without notice.

    之所以说在在 有些 import * 的场景,是因为导入时解释器确实对单下划线开头的名称做了处理。如果你这么写from <module/package> import *,任何以单下划线开头的名称都不会被导入,除非模块/包的__all__列表明确包含了这些名称。更多相关信息见““Importing * in Python”

    双下划线前缀的名称(例如__shahriar

    以双下划线做前缀的名称(特别是方法名)并不是一种惯例;它对解释器有特定含义。Python会改写这些名称,以免与子类中定义的名称产生冲突。Python documentation中提到,任何__spam这种形式(至少以两个下划线做开头,绝大部分都还有一个下划线做结尾)的标识符,都会文本上被替换为_classname__spam,其中classname是当前类名,并带上一个下划线做前缀。
    看下面这个例子:

    >>> class A(object):
    ...     def _internal_use(self):
    ...         pass
    ...     def __method_name(self):
    ...         pass
    ... 
    >>> dir(A())
    ['_A__method_name', ..., '_internal_use']

    正如所料,_internal_use没有变化,但__method_name被改写成了_ClassName__method_name。现在创建一个A的子类B(这可不是个好名字),就不会轻易的覆盖掉A中的__method_name了:

    >>> class B(A):
    ...     def __method_name(self):
    ...         pass
    ... 
    >>> dir(B())
    ['_A__method_name', '_B__method_name', ..., '_internal_use']

    这种特定的行为差不多等价于Java中的final方法和C++中的正常方法(非虚方法)。

    前后都带有双下划线的名称(例如__init__

    这些是Python的特殊方法名,这仅仅是一种惯例,一种确保Python系统中的名称不会跟用户自定义的名称发生冲突的方式。通常你可以覆写这些方法,在Python调用它们时,产生你想得到的行为。例如,当写一个类的时候经常会覆写__init__方法。
    你也可以写出自己的“特殊方法”名(但是别这么做):

    >>> class C(object):
    ...     def __mine__(self):
    ...         pass
    ...
    >>> dir(C)
    ... [..., '__mine__', ...]

    还是不要这样写方法名,只让Python定义的特殊方法名使用这种惯例吧。

    5、这些命名有什么不同吗?

    1,以一个下划线开头的命名 ,如_getFile
    2,以两个下划线开头的命名 ,如__filename
    3,以两个下划线开头和结尾的命名,如 __init__()
    4,其它

  • 相关阅读:
    关于机器人流量对抗的一点感想
    保卫"木叶",从火影剧情看网站攻防的演变
    自动化工具层级图
    对抗恶意机器人/自动化行为的新思路与方案
    C++ 数组、链表和二叉树的比较
    #ifndef和#define区别
    xavier上安装teamviewer
    Ubuntu16.04 下有关conda虚拟环境的一些使用方法
    vector中push_back和emplace_back的区别
    int、int16、int32、int64、float、float16、float32、float64
  • 原文地址:https://www.cnblogs.com/work115/p/5606201.html
Copyright © 2011-2022 走看看