12_python笔记-模块与包


博客cpen_web

练习1

def register():
    print('============注册=============')
    name = input('请输入用户名:')
    user_exit(name)
    with open('user.txt','r',encoding='utf-8') as f:
        s = f.read()
        #json.loads 是把json str 转化成 dict	# json.loads 是把json str 转化成 dict
        user_dict = json.loads(s)
    if name in user_dict:
        print('用户名已存在')
    else:
        pwd = input('请输入密码:')
        user_exit(pwd)
        with open('user.txt', 'w', encoding='utf-8') as f:
            user_dict[name] = pwd
            #把dict  -->  json.str		# 把dict  -->  json.str
            user_str=json.dumps(user_dict)
            f.write(user_str)
        with open('user_count.txt', 'r', encoding='utf-8') as f:
            s = f.read()
            user_count_dict = json.loads(s)
        with open('user_count.txt','w',encoding='utf-8') as f:
            user_count_dict[name] = 0
            f.write(json.dumps(user_count_dict))
            print('注册成功!')

·快速判断出列表中是否有重复的元素

方法1:去重(推荐)

my_str = input('请输入列表中的元素,用空格分开:')
my_list = my_str.split()
print(f'列表为{my_list}')
my_set = set(my_list)
if len(my_list) != len(my_set):
    print('列表中有重复')
else:
    print('列表中没有重复')

方法2

lst = list()
for i in range(5):
    lst.append(input(f"请输入第{i+1}个元素:"))
print(lst)
for i in lst:
    if lst.count(i) != 1:
        print("列表中有重复的元素")
        break
    else:
        print("列表中没有重复的元素")

·输出一个字符串中最长子回文

方法1

s = input("请输入:")
res = s[::-1]
lst = list()
for i in range(0, len(s)):
    for j in range(len(s),0,-1):
        if j > i and s[i:j] == res [len(s)-j:len(s)-i]:
            lst.append(s[i:j])
max_lst = [lst[0]]
max_len = len(lst[0])
for i in lst:
    if len(i) < max_len:
        continue
    elif len(i) == max_len:
        max_lst.append(i)
        max_lst = list(set(max_lst))
    elif len(i) > max_len:
        max_lst = [i]
        max_len = len(i)
for i in max_lst:
    print(i, end = " ")

方法2

def func(demo):
    demo_back = demo[::-1]
    # print(demo,demo_back)
    if demo == demo_back:
        return True
    else:
        return False

my_str = input('请输入字符串:')
result = dict()
max_lenght = 0
for i in range(len(my_str)):
    for j in range(i+1,len(my_str)+1):
        cut_str = my_str[i:j]
        print(cut_str)
        if func(cut_str):
            result[cut_str] = len(cut_str)
print(result)

for item in result.values():
    if item >= max_lenght:
        max_lenght = item
for key,value in result.items():
    if value == max_lenght:
        print(key)

知识点2 Python模块的导入

什么是模块(module)
·模块就是Python文件,里面定义了很多的函数、类、变量
·一个完整大型的python程序是由模块和包的形式组织起来的,可见模块在python中的重要性

模块有什么作用
· 在python交互式解释器中操作输入的代码,在退出python时是不会被保存的; 而模块文 件中的代码是永久存在的
·减少重复代码, 减少工作量(写的量、改的量)、代码更优雅、拿来主义

模块的分类
·标准模块(库) # 注:自带的,直接import导入 import math
·第三方模块(库) # 注:需要pip install 安装的库 import requests
·自定义模块 # 注:自己写的
Python许多时候自己定义的函数,需要经常调用时;就可以自己定义一个模块,将常用函数写入模块里,下次使用常用函数时直接导入模块,就可以使用函数了

#注:ctrl + 右键 查看源代码
#注:math模块中sqrt 开平方的

什么是包(package)
·Python包实际上是一个目录
·包结构的目录里面可以有一个 init.py 模块
·py2与py3
·py2:init.py是必须的
·py3:init.py是可选的
·模块和包名要尽量和内置的模块名不相同, 不然会覆盖内置的模块

知识点3 Python模块的导入

import/from import导入
·直接导入模块

示例

import math
print(math.sqrt(5.55))

·从模块里面导入函数/从包是导入模块

示例

from math import sart
print(sqrt(9.0))

·导入所有函数(不推荐使用*这样导入)

示例

from math import *
print(sqrt(9))

使用名字导入

示例:使用importlib实现动态导入

>>> import importlib
>>> importlib.import_module("math")
<module 'math' from '/usr/lib64/python3.6/lib-dynload/math.cpython-36m-x86_64-linux-gnu.so'>
>>> mod = importlib.import_module("urllib.request")

制作包与模块

pack01(包)
init.py (python文件)
one.py (python文件)

print("pack01.one")	#(文件内容)
def packtest():
    print("pack 01 test function")
two.py		(python文件)
print("pack01.two")	#(文件内容)

pack02(包)
three.py (python文件)

print("pack02.three")#(文件内容)
def packtest():
print("pack 02 test function")

main.py (python文件)

from pack01 import one
from pack01 import one      # 注:导入2次,只执行第1次

知识点4 Python模块的导入

同一个模块重复导入
·当同一个模块重复导入时,只执行第一次

示例

from pack01 import one
from pack01 import one      # 注:导入2次,只执行第1次

导入重名的模块
·两个都会执行,当前生效的是后导入的模块

示例

main.py	
from pack01.one import packtest
from pack02.three import packtest
packtest()

导入相同的模块名,使用后导入的

解决方法:取别名 [重名的模块,as取别名]

示例1

from pack01.one import packtest as packtest_01
from pack02.three import packtest
packtest_01()
packtest()

示例2

import pandas as pd
pd.to_date()

知识点5 相对导入

相对导入
·相对导入使用 . 或 … 来进行导入
·相对导入只能导入包中的模块/子包
·Python会自动识别一个目录是不是包
·对于当前被执行的文件来说: # 注:程序的top_level
·当前执行文件所在目录不是一个包
·子目录及更深的目录都是包

#注:相对导入在运行的主文件中不能使用
相对导入 . 或 …来导入
不能导入程序入口top_level这一层的包或模块
可以使用相对导入,导入top_level下一层的包或者模块
绝对导入
相对于top_level所在路径的绝对位置

重要的是关注程序入口在哪里 top_level

示例1

#pack02
#pk2child
	#pk2.py		# 注:__name__内置函数
	print(__name__)	# 注:__main__  主程序入口,执行程序
#pk2other
	#pk3.py
	print(__name__)	# 注:__main__  主程序入口,执行程序

name
作为直接执行的程序时 打印出__main__
作为模块导入时 打印出导入的模块的路径
name__会保存当前python执行的模块路径
name 如果是直接运行的程序,会打印__main

其他情况下会打印执行的模块路径

程序在哪里运行,它的入口就是top-level
程序的入口在哪里,它的top-level就在哪里
用相对导入只能导入同级的下一级的模块 top_level的层级往下走
top_level 第一层级 main

示例2

main.py作为top_level
pk2 想导入pk3
绝对导入:from pack02.pk2other import pk3
相对导入:from …pk2other import pk3
(相对导入-相对自己本身而言)

three.py 作为主程序 top_level
pk2 想导入pk3
绝对导入:from pk2other import pk3
相对导入:不可以

示例3

pack02/pk2child/pk2.py

print("pk...print...")
print(__name__)

print("import pk3")
from ..pk2other import pk3      # 注:..代表上一级 相对导入
from ..three import packtest
pack02/pk2other/pk3.py
print(__name__)

from pack02.pk2child import pk2    # 注:绝对导入

if __name__ == "__name__":
    print("this is pk3 main test")
pack02/three.py
print("pack02.three")

def packtest():
    print("pack 02 test function")

from pk2other import pk3       # 注:绝对导入
main.py	(top_level)
print(__name__)
if __name__ == "__main__":      # 注:程序作为执行程序的时候,执行下面的
    from pack02.pk2child import pk2

知识点6 模块查找顺序

模块查找顺序
·注意:不要跟Python内置的这些模块重名
·查找顺序:
1.Python 中所有加载到内存的模块都放在sys.modules。当import一个模块时首先会在这个列表中查找是否已经加载了此模块,如果加载了则只是将模块的名字加入到正在调用import的模块的Local名字空间中。如果没有加载则从sys.path目录中按照模块名称查找模块文件
2.如果都没有找到模块名就报错

导入2次,只执行第一次
因为第1次导入,就会加载在内存中,下一次导入的时候,会先查看内存中有没有

示例:查看当前内存空间导入的模块

>>> import sys
>>> sys.modules
{'builtins': <module 'builtins' (built-in)>, 'sys': <module 'sys' (built-in)>, ………'copyreg': <module 'copyreg' from '/usr/lib64/python3.6/copyreg.py'>}	# 注:builtins 内置变量

导入2次,只执行第一次
因为第1次导入,就会加载在内存中,下一次导入的时候,会先查看内存中有没有

>>> sys.path
['', '/usr/lib64/python36.zip', '/usr/lib64/python3.6', '/usr/lib64/python3.6/lib-dynload', '/usr/local/lib64/python3.6/site-packages', '/usr/local/lib/python3.6/site-packages', '/usr/lib64/python3.6/site-packages', '/usr/lib/python3.6/site-packages']

#注:第一个为空,表示当前路径
安装的包基本放在site-packages下面

示例

[root@localhost ~]# cd /usr/lib/python3.6/site-packages
[root@localhost site-packages]# ls
easy_install.py  pip  pip-9.0.3.dist-info  pkg_resources  __pycache__  setuptools  setuptools-39.2.0.dist-info
[root@localhost site-packages]# pip3.6 install requests
………………………………
Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.6/site-packages (from requests)
[root@localhost site-packages]# cd /usr/local/lib/python3.6/site-packages
[root@localhost site-packages]# ls
pickleshare-0.7.5.dist-info     ………………
decorator.py                 parso-0.7.1.dist-info             requests                        ws4py
idna                         pexpect                           requests-2.24.0.dist-info       [root@localhost site-packages]# pip3 install pandas
[root@localhost site-packages]# pip3 install pandas
………………………………………………
Requirement already satisfied: numpy>=1.15.4 in /usr/local/lib64/python3.6/site-packages (from pandas)
Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.6/site-packages (from python-dateutil>=2.7.3->pandas)

示例

E:\sanchuang\lianxi>pip3 install pandas
import pandas

知识点7 Python下划线

Python下划线
标识符是用来标识某种对象的名称。以下划线开头的标识符是有特殊意义的。

下划线的特殊含义(模块)
·以单下划线开头的(_foo)
表示保护对象,不能用 from xxx import * 导入包/模块
·以双下划线开头的(__foo)
表示私有对象,不能用 from xxx import * 导入包/模块
·以双下划线开头和结尾的(foo)
代表Python中特殊方法专用的标识,不建议用户使用这种命名方式。

示例

02下划线 # 注:文件夹
code # 注:文件夹
init.py # 注:python文件
_model.py # 注:python文件
model.py # 注:python文件
mod.py # 注:python文件

init.py中

from code.model import *
print(a)            # 注:可以打印a 可以打印,但不可以打印下划线变量
# print(_a)         # 注:不可以打印_a
# print(__a)        # 注:不可以打印__a
# print(__a__)      # 注:不可以打印__a
print(func())       # 注:可以调用func()
# print(_func())    # 注:不可以调用_func() 报错:未定义

from code.model import _a
print(_a)                       # 注:可以打印
from code import model
print(model.__a)                # 注:可以打印
print(model.a)                  # 注:可以打印
print(model._a)                 # 注:可以打印
#注:以_开头并且以*号导入的  都不能访问

from code.model import a    # 注:导入之前先执行__init__.py

from code import *          # 注:首先执行__init__.py 初始化的操作
#__init__.py加入__all__ = ["model", "_model"]才可以使用 * 导入

_model.py中

print("i am _model.py")

model.py中

print("i am model.py")

a = 0
_a = 1
__a = 2
__a__ = 3

def _func():
    return "func _func"

def func():
    return "func func"

mod.py中

from code.model import *
print(a)            # 注:可以打印a 可以打印,但不可以打印下划线变量
# print(_a)         # 注:不可以打印_a
# print(__a)        # 注:不可以打印__a
# print(__a__)      # 注:不可以打印__a
print(func())       # 注:可以调用func()
# print(_func())    # 注:不可以调用_func() 报错:未定义

from code.model import _a
print(_a)                       # 注:可以打印
from code import model
print(model.__a)                # 注:可以打印
print(model.a)                  # 注:可以打印
print(model._a)                 # 注:可以打印
#注:以_开头并且以*号导入的  都不能访问

from code.model import a    # 注:导入之前先执行__init__.py

from code import *          # 注:首先执行__init__.py 初始化的操作
#__init__.py加入__all__ = ["model", "_model"]才可以使用 * 导入

#示例
init.py文件中
all = [“model”, “_model”] # python里面的内置变量

this is __init__
i am model.py
0
func func
1
2
0
1
i am _model.py

知识点8 模块导入测试

模块导入测试
·测试__init__.py文件中__all__
·定义package中的__all__,用来模糊导入
·导入一个package, 就会首先调用该package的__init__.py文件, 用来初始化模块包
·编写Python代码(不建议在__init__中写python模块,可以在包中在创建另外的模块来写,尽量保证__init__.py简单)

内置属性:name
当自己执行时,等于__name__的值为__main__
当被作为模块导入,等于文件名(不包含后缀, 可含模块名)

其他内置属性
import:导入模块
file:打印模块路径

示例:name == “main” 查看模块是否被运行

[root@localhost ~]# cat one.py
def func():
    return '我是one模块中的函数'

if __name__ == "__main__":
    print(func())
else:
    print("one模块被其他模块导入运行")
[root@localhost ~]# cat two.py
import two

if __name__ == "__main__":
    print(__name__)
[root@localhost ~]# python3 one.py 
我是one模块中的函数
[root@localhost ~]# python3 two.py 
__main__
[root@localhost ~]# ls			# 生成__pycache__文件
one.py         two.py  	__pycache__
[root@localhost ~]# cd __pycache__/
[root@localhost __pycache__]# ls		# 注:python文件 python的字节码
second.cpython-36.pyc  two.cpython-36.pyc	# 注:省略了源代码到字节码的翻译过程

对于主程序而言pyc是临时性的,主程序结束以后,从内存里消失,pyc文件不会被落地到磁盘
对于导入的文件 pyc文件保存到磁盘,节省了重复性翻译
导入的文件,相当于重复性的代码段,翻译成字节码,存到__pycache__里面,落地到磁盘。对于主程序翻译成字节码,不保存到__pycache__,不落地到磁盘
少了一步从源代码到Pyc的翻译过程

print(__file__)	# 注:打印的是当前模块的绝对路径
E:/sanchuang/lianxi/2020-11-2/02下划线/code/model.py

知识点9 文件与模块执行过程

Python文件执行的过程
·词法语法检查
·在内存中生成PyCodeObject
·执行PyCodeObject

Python模块导入执行的过程
·通过sys.path环境变量找到模块文件
·编译成字节码文件(pyc文件)
·如果字节码过期了会自动重新生成
·如果字节码文件已存在则直接导入字节码文件
·执行模块中的代码来创建所定义的对象

知识点10 模块打包与发布

如何分享模块
如何我们写了一个计算Fab第N项的函数,如何分享给别人呢?
·拷贝?
·导入问题?
·依赖问题?

如何使用别人的模块
我们是如何使用第三方模块的?
·pip
·tar.gz

setuptools工具
Setuptools是一个给开发者构建和发布python包的工具,特别是当包依赖于其他包时。
·编写模块与包
在模块中编写show函数
·配置setup.py
·检查setup.py配置是否正确
python setup.py check # 注:命令行命令
running check # 注:显示结果
·生成安装包
python setup.py sdist
#会生成一些文件
#dist(liupack-0.0.1.tar.gz)
·解压 liupack-0.0.1.tar.gz
dist/liupack-0.0.1.tar.gz
·切换到解压后目录并安装
cd liupack-0.0.1
python setup.py install
·共享代码
注册Pypi帐号
上传代码
审核
审核通过后可以直接通过pip install 安装
·打成exe文件
pyinstaller工具 => pygame小游戏,GUI

示例1(出错)

[root@localhost chenpeng]# cat setup.py 		# 注:setup.py放到要打包的文件里面
from setuptools import setup,find_packages

setup(
    name="chenpeng",                    # 注:指定名称
    url="http://www.sanlelearning.com", # 注:指定官网
    version = "0.0.1",                  # 注:指定版本
    packages = find_packages(),
    author = "chenpeng",                # 注:指定作者
    author_email = "1533431376@qq.com",
    install_requires = ['xlrd>=1.1.0'], # 注:指定依赖包
    description = "this is test pack"   # 注:描述信息
)
[root@localhost chenpeng]# python3 setup.py check
running check
[root@localhost chenpeng]# python3 setup.py sdist
running sdist
…………………………………………
Writing chenpeng-0.0.1/setup.cfg
creating dist
Creating tar archive
removing 'chenpeng-0.0.1' (and everything under it)
[root@localhost chenpeng]# ls
abc.txt            dist      grep_test.txt  one.py       setup.py      three.py  zuoye.sh
chenpeng.egg-info  down.txt  ips.txt        __pycache__  test_quto.py  two.py
#注:dist目录  打包好的文件放到dist/下面
[root@localhost chenpeng]# cd dist/
[root@localhost dist]# ls		# 注:打包好的文件
chenpeng-0.0.1.tar.gz		# 注:打包好的文件
[root@localhost dist]# pip3 install chenpeng-0.0.1.tar.gz 
WARNING: Running pip install with root privileges is generally not a good idea. Try `pip3 install --user` instead.
…………………………
Requirement already satisfied: xlrd>=1.1.0 in /usr/local/lib/python3.6/site-packages/xlrd-1.2.0-py3.6.egg (from chenpeng==0.0.1)

示例2

[root@localhost chenpeng]# vim setup.py 
from setuptools import setup

setup(
    name="pythontest01",                # 注:指定名称
    url="http://www.sanlelearning.com", # 注:指定官网
    version = "0.0.1",                  # 注:指定版本
    packages = ["python_test"],
    author = "chenpeng",                # 注:指定作者
    author_email = "1533431376@qq.com",
    install_requires = ['xlrd>=1.1.0'], # 注:指定依赖包
    description = "this is test pack"   # 注:描述信息
)
#注:同级文件下
[root@localhost chenpeng]# cd python_test/
[root@localhost python_test]# ls
__init__.py  one.py  three.py  two.py
[root@localhost chenpeng]# python3 setup.py check
running check
[root@localhost chenpeng]# python3 setup.py sdist
running sdist
running egg_info
………………
[root@localhost chenpeng]# cd dist/
[root@localhost dist]# ls
pythontest01-0.0.1.tar.gz
[root@localhost dist]# pip3 install pythontest01-0.0.1.tar.gz 
………………………………
/usr/local/lib/python3.6/site-packages/xlrd-1.2.0-py3.6.egg (from pythontest01==0.0.1)
[root@localhost dist]# cd /usr/local/lib/python3.6/site-packages
[root@localhost site-packages]# ls
python_test
[root@localhost ~]# python3
>>> from python_test import one

知识点11 软件目录结构规范

定义目录结构目的
·可读性高
不熟悉这个项目的代码的人,一眼就能看懂目录结构,知道程序启动脚本是哪个,测试目录在哪儿,配置文件在哪儿等等。从而非常快速的了解这个项目。
·可维护性、可扩展性好
定义好组织规则后,维护者就能很明确地知道,新增的哪个文件和代码应该放在什么目录之下。这个好处是,随着时间的推移,代码/配置的规模增加,项目结构不会混乱,仍然能够组织良好。

软件目录结构规范
docs => 文档
REMEME.txt
LICENSE
Data

如何用导入模块与包
·用相对导入的方式导入数据

知识点12 小节

小结:注意事项
·对于pyhton模块命名空间作用域, 一定要注意成员变量的范围
·对于__name__属性的使用, 防止代码大量加载运行
·对于模块的导入的几种方式要灵活去运用
·Python模块的打包
·软件目录结构

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mycpen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值