Python——模块:模块就是程序

呃……好像说得有点太多了,大家一定要自己动手先尝试完成哦~
请务必自己先动手,贪一时之快先看答案,您将失去一次锻炼的机会。
回复您的答案即可查看参考答案!
测试题答案:

0. 说到底,Python 的模块是什么?
答:模块就是程序。没错,所谓模块就是平时我们写的任何代码,然后保存的每一个“.py”结尾的文件,都是一个独立的模块。
1. 我们现在有一个 hello.py 的文件,里边有一个 hi() 函数:

  1. def hi():
  2.     print("Hi everyone, I love FishC.com!")

复制代码


请问我如何在另外一个源文件 test.py 里边使用 hello.py 的 hi() 函数呢?
答:只需要在 test.py 中导入 hello 模块(文件名 = 模块名)即可使用 hello.py 中的 hi() 函数。
2. 你知道的总共有几种导入模块的方法?
答:我们总共介绍了三种导入模块的方法。
第一种:import 模块名
第二种:from 模块名 import 函数名
第三种:import 模块名 as 新名字

3. 曾经我们讲过有办法阻止 from…import * 导入你的“私隐”属性,你还记得是怎么做的吗?
答:如果你不想模块中的某个属性被 from…import * 导入,那么你可以给你不想导入的属性名称的前边加上一个下划线(_)。不过需要注意的是,如果使用 import … 导入整个模块,或者显式地使用 import xx._oo 导入某个属性,那么这个隐藏的方法就不起作用了。

4. 倘若有 a.py 和 b.py 两个文件,内容如下:

  1. # a.py
  2. def sayHi():
  3.     print("嗨,我是 A 模块~")
  4.  
  5. # b.py
  6. def sayHi():
  7.     print("嗨,我是 B 模块~")

复制代码


那么我在 test.py 文件中执行以下操作,会打印什么结果?

  1. # test.py
  2. from a import sayHi
  3. from b import sayHi
  4.  
  5. sayHi()

复制代码


答:会打印“嗨,我是 B 模块~”,因为第二次导入的 b 模块把 a 模块的同名函数 sayHi() 给覆盖了,这就是所谓命名空间的冲突。所以,在项目中,特别是大型项目中我们应该避免使用 from…import...,除非你非常明确不会造成命名冲突。
5. 执行下边 a.py 或 b.py 任何一个文件,都会报错,请尝试解释一下此现象。

  1. # a.py
  2. from b import y
  3. def x():
  4.     print('x')
  5.  
  6. # b.py
  7. from a import x
  8. def y():
  9.     print('y')
  10.  
  11. >>> 
  12. Traceback (most recent call last):
  13.   File "/Users/FishC/Desktop/a.py", line 1, in <module>
  14.     from b import x
  15.   File "/Users/FishC/Desktop/b.py", line 1, in <module>
  16.     import a
  17.   File "/Users/FishC/Desktop/a.py", line 1, in <module>
  18.     from b import x
  19. ImportError: cannot import name 'x'

复制代码


答:这个是循环嵌套导入问题。无论运行 a.py 或 b.py 哪一个文件都会抛出 ImportError 异常。这是因为在执行其中某一个文件(a.py)的加载过程中,会创建模块对象并执行对应的字节码。但当执行第一个语句的时候需要导入另一个文件(from b import y),因此 CPU 会转而去加载另一个文件(b.py)。同理,执行另一个文件的第一个语句(from a import x)恰好也是需要导入之前的文件(a.py)。此时,之前的文件处于仅导入第一条语句的阶段,因此其对应的字典中并不存在 x,故抛出“ImportError: cannot import name 'x'”异常。
解决方案是直接使用 import 语句导入:

  1. # a.py
  2. import b
  3.  
  4. def x():
  5. print('x')
  6.  
  7. # b.py
  8. import a
  9.  
  10. def y():
  11.     print('y')
  12.  
  13. a.x()

复制代码



动动手答案:


0. 问大家一个问题:Python 支持常量吗?相信很多鱼油的答案都是否定的,但实际上 Python 内建的命名空间是支持一小部分常量的,比如我们熟悉的 True,False,None 等,只是 Python 没有提供定义常量的直接方式而已。那么这一题的要求是创建一个 const 模块,功能是让 Python 支持常量。
说到这里大家可能还是一头雾水,没关系,我们举个栗子。
test.py 是我们的测试代码,内容如下:

  1. # const 模块就是这道题要求我们自己写的
  2. # const 模块用于让 Python 支持常量操作
  3. import const
  4.  
  5. const.NAME = "FishC"
  6. print(const.NAME)
  7.  
  8. try:
  9.     # 尝试修改常量
  10.     const.NAME = "FishC.com"
  11. except TypeError as Err:
  12.     print(Err)
  13.  
  14. try:
  15.     # 变量名需要大写
  16.     const.name = "FishC"
  17. except TypeError as Err:
  18.     print(Err)

复制代码


执行后的结果是:

  1. >>> 
  2. FishC
  3. 常量无法改变!
  4. 常量名必须由大写字母组成!

复制代码


在 const 模块中我们到底做了什么,使得这个模块这么有“魔力”呢?大家跟着小甲鱼的提示,一步步来做你就懂了:
 

  • 提示一:我们需要一个 Const 类
  • 提示二:重写 Const 类的某一个魔法方法,指定当实例对象的属性被修改时的行为
  • 提示三:检查该属性是否已存在
  • 提示四:检查该属性的名字是否为大写
  • 提示五:细心的鱼油可能发现了,怎么我们这个 const 模块导入之后就把它当对象来使用(const.NAME = "FishC")了呢?难道模块也可以是一个对象?没错啦,在 Python 中无处不对象,到处都是你的对象。使用以下方法可以将你的模块与类 A 的对象挂钩。

 

  1. '''
  2. sys.modules 是一个字典,它包含了从 Python 开始运行起,被导入的所有模块。键就是模块名,值就是模块对象。
  3. '''
  4. import sys
  5. sys.modules[__name__] = A()

复制代码


呃……好像说得有点太多了,大家一定要自己动手先尝试完成哦~
代码清单:

  1. # 该模块用于让 Python 支持常量操作
  2. class Const:    
  3.     def __setattr__(self, name, value):
  4.         if name in self.__dict__:
  5.             raise TypeError('常量无法改变!')
  6.             
  7.         if not name.isupper():
  8.             raise TypeError('常量名必须由大写字母组成!')
  9.  
  10.         self.__dict__[name] = value
  11.  
  12. import sys
  13. sys.modules[__name__] = Const()

复制代码

# const 模块就是这道题要求我们自己写的
# const 模块用于让 Python 支持常量操作
import const

const.NAME = "FishC"
print(const.NAME)

try:
    # 尝试修改常量
    const.NAME = "FishC.com"
except TypeError as Err:
    print(Err)

try:
    # 变量名需要大写
    const.name = "FishC"
except TypeError as Err:
    print(Err)
import sys


# 该模块用于让 Python 支持常量操作
class Const:
    def __setattr__(self, name, value):
        if name in self.__dict__:
            raise TypeError('常量无法改变!')

        if not name.isupper():
            raise TypeError('常量名必须由大写字母组成!')

        self.__dict__[name] = value


sys.modules[__name__] = Const()

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值