分享

程序员的拿来主义,Python模块管理的入门详解,初学者福利

 静幻堂 2020-01-05
纸飞机编程 2020-01-04 10:39:13
程序员的拿来主义,Python模块管理的入门详解,初学者福利

我在写第一行Python之前,以为自己是一个C/C++、JAVA程序员,每天写着大段大段 “高端” 代码乐在其中。

这会顺便去以前的博客掐了一段10年前写过的一段C++的代码,如果没有备注的话今天我都不这么看得懂当初在写什么了。

//  文件下载int fwrite(void *buffer, size_t size, size_t nmemb, void *stream){        struct FtpFile *out = (struct FtpFile *)stream;        if (out && !out->stream)        {                out->stream = fopen(out->filename, "wb");                if (!out->stream)                {                        return -1;                }        }        return fwrite(buffer, size, nmemb, out->stream);} 

在我写了2年C++代码之后,虽然做了一些桌面应用产品,但是我自己一直都不好意思说自己会C和C++,总觉得智商受到了挑战,没学好。

直到因为一个Web项目开始写Python之后,我发觉世界简单了很多,好像Python是专门为我这种天生智力不足的程序员准备的,用起来顺手多了。

原因只有一个,我其实是一个 “二手程序员“,更喜欢拿来主义,直接用别人做好的、现成的东西组装一下就能用。

就跟现在网上流行的说法:后端程序员是CRUD BOY,搞算法的是调参侠,前端程序员是切图员等等诸如此类,主要是为了调侃平时绝大部分程序员做的应用都偏业务层面,没有太多高精尖的技术可言,没有底层组件的研究、没有什么芯片开发、新的图像技术突破等等,当然这绝大部分也包括我在内。

不过我们不用为此感到羞愧,因为即使是拿来主义,也要明白通过什么方式拿来并使用。

今天来讲讲Python的模块管理,看看我们是怎么直接用别人现成代码的。

知识点:

  • python的 “main函数”
  • import 的使用方式
  • 模块、包、库的概念
  • init.py的用处

Python的 "main函数"

在很多语言里,都有一个叫做main函数的东西,通常用于定义一个程序的入口,意思就是当程序启动时要干的事情。

在C语言里差不多长成这样。

int main( void )  {    return 0;}

在JAVA里就挺琐碎了。

public class AClass {  public static void main(String[] args) {      System.out.println("hello world");  }}

这些语言都用了一个明确的内置函数名(main) 去确定程序的入口,那么Python有main函数吗?

事实上是没有的,Python没有一个内置函数来定义程序的入口,而是用到了一下这种方式。

程序员的拿来主义,Python模块管理的入门详解,初学者福利

以上7行代码我们来分别解读一下。

首先运行程序后会执行第4行的print('start'),然后第5行用了一个逻辑判断,来定义了一个伪main函数,并且打印hello world,以及执行fun1函数。

我们看到逻辑判断里用了一个__name__ 的内部变量,它的值是什么呢?

程序员的拿来主义,Python模块管理的入门详解,初学者福利

默认情况下一个python源文件在被执行时,它的__name__变量的值就是 字符串格式的 __main__,大家可以自行打印试验一下。

那么为什么需要有这么一个东西呢?我们不用它一样可以按照顺序执行代码啊?

在这里我们再来看一个例子。

程序员的拿来主义,Python模块管理的入门详解,初学者福利

我对刚才那个one.py文件做了下改进,增加了一行代码,用于打印了当前模块的__name__ 值。

然后我新增了一个叫 two.py的文件,我们来看看two.py的内容和执行结果

程序员的拿来主义,Python模块管理的入门详解,初学者福利

我们用到了一个import的语句,它的用处就是导入其他的py文件,作为当前程序的一个模块。

但是我们发觉当我导入one这个模块时,它只打印了它的__name__ 值和start字符串,并没有执行别的东西。

然后第二行代码我们同样输出了当前two.py 文件里 __name__ 的值。

看到这里不知道各位有没有发觉一个规律,那就是如果一个Python程序文件被其他的程序文件通过import语句导入之后,不会执行被导入文件中的“main”函数,因为它的__name__值已经不是__main__了,我们可以简单粗暴的认为,谁的程序文件当前在被Python执行,谁才有main函数,其他的文件只能作为当前程序文件的一个模块存在。

反过来也是一样,我们也可以在one.py里去import two。

通过以上的例子我们至少学到两个东西。

  • 第一是Python程序文件可以被其他程序文件在自己内部直接import(引用),引用的对象我们就称之为模块
  • 第二是我们可以利用Python "main" 函数这个特性去做不少事情,例如我写一个模块文件,包括很多类,很多函数,然后在main里面去对当前模块进行测试和调用。当前模块被其他程序引用时,不会执行"main"函数里的测试代码,保证了测试和被调用两不误。

import用法

现在我们来仔细说说import的用法,先看个漫画。

程序员的拿来主义,Python模块管理的入门详解,初学者福利

这个漫画其实很大程度在说Python程序员如何用拿来主义做好一个“二手程序员”的,因为有大量现成的模块可以使用时,就没必要再自己写了,重复造轮子不符合程序员懒惰的性格。

关于import导入模块,有两种语法,我们都分别介绍一下。

第一种:当one.py和two.py在同一目录下时,我们想在 two中import one。

# one.pymyname = 'myname is one'
# two.pyimport oneprint(one.myname)
程序员的拿来主义,Python模块管理的入门详解,初学者福利

第二种:当需要import的模块存在于别的目录时,例如下面这种目录结构。

程序员的拿来主义,Python模块管理的入门详解,初学者福利

我打算在 two.py 中 import 跟他同一层目录下的test/pkg_1.py

程序员的拿来主义,Python模块管理的入门详解,初学者福利

于是语法变成了这样,在import前面加了一个from,它的中文意思其实就是 “从test 引入 pkg_1“。

如果我们想在test目录里再加一层目录,那么该如何import呢?

程序员的拿来主义,Python模块管理的入门详解,初学者福利

简单的说我们只需要用 “.” 号替代目录结构中的下划线即可,有多少个层级就用多少个"."号

例如 我想引入 test/test2/china/sichuan/city.py 这个文件。

那么就应该写成 from test.test2.china.sichuan import city,注意 city不用加文件名。

其实关于这两种方式我们要讲的还很多,不过鉴于这是一个初学者的教程系列,我们暂时讲到这即可。

import总的来说就是用来引入其他Python文件的钥匙,通过它我们可以解放大脑和双手,尽量去import现成的模块来用。

同时也可以将我们写好的代码通过模块管理的方式组织得更加科学,便于其他人直接import使用。

模块、包、库

在以上的例子中我们其实已经可以了解到一些关于模块和包的概念里。

简单的说,一个py文件其实就是一个模块(module) 当我们通过import 语句对一个Python程序文件进行引用时,我们将其称之为模块。import之后可以直接使用模块中的变量,函数和类等等一切现成的代码。

的意思很简单,我们只要发现某个目录下包含有__init__.py 文件,就可以称当前目录是一个包,所谓包,意思就是将一堆模块放在一起,然后申请一个命名空间,等着随时被 from import使用。

至于,其实是一个概念,为了和其他的语言做叫法上的兼容,在Python里,它就是以模块或者包的形式出现的。

init.py 文件

在编辑器里大家看目录结构可能不直观,我换个方式给大家看看刚才我们这几个Python文件的目录结构。

程序员的拿来主义,Python模块管理的入门详解,初学者福利

one.py和two.py在根目录,test目录下有一个pkg_1.py和__init__.py的文件。

那么__init__.py是干嘛的呢?

简单的说它的用处就是声明一个文件夹为一个包,通常__init__.py文件里面没有任何内容,只需要这么一个空文件存放在文件夹里即可。

那么有人会问,为什么test下的test2目录里为什么不用加上__init__.py呢?诸位请看以下代码。

程序员的拿来主义,Python模块管理的入门详解,初学者福利

我们可以看到 test.test2 被声明成一个包之后,在第3行打印它的名称,在第4行打印它的类型。

我们会发现 test.test2本质是就是一个模块类产生的对象 (class 'module' ),只是它有一个叫namespace的东西,我们现在可以理解为,当一个模块对象拥有这个namespace的时候,它就是一个包,可以通过它去import包里面的其他模块。

同时我们也打印了被引入的 pkg_2模块,它同样是一个模块类产生的对象,只是我们看到它有一个from xxxx.py的内容,表明这个模块是来自于本地某个Python文件里。

总结:

Python的improt机制是我们构建大型程序的基石,不管是用大量网上的现成模块还是去组织自己的代码模块。在本文,我们对于模块的机制讲得还不够深入,未来在进阶教程里我们会深入到Pyhton模块机制内部,看看它究竟是怎么工作了,目前来说我们只要学到如何通过import引入文件并使用即可。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多