当前位置:主页 > 软件编程 > Python代码 >

浅析python中特殊文件和特殊函数

时间:2023-01-30 10:34:38 | 栏目:Python代码 | 点击:

导入模块

模块通常为单独的.py文件,可以用import直接引用,可以作为模块的文件类型有.py、.pyo、.pyc、.pyd、.so、.dll在导入模块时,解释器做以下工作:

import 语句可以在程序的任何位置使用,你可以在程序中多次导入同一个模块,但模块中的代码仅仅在该模块被首次导入时执行。后面的import语句只是简单的创建一个到模块名字空间的引用而已。sys.modules字典中保存着所有被导入模块的模块名到模块对象的映射。

导入包

多个相关联的模块组成一个包,即多个.py文件构成一个包,以便于维护和使用,同时能有限的避免命名空间的冲突。一般来说,包的结构可以是这样的:

package
  |- subpackage1
      |- __init__.py
      |- a.py
  |- subpackage2
      |- __init__.py
      |- b.py

有以下几种导入方式

import subpackage1.a # 将模块subpackage.a导入全局命名空间,例如访问a中属性时用subpackage1.a.attr
from subpackage1 import a # 将模块a导入全局命名空间,例如访问a中属性时用a.attr_a
from subpackage1.a import attr_a # 将模块a的属性直接导入到命名空间中,例如访问a中属性时直接用attr_a

使用from语句可以把模块直接导入当前命名空间,from语句并不引用导入对象的命名空间,而是将被导入对象直接引入当前命名空间

可以被import语句导入的对象是以下类型:

特殊文件

1、__init__.py文件

__init__.py文件的作用就是将该文件所处的文件夹当做一个模块来管理,每当有外部文件来import的时候,就会执行里面的函数

__init__.py是怎么工作的

当一个目录下含有这个文件,则这个文件夹就是一个python模块,通常__init__.py文件为空,但是我们还可以为它增加其他的功能。我们在导入一个包时,实际上是导入了它的__init__.py文件。这样我们可以在__init__.py文件中批量导入我们所需要的模块,而不再需要一个一个的导入。

当import导入该模块时,同时会执行该文件内容,当导入该模块中的某个函数时需要加上该包名,不然就会报错,如下,当在其他文件中要导入子包subpackage_1中的test11函数时,需要加上包名mypackage

from mypackage.subpackage_1 import test11

__init__.py中还有一个重要的变量,__all__, 它用来将模块全部导入。

# __init__.py
__all__ = ['os', 'sys', 're', 'urllib']
# a.py
from package import *

这时就会把注册在__init__.py文件中__all__列表中的模块和包导入到当前文件中来。在了解了__init__.py的工作原理后,应该能理解该文件就是一个正常的python代码文件。因此可以将初始化代码放入该文件中。

2、.pyc与 .pyo文件

.py文件在汇编时,会生成.pyc文件,在汇编时,会将.py文件中的import的文件链接起来汇编成字节码写到一个.pyc文件中,后面执行时,就直接执行.pyc文件,省去每次都要重新汇编,提高运行速度,(当.py文件的修改时间发生改变,这样会生成新的.pyc文件)在解释器使用-O选项时,将使用同名的.pyo文件,这个文件去掉了断言(assert)、断行号以及其他调试信息,体积更小,运行更快。(使用-OO选项,生成的.pyo文件会忽略文档信息)

特殊函数

1、构造函数

构造函数是一种特殊的类成员方法,主要用在创建对象时初始化对象
python中的构造函数用__init__命名

2、析构函数

析构函数是构造函数的反函数,在销毁对象时调用他们,往往用来做清理善后,
例如:数据库连接对象可以在析构函数中释放对数据库实例资源的占用
python中为类定义析构函数的方法是在类中定义一个名为__del__的没有返回值和参数的函数
python中显示销毁对象的方法,使用del关键

3、静态函数和类函数

python中支持两种基于类名访问成员函数:静态函数和类函数
不同点:类函数有一个隐形参数cls可以用来获取类信息
静态函数使用装饰器@staicmethod定义
类函数使用装饰器@classmethod定义

4、以下划线开头的函数

单线划:_var

下划线前缀的含义是告知其他程序员:以单个下划线开头的变量或方法仅供内部使用。 该约定在PEP 8中有定义。这不是Python强制规定的。 Python不像Java那样在“私有”和“公共”变量之间有很强的区别。

如果使用通配符从模块中导入所有名称,则Python不会导入带有前导下划线的名称(除非模块定义了覆盖此行为的__all__列表)

# This is 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_

有时候,一个变量的最合适的名称已经被一个关键字所占用。 因此,像class或def这样的名称不能用作Python中的变量名称。 在这种情况下,你可以附加一个下划线来解决命名冲突,总之,单个末尾下划线(后缀)是一个约定,用来避免与Python关键字产生命名冲突。 PEP 8解释了这个约定。

双前导下划线:__var

到目前为止,我们所涉及的所有命名模式的含义,来自于已达成共识的约定。 而对于以双下划线开头的Python类的属性(包括变量和方法),情况就有点不同了。双下划线前缀会导致Python解释器重写属性名称,以避免子类中的命名冲突。这也叫做名称修饰(name mangling) — 解释器会更改变量的名称,以便在类被扩展的时候不容易产生冲突。对于该属性的调用可以通过方法调用,而不能直接调用该属性,类似实现属性的私有,例如:

class ManglingTest:
   def __init__(self):
       self.__mangled = 'hello'
   def get_mangled(self):
       return self.__mangled
>>> ManglingTest().get_mangled() # 通过方法获取该函数的值
'hello'
>>> ManglingTest().__mangled # 直接调用该属性时会报错
AttributeError: "'ManglingTest' object has no attribute '__mangled'"

但我们依然可以通过特殊方法来直接获取该属性的值,即通过(_类名__属性)的方式获取,例如

>>> ManglingTest()._ManglingTest__mangled
'hello'

所以在python中并没有真正的私有变量,python解释器会自动将__var修饰为: _类名__属性,该特性对于以双下划线开头的方法依然适用

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
>>> MangledMethod()._MangledMethod__method() # 通过该形式也是可以调用该方法
42

双前导和双末尾下划线 var

如果一个名字同时以双下划线开始和结束,则不会应用名称修饰。不同于仅有双下滑线开头的变量或函, 由双下划线前缀和后双下滑线包围的变量不会被Python解释器修改,但是,Python保留了有双前导和双末尾下划线的名称,用于特殊用途。 这样的例子有,__init__(对象构造函数),或__call__(该函数是使得一个对象可以被调用)最好避免在自己的程序中使用以双下划线开头和结尾的名称,以避免与将来Python语言的变化产生冲突。

单下划线

按照习惯,有时候单个独立下划线是用作一个名字,来表示某个变量是临时的或无关紧要的。

例如,在下面的循环中,我们不需要访问正在运行的索引,我们可以使用“_”来表示它只是一个临时值:

>>> for _ in range(32):
...    print('Hello, World.')
>>> car = ('red', 'auto', 12, 3812.4)
>>> color, _, _, mileage = car
>>> color
'red'
>>> mileage
3812.4
>>> _
12

您可能感兴趣的文章:

相关文章