重拾python(基础篇)
Python特性
- 跨平台的程序设计语言
- 解释性语言,不编译
- 交互式语言,可直接执行代码
- 面向对象语言
面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了;
面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。
面向过程:
优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、 Linux/Unix等一般采用面向过程开发,性能是最重要的因素。
缺点:没有面向对象易维护、易复用、易扩展
面向对象:
优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统 更加灵活、更加易于维护
缺点:性能比面向过程低
下载安装
淦哦,py3.9居然在Windows7上面跑不了
python自带文件说明
- IDLE:自带的简单开发环境
- Python:交互式命令行程序
- manuals:官方技术文档
- module docs:已安装的模块文档
要写代码在IDLE里面写就行了
pycharm
一个更好的IDE,去官网下来用就行,感觉社区版的应该够用
具体操作细节属于肌肉记忆,所以不细讲
函数,转义字符等基础
在黑框框里面输出一些东西
- 加上
type(X)
可输出变量X的类型 - 加上
id(X)
可输出变量X的地址
open
向文件里面输出一些东西,可和print一起乱用,返回一个指针
fp=open('location','mode')
print(XX,file=fp)
fp.close
其中的mode有:见链接
input函数
输入函数,可以给提示语,比c方便多了
运算符
顾名思义,详细见链接
转义字符
ASCII,Unicode
就是一张表,把01和字母联系起来
Unicode是在ASCII之后的东西了,可以表示几乎全世界的字符,记得我写博客的时候都需要把那个TXT文件按照UTF-8来表示想必就是这个原因了
标识符和保留字
保留字其实就是一些在py中有特殊含义的字符,不能够乱用,比如显然不能够用def来命名一个变量啥的
标识符就是你自己给变量的名字,严格区分大小写(都是这样的)
变量
变量是啥
放东西的东西…
(我也不知道怎么解释,这太基础了)
不过python里面有个东西很舒服,就是变量不需要定义类型,它接到啥东西就是什么类型,比c爽多了
变量的组成
变量由三个东西组成:
- id:变量的内存地址
- type:变量的类型
- value:变量里面存的东西
变量赋值
用等号就是赋值
可以多次重复赋值(好像是很显然的)
数据类型
int:整数
- 十进制:默认的那种
- 二进制:在十进制前面加上0b来转义
- 八进制:在十进制前面加上0o来转义
- 十六进制:在十进制前面加上0x来转义
float:浮点数
解决浮点数不精确的方法:
引入一个模块如下:
from decimal import Decimal
调用的时候:
print(Decimal('1.1')+Decimal('2.2'))
bool:布尔类型
false=0
true=1
bool可转为int,所以不要管那么多
str:字符串类型
用单双引号的字符串必须在一行
三引号的可以分布在连续的多行
数据类型转换
str(X)
:把X转成字符串类型int(X)
:把X转成整数类型float(X)
:把X转成浮点数类型
但不要乱转,有些是转不了的
注释
用#
单行注释,"""
来搞多行注释
在开头可规定编码声明:
# coding:gbk
(ascii)# coding:utf-8
(Unicode)
程序的组织结构控制
选择结构
if,elif,else
if XXX:
Do something
elif XXXX
Do something
elif XXXX
Do something
else
DO something
条件表达式
if XXX:
Return something A
else
Return something B
等价于
Return something A if XXX else Return something B
其实就和cpp里面问号表达式一样:
(XXX?(Return something A):(Return something B));
感觉cpp里面的装逼要厉害些哈哈哈
pass语句
占位置,用在需要写但还不知道写啥的时候
循环结构
range
生成一个整数序列[start,stop),且每两个数之间差为step
range(start,stop,step)
可以用如下方式来看序列里面有没有某一个数:
r=range(1,10,2)
print(5 in r)
>>>>True
>print(5 not in r)
>>>>false
while
当型语句,当满足while后面的条件后继续循环内的语句
while XXX:
do XXXXX
for in循环(遍历)
字符串和序列(range)是可迭代变量
for循环的语法如下:
遍历字符串
for s in "international":
print(s)
>>>
i
n
t
e
r
n
a
t
i
o
n
a
l
其实就是一个一个字母的拿出来然后赋值给s变量
遍历序列
for s in range(10):
print(s)
>>>
0
1
2
3
4
5
6
7
8
9
其实就是一个一个值拿出来然后赋值给s变量
没有变量的无灵魂遍历
for _ in range(10):
print("hiahiahiahiahiahiahia\n")
>>>
hiahiahiahiahiahiahia
hiahiahiahiahiahiahia
hiahiahiahiahiahiahia
hiahiahiahiahiahiahia
hiahiahiahiahiahiahia
hiahiahiahiahiahiahia
hiahiahiahiahiahiahia
hiahiahiahiahiahiahia
hiahiahiahiahiahiahia
hiahiahiahiahiahiahia
break
就是从循环中强制退出的语句
只要运行到这一句那就退出当前的循环喽
continue
只要运行到这一句就不管后面的代码直接从循环头头开始重新走一遍
else
else不仅仅可以和if一起用,还可以和while,for一起用
只是我感觉好像else和while,for一起用很奇怪,可能是我cpp打多了吧
简单数据结构
列表
其实就是c++里面的数组,里面可以一个个的存东西
(感觉说了一堆废话)
不过python里面的列表可以存不同类型的数据,和c++里面的数组只能够存数字或字符串有很大的区别,py果然优秀一些
并且这个列表不用管空间,有数据就放就行,不会想C++一样因为手残空间开小了导致数据溢出然后暴掉,就很舒服
列表基本定义和操作
liebiao=['hello','world',98]
liebiao2=list(['hello','world',98,'world'])
print(liebiao)
print(liebiao2)
print(liebiao[1])
print(liebiao[-1])
>
['hello', 'world', 98]
['hello', 'world', 98, 'world']
world
98
1
1
列表查询元素索引操作
liebiao2=list(['hello','world',98,'world'])
print(liebiao2.index('world'))
print(liebiao2.index('world',0,2))
>
1
1
列表切片操作
liebiao_name[start:stop:step]
,区间[start,stop),步长为step
liebiao=list(['hello','world',98,'ee','iede','hiahia',520])
print(liebiao[1:6:2])
print(liebiao[6:1:-2])
>
['world', 'ee', 'hiahia']
[520, 'iede', 98]
列表元素存在与否判断
用in
,not in
来判断
列表元素迭代
for var_name in list_name:
即可
列表元素的增加操作
list_name.append(A)
:在列表list_name末尾加一个元素A,很鸡肋的事情就是,如果A是一个列表,那么就会出现列表里面嵌套列表的情况,很活络但是不知道好不好
list_name.extend(A)
:在列表list_name末尾至少添加一个元素A,这个时候如果A是一个列表,就会把两个列表合并,把A怼在list_name后面
list_name.insert(pos,A)
:在列表的位置pos添加一个元素A
好像切片可以随便插入很多元素:
liebiao=list(['hello','world',98,'ee','iede','hiahia',520])
print(liebiao)
liebiao[1:1:1]=['lueluelue','abababa']
print(liebiao)
liebiao[2:4:1]=['250','520']
print(liebiao)
>
['hello', 'world', 98, 'ee', 'iede', 'hiahia', 520]
['hello', 'lueluelue', 'abababa', 'world', 98, 'ee', 'iede', 'hiahia', 520]
['hello', 'lueluelue', '250', '520', 98, 'ee', 'iede', 'hiahia', 520]
列表元素的删除操作
list_name.remove(A)
把第一个A从列表中删掉
list_name.pop(pos)
把位置为pos的元素从列表中删掉,如果pos没有定义,就删除最后一个元素
当然切片也可以大量的删除元素,如果想要把切后的元素直接赋给原列表,可以:
list_name[start,stop,step]=[]
list_name.clear()
清空列表中的所有元素
del list_name
把列表整个删了
列表元素的修改操作
直接赋值可以list_name[X]=A
也可以切片,见上列表元素增加操作
列表的排序操作
太舒服了,直接快排,想起了当年用cpp手写快排的时光…
list_name.sort(reverse=False)
升序排序,默认
list_name.sort(reverse=True)
降序排序
或者可以用内置函数来产生一个列表对象
list_name2=sorted(list_name,reverse=True)
,降序排列,放到list_name2里面
列表生成式
用for循环一句话就可以搞一个列表出来,有点意思
list_name=[i*X for i in range(start,stop,step)]
比如:
list_name=[i*1 for i in range(1,10,1)]
print(list_name)
list_name=[i*4 for i in range(1,10,1)]
print(list_name)
>
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[4, 8, 12, 16, 20, 24, 28, 32, 36]
字典
字典是啥
一个无序的序列,可变,每个元素由键和值构成,叫键值对,感觉这个数据结构过于方便和高级了,咋实现的啊…
哦原来用的是hash函数啊,好高级,字典树?不知道
感觉字典树应该可以实现这个功能,可以试一下诶
那这东西占的空间不是大的飞起来,天哪
字典的创建
dic_name={'haha':22,'heaha':2322,'hahar':222,'harha':232}
dic_name=dict(name='jack',age=20)
字典元素的获取
dic_name={'haha':22,'heaha':2322,'hahar':222,'harha':232}
print(dic_name['haha'])
print(dic_name.get('haha'))
print(dic_name.get('hahaiii',7373))
>
22
22
7373
用字典内置的get函数可以避免找不到对应的键从而导致程序炸掉,这种情况下get函数返回一个None值
如果在get后面放一个数字,那么如果没有插到对应的键,就会把这个数字返回来
字典元素存在与否的判断
dic_name={'haha':22,'heaha':2322,'hahar':222,'harha':232}
print('haha' in dic_name)
print('haha' not in dic_name)
>
True
False
就用in,not in判断就行
字典元素的删除
dic_name={'haha':22,'heaha':2322,'hahar':222,'harha':232}
del dic_name['haha']
print(dic_name)
>
{'heaha': 2322, 'hahar': 222, 'harha': 232}
用del命令即可
字典元素的新增和修改
dic_name={'haha':22,'heaha':2322,'hahar':222,'harha':232}
dic_name['lueluelue']=520250
print(dic_name)
dic_name['lueluelue']=520
print(dic_name)
>
{'haha': 22, 'heaha': 2322, 'hahar': 222, 'harha': 232, 'lueluelue': 520250}
{'haha': 22, 'heaha': 2322, 'hahar': 222, 'harha': 232, 'lueluelue': 520}
获取字典的视图
获取所有的键:用内置函数Keys=dic_name.keys()
获取所有的值:用内置函数Value=dic_name.values()
获取所有的键值对:用内置函数Items=dic_name.items()
,返回的是元组
字典元素的遍历
用for:
dic_name={'haha':22,'heaha':2322,'hahar':222,'harha':232}
for A in dic_name:
print(A)
print(dic_name[A])
字典生成式
内置函数zip:
dic_name={Key_list:Value_list for Key_list,Value_list in zip(Key_list,Value_list)}
Name=['A','B','C','D']
scores=[1,1,0,0,-1]
dic_name={Name:scores for Name,scores in zip(Name,scores)}
print(dic_name)
>
{'A': 1, 'B': 1, 'C': 0, 'D': 0}
如果两个列表内容数量不同,以少的那个为准
元组
元祖是啥
是一个不可变序列,没办法增删改
据说用不可变序列有利于防止把操作对象搞混
当然如果元组里面存一个列表这种可变序列的话,这些可变序列是可以修改的,很有意思
元组的创建方式
三种等价方式
t=('P','h',99)
t='P','h',99
t=tuple(('P','h',99))
如果元祖里面只有一个元素,要这样写:
t=('p',)
元组的遍历
t=('P','o',2,3,4,4,24)
for i in t:
print(i)
就可以实现遍历(好像一般遍历都是用for循环就行吧)
集合
集合是啥
是没value的字典,也是用hash来搞的,这个集合里面没有重复的元素,这可是数学里面的集合的基本性质
集合的创建
两种等价方式
s={1,2,2,3,2}
s=set({1,2,2,3,2})
集合元素判断
in或not in就可以了
集合元素的增加操作
s.add(x)
,x加入集合s
s.update(A)
,s中加入集合或列表或元组A
集合元素的删除操作
s.remove(x)
:删除一个指定元素x,如果没有就报错
s.discard(x)
:删除一个指定元素,如果指定元素不存在不报错
s.pop()
:一次删除任意一个元素(好奇怪的东西)
s.clear()
:清空集合
集合之间的关系
判断两个集合一样或不一样:A==B
,A!=B
判断A是否是B的子集:A.issubset(B)
判断A是否是B的超集:A.issuperset(B)
判断AB是否有交集:A.isdisjoint(B)
,有交集返回false
,否则返回true
集合的数学操作
s1.intersection(s2)
,s1 & s2
都是求交集
s1.union(s2)
,s1 | s2
都是求并集
s1.difference(s2)
,s1 - s2
都是求差集
s1.symmetric_difference(s2)
,s1 ^ s2
都是求对称差集
集合生成式
把列表生成式中的方括号变成花括号就行
s={i for i in range(1,10,2)}
字符串
不可变的字符序列
字符串的声明
单双三引号都可以的
字符串的驻留机制
对于多个实际内容相同的一个字符串,python不会多次占空间,只在内存里面搞一份,这就叫驻留,很省空间
但是驻留也有条件
- 字符串长度为0,1时
- 只有字母数字下划线的字符串
- 一开始就一样的字符串(后面加成一样的不算)
- [-5,256]之间的数字
可以强制驻留,引入:import sys
即可
pycharm优化了这种情况,可以不用引入sys就可以驻留
字符串的常用操作
字符串的查询
s.index('substr')
:查找子串substr第一次出现的位置,如果子串不存在,就报错
s.rindex('substr')
:查找子串substr最后一次出现的位置,如果子串不存在,就报错
s.find('substr')
:查找子串substr第一次出现的位置,如果子串不存在,就返回-1
s.rfind('substr')
:查找子串substr最后一次出现的位置,如果子串不存在,就返回-1
字符串的大小写转换操作
s.upper()
:把字符串中所有字母转化成大写字母
s.lower()
:把字符串中所有字母转化成小写字母
s.swapcase()
:把字符串中所有小写字母转化成大写字母,所有大写字母转化成小写字母
s.capitalize()
:把第一个字母转换为大写,其余的字符转化为小写
s.title()
:把字符串中每个单词的第一个字母转换为大写,其余的字符转化为小写
字符串的内容对齐方法
s.center()
:居中对齐,第一个参数指定宽度,第二个参数指定填充符,可选,默认空格。如果设置宽度小于实际宽度就返回原字符串
s.ljist()
:左对齐,第一个参数指定宽度,第二个参数指定填充符,可选,默认空格。如果设置宽度小于实际宽度就返回原字符串
s.rjist()
:右对齐,第一个参数指定宽度,第二个参数指定填充符,可选,默认空格。如果设置宽度小于实际宽度就返回原字符串
s.zfill()
:右对齐,左边用0填充,只收一个参数指定字符串的宽度。默认空格。如果设置宽度小于实际宽度就返回原字符串
字符串的劈分操作
s.spilt(sep='X',maxspilt=A)
:从左开始劈,默认以空格为标志劈,返回一个列表。可用参数sep来定劈分符,用maxspilt来定最大劈分次数
s.rspilt(sep='X',maxspilt=A)
:从右开始劈,默认以空格为标志劈,返回一个列表。可用参数sep来定劈分符,用maxspilt来定最大劈分次数
字符串的判断操作
s.isidentifier()
:判断s是不是合法的字符串
s.isspace()
:判断s是否全部是空白字符组成
s.isalpha()
:判断s是否全部由字母组成
s.isdecimal()
:判断字符串是否全部由十进制数字组成
s.isnumberic()
:判断s是否全部由数字组成
s.isalnum()
:判断s是否全部由字母和数字组成
字符串的替换和合并
s.replace('A','B',X)
:字符串的替换,用B换A,换X次
s.join()
:将列表或元组中的字符串合并为新的一个字符串,感觉这个函数很奇怪…
字符串的比较操作
>,>=,<,<=,==,!=
都可以用来相应的比,比的时候从前往后一个一个的比,比的实际上就是ascll码或者什么码,就酱
字符串的切片操作
切片涂奶酪,真香
就和列表切片一个格式:
s='hello Java'
s1=s[:5:1]
s2=s[6::1]
s3='!'
print(s1+s3+s2)
>
hello!Java
格式化字符串
用%,{},{var}
来做占位符都ok
name='popoi'
age=1231
print('my name is %s,%d years old' % (name,age))
print('my name is {0},{1} years old'.format(name,age))
print(f'my name is {name},{age} years old')
>
my name is popoi,1231 years old
my name is popoi,1231 years old
my name is popoi,1231 years old
%Xd
:X是数字前面的宽度%.Xlf
:X是保留小数的位数
这些细节比较杂,可以去网上找一些详细的资料,看着用就应该没问题了
字符串的编码转换
可以用encode
和decode
来编码和解码,也就是把字符串搞成GBK或者UTF-8用s.encode(encoding='GBK')
或者s.encode(encoding='UTF-8')
,把GBK或者UTF-8搞成字符串用s.decode(encoding='GBK')
或者s.decode(encoding='UTF-8')
函数
函数是啥
太基础,没法解释
函数的创建
def Name(canshuA,canshuB...):
do something
return X
其中参数canshuA,canshuB
(这个是形参)等等都是可以在def语句那里赋一个初值的,避免没有值的时候出现bug
函数的返回值
如果返回多个值,结果就是元组类型
函数参数
可变数目的参数
这个挺好用的诶
如果只是单个元素(个数可变的位置参数)的话可以这样:
def fun(*args):
return args
这个时候如果往fun函数里面输入多个值,args就会以一个元组的形式返回
如果有多个元素可以搞成字典的形式(个数可变的关键字参数):
def fun(**args):
return args
print(fun(a=10,b=34,c=429))
>
{'a': 10, 'b': 34, 'c': 429}
可变的未知参数只能够有一个哦,写多个要遭起
python的异常处理机制
debug这个东西…噩梦啊
除了一般的贱贱的手法比如加调试信息,加断点之外,还有这些新东西可以试试
try..except..else结构
try:
do A
except BaseException as e:
do B
else:
do C
finally:
do D
其中A部分就是可能出现bug的代码,B部分就是出现bug后要干的事情,BaseException那里可以写可能出现的错误,如果不知道会出现什么错误就写BaseException来网罗所有错误,e就是给这个错误取的名字,起到简略代码量的作用,C部分就是没出锅要干的事情,D就是无论如何都要在最后干的事情(这个好像没什么必要吧突然感觉)
有意思
类
类的创建
class Class_name:
pass
类的组成
class Student:
Place='China'#写在类里面的变量,即类属性
def __init__(self,name,age): #初始化方法,这里的self就指这个类
self.name=name
self.age=age
# 似乎这个init方法就可以规定student类里面有哪些属性了,所以类属性有什么用呢
def eat(self):#实例方法(函数在类里面叫做方法)
print('eating\n')
@staticmethod #修饰语句
def M():#静态方法
print('M')
@classmethod #修饰语句
def N(cls): #类方法
print('N')
只是我不是很懂,上面的三种方法有什么区别?
类的对象的创建和方法的使用
class Student:
Place = 'China' # 写在类里面的变量,即类属性
def __init__(self, name, age): # 初始化方法,这里的self就指这个类
self.name = name
self.age = age
def eat(self): # 实例方法(函数在类里面叫做方法)
print('eating\n')
@staticmethod # 修饰语句
def M(): # 静态方法
print('M')
@classmethod # 修饰语句
def N(cls): # 类方法
print('N')
# 上面是定义类
studentA = Student('A', 111) # 这里是创建对象
#下面是调用方法
studentA.eat()
studentA.M()
studentA.N()
>
eating
M
N
类方法和属性的动态修改
类属性可以在运行的时候改,改了后所有的对象跟着改
而如果想给某一个对象搞一些特殊的,类里面没有定义的方法和属性的话,也是可以的,但这个就只对这个对象起作用了:
class student:
def __init__(self,age,name):
self.AGE=age
self.NAME=name
def run(self):
print('RunRunRun')
def eat():
print('yummy')
A=student(1,'A')
B=student(2,'B')
print(A.NAME,A.AGE,B.NAME,B.AGE)
A.gender='Male'
B.EAT=eat
print(A.gender)
B.EAT()
>
A 1 B 2
Male
yummy
类的浅拷贝和深拷贝
浅拷贝类,就只拷贝类本身的指针,至于类里面的父类,属性等等都不拷贝
深拷贝就要把所有的东西都拷贝一遍
面向对象的三大特征和一些其他相关
封装
封装就是,把代码包装到类对象中,在方法内部对属性进行操作,在类的外面调用方法,不用考虑类里面是怎么实现的,这就可以很舒服的隔离复杂度
在属性前面加上两个_
就可以避免属性在类外部被直接访问,可以通过dir
命令获得所有的属性名从而用可共用的属性名来间接访问
class student:
def __init__(self,age,name):
self.AGE=age
self.__NAME=name
def run(self):
print('RunRunRun')
stu=student(3,'E')
print(dir(stu))
print(_student__NAME)
>
['AGE', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_student__NAME', 'run']
E
继承
用Son_Class
类继承Father_ClassA,Father_ClassB...
这些类:
class Son_Class(Father_ClassA,Father_ClassB...):
pass
如果没有指定,就继承object
,这个是所有的类的父类
定义子类的时候,必须在其构造函数中调用父类的构造函数.这一点其实很好理解,毕竟如果父类都还没有构造,子类构造个鬼鬼啊
比如下面,我们写两个类,HumanBeings
和Student
,Student
是HumanBeings
的子类
class HumanBeings(object):
def __init__(self,age,name,gender):
self.age=age
self.name=name
self.gender=gender
def outputinformation(self):
print(self.name,self.gender,self.age)
class Student(HumanBeings):#单继承
def __init__(self,name,age,gender,classnumber,grade):
super().__init__(age,name,gender)
self.classnumber=classnumber
self.grade=grade
def outputinformation(self):
print(self.name,self.gender,self.age,self.classnumber,self.grade)
StudentA=Student('A',12,'Female',1,3123)
StudentA.outputinformation()
>
A Female 12 1 3123
方法重写
如果父类里面有一个函数,那么子类里面也是可以调用的,但是执行的代码显然是父类里面的代码
因此如果子类的同一个函数要执行不同的操作,那就需要在子类里面重新写一遍,就像上面的outputinformation
函数一样
(误打误撞就写了个方法重写)
object类
这个是所有类的爸爸
因此它里面的函数大家都可以用,当然也可以重写啦
多态
python里面多态这个东西就很灵活
也就是说对于一个函数,无论它传进来的参数是什么类型,只要这个函数调用的是该类型里面有的属性和方法,那这个函数就可以跑得动
很骚的一个操作,毕竟是一个动态语言
class A:
def DD(self):
print('hiahia')
class B:
def DD(self):
print('hiahia')
def HiaHia(obbdd):
obbdd.DD()
AA=A()
BB=B()
HiaHia(AA)
HiaHia(BB)
>
hiahia
hiahia
一些特殊方法和属性
- 属性:
__dic
:获得类对象或者实例对象相关的所有方法和属性
- 方法:
__len()__
:获得列表的长度的方法
__add()__
:加法的内置方法
__new()__
:创建对象的内置方法
__init()__
:对创建的对象进行初始化的方法
上面这些方法其实也是可以重写的,也就是按照这个方法本来的参数格式来将它重写一遍,可以达到像用加号直接连接两个字符串的这种新的好玩的操作
关于new和init方法有一些需要注意的东西,只要用一个类新建了一个对象,那么就会调用object类 (祖宗类) 里面的new和init方法,先用new搞一个对象出来,然后返回给init函数,在init函数里面赋值最后返回给新建的那个对象.因此如果重写这两个方法的话应该就会改变这个过程(只要敢乱写)
更细节的东西可以咨询因特网先生
模块
模块是啥
模块就是一个.py
文件,里面有函数,类,类方法属性,语句啥的
这就很舒服,因为似乎可以引用的样子,从而便于拆分任务
一个py程序就由多个模块和包(包马上就讲到了)构成喽
模块操作
- 新建模块:直接新建
.py
文件就行 - 导入模块:
import Module
或者from Module import f
(第二个是指从Module中导入f函数) - 使用模块中的函数方法相关:
Module.f()
:可以调用Module里面的f函数dir(Module)
:返回Module里面的东西
如果要导入自定义模块(就是自己写的模块)的话,有几种比较好的方法,我最喜欢的一种就是用sys引入地址:
假如有一个ccaa.py
在G:\Learning Python\code
里面,然后我要在某一个py模块里引入ccaa这个模块,就可以这样写:
# ccaa.py
def add(a,b):
return a+b
def sub(a,b):
return a-b
class Human(object):
def __init__(self,age,gender,name):
self.age=age
self.gender=gender
self.name=name
def outputinformation(self):
print('Name:'+self.name+' age:'+str(self.age)+' gender:'+self.gender)
# 任意一个文件
import sys
sys.path.append(r"G:\Learning Python\code")
import ccaa
print(ccaa.add(111,222))
print(ccaa.sub(111,222))
B=ccaa.Human(19,'Female',"B")
B.outputinformation()
>
333
-111
Name:B age:19 gender:Female
模块主程序的指定
在代码前这样写:
if __name__ == '__main__':
do something
则可以让这个do something只在本模块被当做主程序运行的时候才执行,而被当做模块导入的时候就不行
python中常见的内置模块
sys,time,os,calendar,urllib,json,re,math,decimal,logging...
详情请上网详细搜索
第三方模块的安装和使用
pip install Module_Name
:安装(在dos里面输入)
import Module_Name
:使用
包
包是啥
是一个分层次的目录结构,把一堆模块组织在一起
包和目录的差别就是,包里面会有一个__init__.py
文件,目录里面没有
如何导入包
import方法
如果用这个方法,就只能够直接导入包名不能够单独导入包里面的模块:import p
from import方法
如果这样就可以导入方法里面的模块了,还可以用一个名称代指:
from pageage1 import module_A as A
文件读写
打开/创建文件:file=open(Filename [,mode,encoding])
其中,Filename指要打开或创建的文件名称,mode是打开模式,模式有r,w,a,b,+
等等,具体上网一查就知道了.encoding是指编码方式,默认gbk.
文件指针就放在file变量里面了,这个指针有一些可用的函数,可利用其进行文件读写操作:
file.read(size)
:读取file中size个字节或字符的文件,若没有写size就直接读取到文件末尾file.readline()
:从文本中读取一行内容file.readlines()
:从文本中一行一行读取,形成一个列表然后返回file.write(X)
:把X字符串写入文件file.writelines(X)
:把X字符串列表写入文件,不加换行符file.close()
:关闭文件,释放资源file.seek(offeset[,whence])
,file.tell()
,file.flush()
等,咨询Internet即可
with语句(上下文管理器)
可以用with语句来避免忘记关掉文件而导致的资源浪费
with open('filename','mode') as Name:
do something
离开with语句后就可以直接关掉filename文件了
其原理是无论是否报错,只要退出了with语句,就会执行特殊方法__exit()__
来释放资源
最后的测验
一个练习题:学生管理系统
需求
代码
本来想写三个模块的(查询修改总览),但是由于能力有限,不知道怎么样合理调用变量,所以就把修改和总览模块放在一起了
手模了几组数据程序跑得过,因此至于bug嘛..不要管啦,懒得debug了
informationBase.py
# Andrew82106
# time: 2021/7/16 11:33
class Human(object):
def __init__(self,name,age,gender,height):
self.age=age
self.name=name
self.gender=gender
self.height=height
class Student(Human):
def __init__(self,name,age,gender,height,numofsubject,subject,grade,Class):
super().__init__(name,age,gender,height)
self.subject=subject#dirctory
self.grade=grade
self.Class=Class
self.numofsubject=numofsubject
StudentQuery.py
# Andrew82106
# time: 2021/7/17 16:58
import sys
sys.path.append(r"G:\Learning Python\StudentGradeSystem")
#import informationBase as Info
#import StudentModify as Modi
class Sort_:
@staticmethod
def Mysort(Dic,Reverse):
Result= {}
for i in Dic:
a=Dic[i]
if a in Result:
Result[a]+=','
Result[a]+=i
else:
Result[a]=i
X=sorted(Result,reverse=Reverse)
Result2={}
length=len(X)
for i in range(0,length,1):
Result2[Result[X[i]]]=X[i]
return Result2
@staticmethod
def SubjectRank(Information_,subjects):
Dic={}
length=len(Information_)
for i in range(0,length,1):
#length2=len(Information_[i].subject)
for j in Information_[i].subject:
if j == subjects:
Dic[Information_[i].name]=Information_[i].subject[j]
#Name=sorted(Dic.values())
Name = Sort_.Mysort(Dic,True)
length2=len(Name)
if length2<=0:
print('没有学这个科目的学生,请检查是否输入错误')
return
cnt=0
print(">>>>>>>>>>>>{0}学科的各个学生排名".format(subjects))
for i in Name:
print("排名{0}:{1} {2}分".format(cnt+1,i,Name[i]))
cnt+=1
return
@staticmethod
def PersonalRank(name,information__):
length=len(information__)
for i in range(0,length,1):
if information__[i].name==name:
Student=information__[i]
Name=Sort_.Mysort(Student.subject,True)
cnt=0
print(">>>>>>>>>>>>{0}的各学科排名:".format(name))
for j in Name:
print("排名{0}:{1} {2}分".format(cnt+1,j,Name[j]))
cnt+=1
def SumScore(Name,information__):
length=len(information__)
for i in range(0,length,1):
if(information__[i].name==Name):
Student=information__[i]
sum=0
#length=len(Student.subject)
for i in Student.subject:
sum+=Student.subject[i]
print("姓名:{0} 总分:{1}".format(Student.name,sum))
return
print("没有找到这个学生,请确认输入正确性:")
return
if __name__ == '__main__':
#numofstudent=Modi.login_information()
#Modi.output_information(numofstudent)
#SumScore('Bily')
#Sort_.PersonalRank('Bily')
pass
Student_Information_Arrangement_System.py
# Andrew82106
# time: 2021/7/18 14:23
import sys
sys.path.append(r"G:\Learning Python\StudentGradeSystem")
import informationBase as Info
import StudentQuery as Quer
global information_
global numofstudent
class Modi:
@staticmethod
def cutback(Stringss): # 利用切片把末尾的回车去掉的函数
length = len(Stringss)
return Stringss[0: length - 1:1]
@staticmethod
def login_information(): # 读取文件模块
global numofstudent
global information_
information_=[]
file = open("student.txt", mode='r', encoding='utf-8')
info = 0
numofstudent = int(file.readline())
if numofstudent == 0:
return 0
while (1): # {SubName1:score1,SubName2:score2......}
name_ = Modi.cutback(file.readline())
age_ = int(file.readline())
gender_ = Modi.cutback(file.readline())
height_ = int(file.readline())
grade_ = int(file.readline())
Class = int(file.readline())
numofsub = int(file.readline())
Sub = {}
for i in range(0, numofsub, 1):
Sub_name = Modi.cutback(file.readline())
# Sub_name = file.readline()
Sub[Sub_name] = int(file.readline())
# print(">>>>{0}".format(info))
information_.append(Info.Student(name_, age_, gender_, height_, numofsub, Sub, grade_, Class))
info += 1
# print('info{0}'.format(info))
if info >= numofstudent:
return numofstudent
@staticmethod
def output_Student(Student): # 输出某个学生的信息模块
print(">>>>>>\n姓名:{0} 性别:{1} 年龄:{2} 身高(cm):{3} {4}年级{5}班".format(Student.name, Student.gender, Student.age,
Student.height, Student.grade, Student.Class))
lenth = len(Student.subject)
print("在学学科数目:{0}".format(lenth))
for j in Student.subject:
print("学科名:{0} 分数:{1}".format(j, Student.subject[j]))
@staticmethod
def output_information(numofstudent): # 输出所有文件信息模块
global information_
if numofstudent == 0:
print("还没有任何信息")
return
for i in range(0, numofstudent, 1):
Modi.output_Student(information_[i])
@staticmethod
def output_information_TOFiles(numofstudent): # 输出所有文件信息模块
print('正在将文件保存到静态文档中')
file = open("student.txt", mode='w', encoding='utf-8')
file.write(str(numofstudent) + '\n')
for i in range(0, numofstudent, 1):
file.write("{0}\n{1}\n{2}\n{3}\n{4}\n{5}\n{6}\n".format(information_[i].name, information_[i].age,
information_[i].gender,
information_[i].height, information_[i].grade,
information_[i].Class,
information_[i].numofsubject))
for j in information_[i].subject:
file.write("{0}\n{1}\n".format(j, information_[i].subject[j]))
print('存储完毕')
@staticmethod
def generate_Student():
name = input('输入学生名字:')
age = int(input('输入学生年龄:'))
while (1):
gender = input('输入学生性别(M=Male,F=Female):')
if gender == 'M':
gender = 'Male'
break
elif gender == 'F':
gender = 'Female'
break
else:
print('请不要输入无关字符')
height = int(input('输入学生身高(cm):'))
grade = int(input('输入学生年级:'))
Class = int(input('输入学生班级:'))
numofsub = int(input('请问该学生有多少正在学的科目:'))
sub = {}
for i in range(0, numofsub, 1):
nameofs = input('第{0}个在学学科名:'.format(i + 1))
sub[nameofs] = int(input('这个学科本次考试的分数:'))
return Info.Student(name, age, gender, height, numofsub, sub, grade, Class)
@staticmethod
def addStudent():
global numofstudent
Stu = Modi.generate_Student()
information_.append(Stu)
numofstudent=len(information_)
@staticmethod
def DeleteStu():
global numofstudent
name = input('输入要删除的学生的名字')
for i in range(0, numofstudent, 1):
if information_[i].name == name:
print('该学生信息如下:')
Modi.output_Student(information_[i])
while 1:
ensure = input('确定要删除吗?Yes为确定,No为取消:')
if ensure == 'Yes':
information_.pop(i)
print('成功删除')
numofstudent = len(information_)
return
elif ensure == 'No':
print('成功取消删除操作')
numofstudent = len(information_)#
return
else:
print("请不要输入无关内容:")
print('找不到该学生,请检查是否有输入错误')
numofstudent = len(information_)
return 0
@staticmethod
def updateStudent():
while 1:
name = input('请输入要修改信息的学生的名字:')
Have = False
for i in range(0, numofstudent, 1):
if information_[i].name == name:
print('该学生信息如下:')
Have = True
Modi.output_Student(information_[i])
while 1:
choose = input('请问要修改什么?输入相应字符进行修改(Name,Age,Gender,Height,Subject,Grade,Class),输入exit退出修改:')
if choose == 'Name':
information_[i].name = input('请输入修改后的名字:')
print('修改成功')
elif choose == 'Age':
information_[i].age = input('请输入修改后的年龄:')
print('修改成功')
elif choose == 'Gender':
information_[i].gender = input('请输入修改后的性别:')
print('修改成功')
elif choose == 'Height':
information_[i].height = input('请输入修改后的身高(cm):')
print('修改成功')
elif choose == 'Subject':
while 1:
choose2 = input("请问是否新增科目,输入Yes或No,退出输出Exit:")
if choose2 == 'Yes':
NumofNew = int(input('新增几个科目:'))
for j in range(0, NumofNew, 1):
Name = input('输入新增的第{0}个科目的名字:'.format(j + 1))
# if information_[i].subject.has_key(Name):
if Name in information_[i].subject:
print("已经有这个科目了")
else:
information_[i].subject[Name] = input("输入{0}的分数:".format(Name))
elif choose2 == 'No':
while 1:
choose3 = input("输入欲修改科目的名称:")
D = []
Have_ = False
for k in information_[i].subject:
if k == choose3:
Have_ = True
while 1:
choose4 = input('删除此科目输入 Del ,修改此科目分数输入 Modi,退出输入exit:')
if choose4 == 'Del':
D.append(k)
break
elif choose4 == 'Modi':
information_[i].subject[k] = input('修改后的分数:')
break
elif choose4 == 'exit':
break
else:
print('请不要输入无关字符')
if Have_ == False:
print('未查询到相关科目,请注意拼写和大小写是否正确')
else:
for kk in range(0, len(D), 1):
del information_[i].subject[D[kk]] # 字典元素不能够再遍历字典的时候删除,所以在里面做个标记之后再删除
print("待删除元素处理完成")
D.clear()
break
elif choose2 == 'Exit':
break
else:
print("请不要输入无关内容")
elif choose == 'Grade':
information_[i].grade = input('请输入修改后的年级:')
print('修改成功')
elif choose == 'Class':
information_[i].Class = input('请输入修改后的班级:')
print('修改成功')
elif choose == 'exit':
print("退出")
break
else:
print("不要输入无关内容")
if Have == False:
print("未找到学生信息,请重新输入:")
elif Have == True:
print("成功更新")
return
@staticmethod
def getStudent(Name):
length = len(information_)
for i in range(0, length, 1):
if (information_[i].name == Name):
return information_[i]
# print("未找到相关学生信息")
return False
def checkFiles():
try:
f = open("student.txt")
f.close()
print("成功读取到静态文件,正在启动系统")
except BaseException:
print("想必这应该是第一次使用本系统,创建静态文件存档中...")
f = open("student.txt",mode="x",encoding='UTF-8')
f.write('0')
f.close()
def OutputMenu():
print("_________________学生成绩管理系统(1.0.0)_________________")
print("_________________ Menu _________________")
print("___________ 1.新建学生存档信息 ___________")
print("___________ 2.修改学生存档信息 ___________")
print("___________ 3.删除学生存档信息 ___________")
print("___________ 4.查询单科相关学生总排名 ___________")
print("___________ 5.查询某学生所有信息 ___________")
print("___________ 6.查询各学生所有信息 ___________")
print("___________ 7.查询某学生所学科目排名 ___________")
print("___________ 输入其他任意字符来退出系统 ___________")
def OutputChoose(INPUT):
length=len(INPUT)
Choose = input("请输入欲进行的操作前面的数字编号:")
while 1:
for i in range(0,length,1):
if(str(Choose)==str(INPUT[i])):
return INPUT[i]
Choose=input("请不要输入一些无关的字符:")
checkFiles()
Modi.login_information()
while 1:
OutputMenu()
Choose=int(input("请输入欲进行的操作前面的数字编号:"))
if Choose == 1:
Modi.addStudent()
elif Choose == 2:
Modi.updateStudent()
elif Choose == 3:
Modi.DeleteStu()
elif Choose == 4:
subject = input("请输入要查询的科目:")
Quer.Sort_.SubjectRank(information_, subject)
elif Choose == 5:
while 1:
name = input("请输入要查询的学生姓名:")
Check = Modi.getStudent(name)
if type(Check) != bool:
Modi.output_Student(Check)
break
else:
print("未查询到相关学生信息")
elif Choose == 6:
Modi.output_information(numofstudent)
elif Choose == 7:
while 1:
name = input("请输入要查询的学生姓名:")
Check = Modi.getStudent(name)
if type(Check) != bool:
Quer.Sort_.PersonalRank(Check.name,information_)
break
else:
print("未查询到相关学生信息")
else:
print("谢谢使用")
Modi.output_information_TOFiles(numofstudent)
break
感觉这样一打还是暴露出很多问题
变量和函数的名字取得太长,程序鲁棒性不行,函数实现上比较冗长
按理来讲一百多行应该足够了但我这个….
这么丑的代码就不往GitHub上面传了吧
还有,在打包生成exe文件的时候一定记得,要把杀毒软件暂时关掉,不然造不出来exe文件的