20. 企业级开发基础1:自定义模块

本节内容

1 模块的概念和意义
2 模块的定义和使用
3 再说变量的作用域

之前的课程中,我们已经了解了python程序设计开发的基础部分内容 包含了数据类型、变量、运算符、程序选择结构、循环结构、函数处理、字符串处理等等内容。 本节内容开始,我们开始学习python企业级开发基础部分的内容,会涉及到模块式整合开发、面向对象程序设计、错误的调试和测试、高级开发[文件IO处理,网络编程,多线程程序开发、正则表达式等等]内容,

1. 模块的概念和意义

我们在常规程序开发的过程中,如果只是通过python来写一些项目维护的小脚本程序,前面学过的内容已经基本够用了,但是如果涉及到企业级开发的复杂的一些需求的话,程序设计开发过程中会出现大量的代码,如果着大量的代码(如:1万行代码)写在一个python文件中,就会让这个文件的体积非常的庞大,开发过程中会造成大量的不必要的问题:如变量定义是否会覆盖其他定义的变量,添加功能处理代码会否影响其他的功能,由于大量代码集中在一个文件中导致修改维护变得非常的不容易,代码的可读性非常 差等等各种问题。

此时,为了方便我们将不同的处理功能区分开,我们将处理不同数据或者功能的函数分别分组存放在不同的python文件中,就会将上面一个比较庞大的python文件拆分成多个python文件,每个python文件中的代码内容会比较少,通过多个Python文件互相组合的方式来完成复杂的处理功能。这样拆分的不同的python文件,每个python文件就是一个单独的python模块,专业术语:module 我们定义好的Python模块,可以在需要的地方,通过import 模块名称关键字来引入这个模块,代码如下:

user.py 用户模块
--------------
def showInfo(name, age):
      print("user info:  name[" + name + "] age [" + age + "]")
--------------
goods.py 商品模块
--------------
def showGoods(name, price):
      print("goods info: goodsName: [" + name + "] price [¥" + str(price)+ "]")
--------------
main.py 主模块中使用其他的模块
--------------
import user
import goods

user.showInfo("tom", 18)
goods.showGoods("alienware", 14999)

拆分模块的好处是第一、将一个比较复杂的单文件拆分成多个文件,方便代码的管理和开发维护,第二、我们开发并完善好的Python模块,在其他需要这个模块功能的地方就可以直接引入组合这个模块,不需要重复编写Python代码了,第三、不同的python模块中,就可以使用相同名称的变量了,不同模块中的变量不会互相覆盖数据或者产生冲突,降低了我们代码开发的成本

2. 模块的使用和解决的问题

拆分模块之后,我们会遇到这样的问题

2.1. 变量名称冲突

变量名称在不同的python文件/模块中,同名变量不会互相产生冲突

user.py 用户模块
--------------
# 记录当前系统中用户数量的变量count
count = 12
# 打印当前系统中用户数量的函数
def getCount():
      print("user count:" + str(count))
--------------
goods.py 商品模块
--------------
# 记录当前系统中商品数量的变量count
count = 1001
# 获取并答应当前系统中所有商品数量的函数
def getCount():
      print("goods count:" + str(count))
--------------
main.py 主模块中使用其他的模块
--------------
import user
import goods
user.getCount()  #执行结果:12
goods.getCount() # 执行结果:1001
2.2. 模块名称冲突

我们也同样考虑到了,模块名称和定义变量一样,某些情况下模块名称也有可能冲突,如:我们的项目中处理用户数据定义了一个工具模块utils.py,处理商品数据定义了一个工具模块utils.py,此时这两个模块冲突了;解决方案如下 我们会将不同的模块,python定义了包的概念,根据处理的功能或者数据的不同,存放在不同的包中,用于区分不同的模块; 包在python中,就是一个文件夹,为了区分包文件夹和普通的文件夹,在包文件夹中,必须定义一个__init__.py模块文件,这个文件内容可以为空。

# 1. 创建users文件夹,是用来处理用户数据的包
# 2. 在users文件夹下创建__init__.py文件,内容可以为空
# 3. 在users文件夹下创建utils.py工具模块
--------------
"这是处理用户数据的工具模块"
x = 129.00
y = 432.24
# 获取用户当前位置的函数
def getLocation():
      # 返回用户位置数据
      return x, y
--------------
#4. 创建goods文件夹,是用来处理用户数据的包
#5. 在goods文件夹下创建__init__.py文件,内容可以为空
#6. 在goods文件夹下创建utils.py工具模块
--------------
"这是处理商品数据的工具模块"
address = "河南郑州"
# 获取商品产地的函数
def getProduction():
      # 返回商品的产地
      return address
--------------
7.创建main.py程序运行的入口文件,引入users和goods两个模块
使用不同模块中的函数
--------------
import users.utils
import goods.utils
xx, yy = users.utils.getLocation()
addr = goods.utils.getProduction()
print(xx, yy)
print(addr)

包->模块开发

3. 模块中再说变量

变量在之前的课程中,我们已经提到了变量在Python中有局部变量和全局变量的区分,是通过是否定义在函数内部来区分的。 此时有了多模块之后,对于变量的作用域,需要进行更加细致的划分。

3.1. 模块内部

模块内部,还是按照正常的情况进行划分,按照是否定义在函数内部来区分全局变量和局部变量,在模块文件内部,变量的使用没有任何的变量 在模块内部,变量依旧是全局变量/局部变量,变量的作用域正常使用即可

"这是一个用户数据处理模块"
# 全局变量,记录系统中用户的在线人数
onlineCount = 100

def getUserinfo(name):
      # 定义了一个局部变量,这个局部变量只能在当前函数内部访问
      msg = "尊敬的用户您好,"
      if name == "":
            name = "游客"
      return msg + name;
3.2. 不同模块之间的变量访问

python中定义了模块之后,不同模块之间访问数据和函数的情况就比较常见了;模块中的变量,有些是需要让别的模块访问的,有些是不希望别的模块访问的,此时就会将变量区分为模块公开的变量、模块私有的变量两种变量了。

  • python的模块中,按照正常的命名规则命名的变量或者函数,规范为公开的变量或者函数,其他的模块都可以正常的访问
  • python的模块中,使用一个下划线开头来命名的变量或者函数,规范为私有的变量或者函数,只能在当前模块中使用
  • python的模块中,使用两个下划线开头的变量,可以别模块直接引用使用具有特殊的含义,如__name__表示当前模块名称等等;规范要求我们自己的变量名称尽量不要使用这样的名称。
"商品信息管理模块goods.py"
# 游客打折折扣,变量名称下划线开头,不希望其他模块访问
_discountVisitor = 9.5
# 会员打折折扣,变量名称下划线开头,不希望其他模块访问
_discountMember = 8.5

# 游客购买折扣计算,函数名称下划线开头,不希望其他模块访问
def _visitorBuy(goodsName, price):
    resPrice = price * _discountVisitor;
    print("尊敬的游客,您购买了" + name + ",总价格是:" + str(resPrice));

# 会员购买折扣计算,函数名称下划线开头,不希望其他模块访问
def _memberBuy(goodsName, price):
    resPrice = price * _discountMember;
    print("尊敬的游客,您购买了" + name + ",总价格是:" + str(resPrice));

# 购买商品的函数,允许其他模块访问的函数,正常命名
def buy(type, name, price):
    if type == 1:
        _visitorBuy(name, price)
    elif type == 2:
        _memberBuy(name, price);
    else:
        print("对不起,您没有权限购买商品")

注意:这里出现了公开/公有变量和私有变量/函数的概念,公开/公有变量/函数就是我们平时定义的普通的全局变量/函数;这里的私有变量/函数,是在原有的全局变量/函数的基础上,变量名称前面加了一个下划线,约定这是私有的变量/函数,不应该让其他的模块访问【记住:这里的约定,不是强制,所以其他模块如果要访问这样的私有变量,还是可以访问到的,但是规范上不应该这么做】

"用户信息处理模块users.py"
# 这里定义了一个私有的变量 _userType和_userDesc
_userType = "管理员"
_userDesc = "游客操作权限,只能访问不能修改任何信息"
def _changeDisc(_userType):
    if _userType == "管理员":
        _userDesc = "超级管理员操作权限"
    if _userType == "会员":
        _userDesc = "普通操作权限,不能修改敏感信息"
-------------------------
"程序运行的主要模块main.py"
import users
# 使用users模块中的_userType变量
print(users._userType)
users._userType = "会员"
print(users._userType)
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
#  上面的代码中,我们可以在main模块中,访问引入的
# 另一个模块users模块中定义的私有变量_userType
# !这不是我们想要的,私有的不是不能让其他模块访问吗?
# !这里请注意:下划线开头的变量,规范是私有变量,不应该
# 让其他的模块访问,而不是强制,这里的规范是一种项目开发约定!
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Python小屋

Python选择结构注意事项

以百分制成绩转换为字母等级成绩为例,简单介绍一下Python选择结构需要注意的事项。

1433
来自专栏web前端教室

《JS回调是怎么回事》 | 7月28日微课 文字版

image.png 大家好,今晚的微课主要讲一个JS的回调。 这段时间51题练习群里有同学问回调是怎么回事?这个问题我竟然一时无法回答,因为简单的说就一句话,当...

21010
来自专栏CodingToDie

Python学习(九):错误再多 我也要改正

当遇到错误的时候,有时我们并不想终止程序运行,遇到某些错误,我们想给用户一个友好的提示,告诉用户为什么出错,这也是必要的。

3616
来自专栏码生

shell 语法 干货

832
来自专栏ImportSource

并发编程-原子性

前面我们说了有关stateless的内容,那么如果我们在一个stateless的object中添加一个状态元素会发生什么呢?现在假设我们想要添加一个命中计数器(...

38611
来自专栏北京马哥教育

记一次调试python内存泄露的问题

这两天由于公司需要, 自己编写了一个用于接收dicom文件(医学图像文件)的server. 经过各种coding-debuging-coding-debugi...

6607
来自专栏小樱的经验随笔

如何在命令长度受限的情况下成功get到webshell(函数参数受限突破、mysql的骚操作)

还记得上篇文章记一次拿webshell踩过的坑(如何用PHP编写一个不包含数字和字母的后门),我们讲到了一些PHP的一些如何巧妙地绕过数字和字母受限的技巧,今天...

1312
来自专栏北京马哥教育

Python 函数库 APIs 编写指南

2854
来自专栏我就是马云飞

设计模式二十四章经之状态模式

931
来自专栏技术专栏

Scala入门与进阶(一)- 初始Scala

1012

扫码关注云+社区