GVKun编程网logo

如何编写良好/正确的__init__.py包文件(怎么编写.py文件)

25

本文将介绍如何编写良好/正确的__init__.py包文件的详细情况,特别是关于怎么编写.py文件的相关信息。我们将通过案例分析、数据研究等多种方式,帮助您更全面地了解这个主题,同时也将涉及一些关于p

本文将介绍如何编写良好/正确的__init__.py包文件的详细情况,特别是关于怎么编写.py文件的相关信息。我们将通过案例分析、数据研究等多种方式,帮助您更全面地了解这个主题,同时也将涉及一些关于python __new__ 和 __init__、python 中的__init__.py的用法与个人理解、python 中的__iter__ __reversed__ __next__、Python 的__del__()方法 ---内存回收,对象销毁 || 与__init__方法对比的知识。

本文目录一览:

如何编写良好/正确的__init__.py包文件(怎么编写.py文件)

如何编写良好/正确的__init__.py包文件(怎么编写.py文件)

我的软件包具有以下结构:

mobilescouter/    __init__.py #1    mapper/        __init__.py  #2        lxml/            __init__.py #3            vehiclemapper.py            vehiclefeaturemapper.py            vehiclefeaturesetmapper.py        ...        basemapper.py   vehicle/        __init__.py #4        vehicle.py        vehiclefeature.py        vehiclefeaturemapper.py   ...

我不确定__init__.py应如何正确写入文件。
__init__.py #1样子:

__all__ = [''mapper'', ''vehicle'']import mapperimport vehicle

但是例如应该__init__.py #2看起来如何?我的是:

__all__ = [''basemapper'', ''lxml'']from basemaper import *import lxml

什么时候应该__all__使用?

答案1

小编典典

__all__很好-它有助于指导导入语句,而无需自动导入模块
http://docs.python.org/tutorial/modules.html#importing-from-a-
package

使用__all__import *是多余的,仅__all__需要

我认为import*__init__.py导入软件包中使用的最强大的理由之一是能够重构已经成长为多个脚本的脚本,而又不会破坏现有的应用程序。但是,如果您从一开始就设计一个包装。我认为最好将__init__.py文件留空。

例如:

foo.py - contains classes related to foo such as fooFactory, tallFoo, shortFoo

然后应用程序增长,现在是整个文件夹

foo/    __init__.py    foofactories.py    tallFoos.py    shortfoos.py    mediumfoos.py    santaslittlehelperfoo.py    superawsomefoo.py    anotherfoo.py

然后初始化脚本可以说

__all__ = [''foofactories'', ''tallFoos'', ''shortfoos'', ''medumfoos'',           ''santaslittlehelperfoo'', ''superawsomefoo'', ''anotherfoo'']# deprecated to keep older scripts who import this from breakingfrom foo.foofactories import fooFactoryfrom foo.tallfoos import tallFoofrom foo.shortfoos import shortFoo

因此编写的执行以下操作的脚本在更改期间不会中断:

from foo import fooFactory, tallFoo, shortFoo

python __new__ 和 __init__

python __new__ 和 __init__

概述

newinit 是类实例化的过程中被调用的方法, new 负责对象的创建,相当于构造器或者构造函数; init 负责对象初始化。 使用频率上, init 较多会被使用。

class A(object):

    def __new__(cls):
        return object.__new__(cls)

    def __init__(self):
        self.instance_method()

    def instance_method(self):
        print ''success!''

newA = A()

区别

参数

new 的第一个参数是 cls,表示类本身。

init 类似一般的实例方法, 第一个参数是 self,表示实例。我们可以看到 init 方法运行之前, 实例已经可以被使用了(self参数)。实例上的其他的方法也是可以使用的了。

调用时机

当我们创建类的对象时, new 先被调用,返回一个对象,对象引用作为参数传递给 init__, 然后对象属性被初始化。__init 方法不能返回任何数据。

__new__ --->(创建对象) --> __init__(self)

使用

只有很少的时候需要自己编写 new 方法,比如单例模式。大多数情况下,只需要关心实例的初始化,初始化过程中属性的分配,以及是否调用其他的实例方法。

以上代码和经验仅在 Python(2.7) 得到验证。

python 中的__init__.py的用法与个人理解

python 中的__init__.py的用法与个人理解

使用Python模块常见的情况是,事先写好A.py文件,需要import B.py文件时,先拷贝到当前目录,然后再import

这样的做法在程序量较小的情况下是可行的,如果程序交互复杂程度稍高,就很费力了

有一种解决方法可以将多个.py文件组织起来,方便在外部统一调用,和在内部互相调用:python中的 __init__.py在包调用中起到了重要的作用

 

首先要明确的Python在执行import包的时候,执行的操作,按照python的文档描述,操作如下:

a) 创建一个新的,空的module对象(它可能包含多个module);
b) 把这个module对象插入sys.module中
c) 装载module的代码(如果需要,首先必须编译) (首先需要找到module程序所在的位置,其原理为:如果需要导入的module的名字是m1,则解释器必须找到m1.py,它首先在当前目录查找,然后是在环境变量PYTHONPATH中查找
d) 执行新的module中对应的代码。

 

Python中的package定义很简单,其层次结构与.py所在目录的层次结构相同,比较关键的一点是package中必须包含一个__init__.py的文件

例如,我们可以这样组织一个package: init为顶层目录

运行结果如下

 

其中__init__.py可以为空,只要它存在,解释器对其视作一个package处理。

第一层:pack, pack2, main.py

第二层 pack: __init__.py,module_A.py

    pack2:__init__.py,module_B.py

main.py 调用脚本:

from pack import func1
from pack import func2
from pack2 import print_lst
def main():
    func1()
    func2()
    print_lst()

if __name__ == "__main__":
    main() 

其中 module_A:

def func1():
    print("MODULEAAAAA_func1111")

def func2():
    print("MODULEAAAAA_func2222")

同一层 __init__.py

from .module_A import func1
from .module_A import func2

.module_A 表示__init__.py同一层目录的module_A

个人理解是:当 main.py调用脚本from pack import func1

由于from操作 会默认目录下存在pack包,解释器会首先寻找__init__.py

而__init__.py内容不为空,对module_A引入了两个函数fun1,fun2,生成了函数引用域(太菜不知道专属名词)

所以在main.py 中可以不显式地指明module_A而直接用: from pack import fun1,fun2

如果把pack下的init.py 的第二行 import func2注释

 也就是说,package内的module的import 是受__init__.py限制的

有时在import语句中会出现通配符*,导入某个module中的所有元素,这是怎么实现的呢?
答案就在__init__.py中。如果在__init__.py文件中写(指定)

__all__ = [''module_A'']

如果改为

__all__ = []
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named module_A

运行则会报错,如上

这也就是说,package内的module的导入是受__init__.py限制的

好了,最后来看看,如何在package内部互相调用。


如果希望调用同一个package中的module,则直接import即可。

也就是说,在module_A.py中,可以直接使用import module_others
如果不在同一个package中,例如我们希望在module_A.py中调用module_B.py中的FuncB,则应该这样:
from module_B的包名(目录).module_B import funcB

python 中的__iter__ __reversed__ __next__

python 中的__iter__ __reversed__ __next__

__reversed__ 返回集合的倒叙迭代器,如果没有实现这个方法,reversed () 会去使用__getitem__和__len__来实现

介绍__next__和 __iter__方法需要了解下可迭代对象 (iterable) 和迭代器 (iterator):

    标准的迭代器都有两个方法__next__和__iter__:
        __next__    返回下一个可用的元素,如果没有元素了,抛出 StopIteration 异常
        __iter__     返回 self
        
    什么是可迭代对象:
        如果对象实现了__iter__方法,那么对象就是可迭代的。python 中的序列都可以迭代。如果没有实现__iter__, 实现了__getitem__ 方法,而且参数是从零开始的索引,这种对象也可以迭代。
        
    迭代器和可迭代对象的关系:
        python 从可迭代对象中获取迭代器 (可迭代对象 ---iter ()---> 迭代器 ---next ()---> 值)    

 

In [9]: a=(1,2,3)

    In [10]: type(a)
    Out[10]: tuple

    In [11]: b=iter(a)

    In [12]: type(b) Out[12]: tuple_iterator In [13]: a=[1,2,3] In [14]: type(a) Out[14]: list In [15]: b=iter(a) In [16]: type(b) Out[16]: list_iterator In [20]: while True: ...: try: ...: print(next(b)) ...: except StopIteration: ...: break ...: 1 2 3 也可以使用for来做,上面的异常python已经内部自动处理: In [3]: for i in b: ...: print(i) ...: 1 2 3

 

    例子:定义一个可迭代对象和迭代器
   

from random import choice
class TmptestIterator: def __iter__(self): return self def __next__(self): tmp=choice([i for i in range(10)]) if tmp == 5: raise StopIteration return tmp class TemTest: def __iter__(self): return TmptestIterator()
a=TemTest()
print(TmptestIterator,TemTest)
for i in a:
    print (i)

<class ''__main__.TmptestIterator''> <class ''__main__.TemTest''>
6
1
1
2
2
2
1
3

 

参考:https://docs.python.org/3/library/stdtypes.html#container.__iter__()

 

Python 的__del__()方法 ---内存回收,对象销毁 || 与__init__方法对比

Python 的__del__()方法 ---内存回收,对象销毁 || 与__init__方法对比

 __del__():

    使用场景:
        1、当删除对象时,Python解析器会默认调用__del__()方法
        2、销毁(释放)内存中的对象时回调__del__()方法

新建一个 User 类:

class User():
    def __init__(self):
        print('User 初始化成功---')
 
    def __del__(self):
        print('User 对象被回收---')

示例一:

# 创建一个user对象
u = User()
 
# 删除该User对象
del u
 
print('del u -------------')


执行结果
 User 初始化成功---
 User 对象被回收---
 del u -------------

代码详解:

  u = User() 在内存中创建了一个 User 对象,并且让变量 u 引用该内存的 User 对象

  del u 删除变量 u , 此时内存中的 User 对象没有任何变量对其引用,Python解析器就会回调 __del__()方法,回收内存

 

示例二

u1 = User()
u2 = u1

del u1
print('del u1 -------')
 
del u2
print('del u2 -------')

执行结果
User 初始化成功---

del u1 -------
User 对象被回收---
del u2 -------

代码解析:

  u1 = User() 创建一块存放 User 对象的内存,并且,变量 u1 指向该内存

  u2 = u1 此处又新建变量 u2, 并且 u2 引用了 u1 的内存地址,此时,u1 和 u2 同时引用同一个内存地址

  del u1 删除 u1 时,删除该变量对User对象的引用,此时,由于内存中的 User 对象还在被 u2 引用,所以不会回收该内存(不会回调__del__()方法)

  del u2 删除 u2 后,内存中的 User 对象已经没有引用的变量,此时解释器才会对内存进行回收,回调 __del__()方法

我们今天的关于如何编写良好/正确的__init__.py包文件怎么编写.py文件的分享已经告一段落,感谢您的关注,如果您想了解更多关于python __new__ 和 __init__、python 中的__init__.py的用法与个人理解、python 中的__iter__ __reversed__ __next__、Python 的__del__()方法 ---内存回收,对象销毁 || 与__init__方法对比的相关信息,请在本站查询。

本文标签: