python常识
\1. 注释的作用 #单行前后都可以 快捷键ctrl+/ 多行注释‘‘’ ‘’‘
\2. 变量:把数据在内存存储后定义一个名称,数据所在的内存地址的名称
\3. .定义变量=值,标识符统一规范
标识符命名规则
· 由数字、字母、下划线组成
· 不能数字开头
· 不能使用内置关键字(python内部定义单词)不用背
· 严格区分大小写
命名习惯:见名知意,一个名词多个单词用下划线连接,定义变量字符用引号
Python不能随便缩进,解释器依次运行
Debug工具使用看程序细节,打断点行号右边红点,运行debug,debug面板单击下滑键(运行下一行)
Console界面显示每行运行结果
认识数据类型
检测数据类型
type()函数,str字符串要带引号,【】是列表list,()是元组tuple,{}是集合set,f={'name':'tom','age':18 }键值对是字典
格式化输出
%s字符串(都能输出),%d有符号的十进制整数,%f浮点数
%u无符号十进制整数,%X十六进制整数(大小写),%E科学计数法
print(**"****今年我的年龄是****%d****岁****"**%age) print(**'****我的名字是****%s'**%name) print(**"****我的体重是****%.2f****斤****"**%weight) print(**"****我的学号是****%03d"**%stu_id) print(**"****我的名字是****%s****,今年****%d****岁了****"**%(name,age))
语法格式化字符串f:print(f"**我的名字是{name},今年{age}岁了"**)
转义字符\n换行,\t制表符(一个tab键4个空格的距离)(结束符默认换行\n)
print(**'hello'**,end=**'**\t**'**)
转换数据类型
运算符
-
运算符:算数(//整除,**指数),赋值(多变量赋值),复合赋值,比较,逻辑
-
混合运算优先级顺序:()高于 ** 高于 * / // % 高于 + -
-
多变量赋值num1,float1,str1=10,0.5,'hello'
-
多变量赋相同值a=b=100
-
复合赋值运算符先算右边的表达式
条件和循环语句
-
条件语句,input默认是字符串要比较数字要转化为int型
-
某条条件成立后,其他代码不会执行
-
多重判断if elif else,多个条件同时成立()and()
If (条件为真True则执行):
If嵌套语句
导入模块随机数
import random computer=random.randint(0,2)
三目运算符,条件成立执行的表达式 if 条件 else 条件 不成立执行的表达式
-
循环while 条件: ,有计数器一定要有计算
-
Break和continue,continue退出当前循环执行下次循环,后面的语句不会执行了
-
循环嵌套计数器要记得清零,使输出在同一行print(‘*’,end=’’)默认换行print()
for循环,for 变量 in 序列:
While和else使用,else循环结束之后要结束的代码,continue后会执行else部分代码
注意“i”的位置,不要放到continue的下面,会造成死循环
对于 range() 函数,有几个注意点:(1)它表示的是左闭右开区间;(2)它接收的参数必须是整数,可以是负数,但不能是浮点数等其它类型;(3)它是不可变的序列类型,可以进行判断元素、查找元素、切片等操作,但不能修改元素;(4)它是可迭代对象,却不是迭代器。
字符串
字符串三引号换行支持换行,单引号句子里如果有单引号会混淆,加\转义符号
字符串切片
str【1】编号从0开始,序列【开始位置:结束位置:步长】不包含结束位置下标数据,如果不写开始位置默认从0开始,如果不写开始结束就是所有,步长正负数都可
步长为负数表示倒着数,正向从0开始负向从1开始
(如果选取方向如果和步长方向冲突则无法选取数据)
字符串.split(分割字符,分割次数num),分割返回一个列表,返回值会丢失分割字符
查找操作
字符串find(子串,开始下标,结束下标)返回下标(没找到返回-1)
index()查找子串是否在(没找到会报错),
count()
rfind和rindex从右侧开始查找
插入元素
在指定位置插入元素:字符串.replace(旧子串,新子串,替换次数),(原有字符串没有修改不可变数据类型,替换次数超出子串次数表示替换所有)
list.insert(1, last_one)
字符串倒序
str[::-1]
拼接字符串
.join(字符串)
大小写转化
第一个capitalize()
转化每个单词title()
Lower()转小写
upper()全部转大写
删除字符串空白字符
Lstrip()删除字符串左侧空白字符
strip()删除两侧
字符串对齐
字符串.ljust(长度,填充字符)
center()
rjust()
判断是否以指定子串开头,判断字符串
字符串.startswich(子串,开始下标,结束下标),字符串.endswich()
Isdigit()判断是否全数字
isapha()判断是否全字母
isalnum判断数字或字母
isspace()判断是否空白
列表
-
查找通过下标,列表.index(数据,开始下标,结束下标)
-
count()
-
Len()列表长度
-
判断列表数据是否存在 in ,not in print('tom'in name_list)
-
增加数据:列表序列.append(数据),列表可改数据
如果append是追加的数据是一个序列,则追加到整个序列到列表
-
Extend()在列表结尾追加数据
-
如果是序列则逐一加入到列表列表序列.insert(位置下标, 数据)
-
删除列表del ⽬标,也可以删除指定位置数据
-
pop():删除指定下标的数据(默认为最后⼀个),并返回该数据。
-
remove():移除列表中某个数据的第⼀个匹配项。
-
clear():清空列表
-
修改指定下标数据,逆置:列表.reverse()
-
列表序列.sort( key=None, reverse=False),
注意:reverse表示排序规则,reverse = True 降序, reverse = False 升序(默认)
-
列表复制:name_li2 = name_list.copy()
-
列表取值:1.按下标取值 2.按切片取值 3.循环遍历判断
-
列表的拼接 list3 = list1 + list2
-
列表去重 list4 = set(list3) list5 = list(list4)
-
列表的循环遍历优先for循环
-
列表嵌套
元组
元组:如果定义的元组只有⼀个数据,那么这个数据后⾯也好添加逗号,否则数据类型为唯⼀的 这个数据的数据类型
元组的常⻅操作:index(),count(),len()
注意:元组内的直接数据如果修改则⽴即报错
但是如果元组⾥⾯有列表,修改列表⾥⾯的数据则是⽀持的,故⾃觉很重要。
获取最后一个(第n个)元素:last_one = list[-1]
tuple(namelist)即可直接完成元组对列表的强制转换
列表倒数,将int值转换成字符串类型的值,然后使用切片倒序i = i[::-1]
字典
字典⾥⾯的数据是以键值对(用冒号表示)形式出现,字典数据和数据顺序没有关系,即字典不⽀持下标, 后期⽆论数据如何变化,只需要按照对应的键的名字查找数据即可。符号为⼤括号 ,各个键值对之间⽤逗号隔开
(字典为可变类型。)
字典常见操作:
-
增加数据写法:字典序列[key] = 值
注意:如果key存在则修改这个key对应的值;如果key不存在则新增此键值对
-
del() / del:删除字典或删除字典中指定键值对,
-
dict.clear():清空字典
-
查找操作:字典序列.get(key, 默认值)
注意:如果当前查找的key不存在则返回第⼆个参数(默认值),如果省略第⼆个参数,则返回 None。
-
取关键字dict1.keys(),
-
取关键字对应的值dict1.values(),
-
取键值对dict1.items()
for key,value in kwargs.items():
print("key=",key,"value=",value)
集合
创建集合使⽤ {} 或 set() , 但是如果要创建空集合只能使⽤ set() ,因为 {} ⽤来创建空字典特点:
-
\1. 集合可以去掉重复数据;
-
\2. 集合数据是⽆序的,故不⽀持下标
-
3.集合是可变类型
集合常⻅操作⽅法:
-
增加数据 add()
-
update(), 追加的数据是序列。s1.update([50,60])
-
删除数据 remove(),删除集合中的指定数据,如果数据不存在则报错。
-
discard(),删除集合中的指定数据,如果数据不存在也不会报错。
-
pop(),随机删除集合中的某个数据,并返回这个数据。
-
查找数据 in:判断数据在集合序列 not in:判断数据不在集合序列
公共操作和方法
-
+ 合并 字符串、列表、元组
-
* 复制 字符串、列表、元组 (复制多少遍)
-
in 元素是否存在 字符串、列表、元组、字典
-
not in 元素是否不存在 字符串、列表、元组、字典
-
len() 计算容器中元素个数
-
del 或 del() 删除
-
max() 返回容器中元素最⼤值
-
min() 返回容器中元素最⼩值
-
range(start, end, step) ⽣成从start到end的数字,步⻓为 step,供for循环使⽤
-
enumerate(可遍历对象, start=0) 枚举
注意:start参数⽤来设置遍历数据的下标的起始值,默认为0。
⽤于将⼀个可遍历的数据对象(如列表、元组或字符串)组合为⼀个索引序列,同时列出数据和数据下标,⼀般⽤在 for 循环当中。
for index,char in enumerate(list1,start=1): print(f'下标为{index},对应字符为{char}')
-
列表推导式⼜叫列表⽣成式。
作⽤:⽤⼀个表达式创建⼀个有规律的列表或控制⼀个有规律列表。
list1=[i for i in range(10)]
双重循环:list3=[i+j for i in list1 for j in list2]
函数
搭建整体框架,需求分析
函数的⽂档说明
def sum_num(a, b): """ 求和函数 """ return a + b help(sum_num)
函数嵌套
如果函数A中,调⽤了另外⼀个函数B,那么先把函数B中的任务都执⾏完毕之后才会回到上次函数A执⾏的位置。
-
定义函数时同时定义了接收⽤户数据的参数a和b,a和b是形参
-
调⽤函数时传⼊了真实的数据10 和 20,真实数据为实参
-
局部变量的作⽤:在函数体内部,临时保存数据,即当函数调⽤完成后,则销毁局部变量。
-
全局变量 所谓全局变量,指的是在函数体内、外都能⽣效的变量
在函数体内部修改全局变量global 关键字声明a是全局变量
-
return可以退出当前函数,导致return下⽅的代码不执⾏。
return a, b 写法,返回多个数据的时候,默认是元组类型。
return后⾯可以连接列表、元组或字典,以返回多个值。
函数调⽤
-
位置参数:调⽤函数时根据函数定义的参数位置来传递参数
-
关键字参数:函数调⽤,通过“键=值”形式加以指定。可以让函数更加清晰、容易使⽤,同时也清除了参数的顺序需求。user_info('⼩明', gender='男', age=16)
注意:函数调⽤时,如果有位置参数时,位置参数必须在关键字参数的前⾯,但关键字参数之间不存在先后顺序。
-
缺省参数也叫默认参数,⽤于定义函数,为参数提供默认值,调⽤函数时可不传该默认参数的值(注 意:所有位置参数必须出现在默认参数前,包括函数定义和调⽤)def user_info(name, age, gender='男'):
-
不定⻓参数也叫可变参数。⽤于不确定调⽤的时候会传递多少个参数(不传参也可以)的场景。此时,可⽤包裹(packing)位置参数,或者包裹关键字参数,来进⾏参数传递,会显得⾮常⽅便。返回⼀个元组,不传数据时返回空元组
包裹位置传递
def user_info(*args):
注意:传进的所有参数都会被args变量收集,它会根据传进参数的位置合并为⼀个元组(tuple),
args是元组类型,这就是包裹位置传递。
包裹关键字传递
def user_info(kwargs):**
user_info(name='TOM', age=18, id=110)
组包
综上:⽆论是包裹位置传递还是包裹关键字传递,都是⼀个组包的过程
元组类型不定长参数与字典类型不定长参数的混合使用
def num(*args, **kwargs): for i in args: print(i) for key,value in kwargs.items(): print("key:",key,"value:",value)
多个返回值元组拆包
def return_num(): return 100, 200 num1, num2 = return_num()
dict1 = {'name': 'TOM', 'age': 18} a, b = dict1
-
对字典拆包,取出来的是字典的key
-
交换变量值 a, b = b, a
-
在python中,值是靠引⽤来传递来的。
-
我们可以⽤ id() 来判断两个变量是否为同⼀个值的引⽤。 我们可以将id值理解为那块内存的地址标识
int:计算前后id值不同
列表:计算前后id值相同
-
不可变参数用值传递
像整数和字符串这样的不可变对象,是通过拷贝进行传递的,因为你无论如何都不可能在原处改变不可变对象
-
可变参数是引用传递
比如像列表,字典这样的对象是通过引用传递、和C语言里面的用指针传递数组很相似,可变对象能在函数内部改变。
-
⽤户选择系统功能的代码需要循环使⽤,直到⽤户主动退出系统。
-
用列表存储学生,用字典存储学生信息
递归
函数内部⾃⼰调⽤⾃⼰,必须有出⼝
lambda 表达式
如果⼀个函数有⼀个返回值,并且只有⼀句代码,可以使⽤ lambda 参数列表 : 表达式
lambda表达式的参数可有可⽆,函数的参数在lambda表达式中完全适⽤。
lambda表达式能接收任何数量的参数但只能返回⼀个表达式的值。
lambda的参数形式
-
⽆参数
fn2 = lambda: 100
print(fn1())
-
默认参数
fn1 = lambda a, b, c=100: a + b + c
print(fn1(10, 20))
-
可变参数:*args
fn1 = lambda *args: args
print(fn1(10, 20, 30))
注意:这⾥的可变参数传⼊到lambda之后,返回值为元组。
-
可变参数:**kwargs
fn1 = lambda **kwargs: kwargs
print(fn1(name='python', age=20))
-
带判断的lambda
fn1 = lambda a, b: a if a > b else b
print(fn1(1000, 500))
列表数据按字典key的值排序
students = [ {'name': 'TOM', 'age': 20}, {'name': 'ROSE', 'age': 19},
{'name': 'Jack', 'age': 22} ]
# 按name值升序排列
students.sort(key=lambda x: x['name'])
print(students)
# 按name值降序排列
students.sort(key=lambda x: x['name'], reverse=True)
print(students)
⾼阶函数
把函数作为参数传⼊,这样的函数称为⾼阶函数,⾼阶函数是函数式编程的体现。函数式编程就是指这种⾼度抽象的编程范式。
-
abs() 函数可以完成对数字求绝对值计算
-
round() 函数可以完成对数字的四舍五⼊计算。
注意:函数式编程⼤量使⽤函数,减少了代码的重复,因此程序⽐较短,开发速度较快
def sum_num(a, b, f): return f(a) + f(b) result = sum_num(-1, 2, abs) print(result)
-
map(func, lst):将传⼊的函数变量func作⽤到lst变量的每个元素中,并将结果组成新的列表
list1 = [1, 2, 3, 4, 5] def func(x): return x ** 2 result = map(func, list1)
-
reduce(func,list)每次func计算的结果继续和序列的下⼀个元素做累积计算。
import functools list1 = [1, 2, 3, 4, 5] def func(a, b): return a + b result = functools.reduce(func, list1)
-
filter(func, lst)函数⽤于过滤序列, 过滤掉不符合条件的元素,
返回⼀个 filter 对象。如果要转换为列表, 可以使⽤ list() 来转换。
Python中pass语句的作用是 在编写代码时只写框架思路,具体实现还未编写就可以用 pass 进行占位,使程序不报错,不会进行任何操作
文件
把⼀些内容(数据)存储存放起来,可以让程序下⼀次执⾏的时候直接使
⽤,⽽不必重新制作⼀份,省时省⼒。
拓展模式要遵循于主访问模式rwa
文件操作
open函数,可以打开⼀个已经存在的⽂件,或者创建⼀个新⽂件
open(name, mode)
f = open('test.txt', 'w')
此时的 f 是 open 函数的⽂件对象。
⽂件对象⽅法
-
对象.write('内容')
注意:
-
w 和 a 模式:如果⽂件不存在则创建该⽂件;如果⽂件存在, w 模式先清空再写⼊, a 模式 直接末尾追加。
-
r 模式:如果⽂件不存在则报错
-
⽂件对象.read(num)
num表示要从⽂件中读取的数据的⻓度(单位是字节),如果没有传⼊num,那么就表示读取⽂件中所有的数据。
-
readlines
可以按照⾏的⽅式把整个⽂件中的内容进⾏⼀次性读取,并且返回的是⼀个列表,其中每⼀⾏的数据为⼀个元素。content=f.readlines()
-
readline()
⼀次读取⼀⾏内容
content = f.readline() print(f'第⼀⾏:{content}') content = f.readline() print(f'第⼆⾏:{content}')
-
seek()
作⽤:⽤来移动⽂件指针。
⽂件对象.seek(偏移量, 起始位置)
起始位置:
0:⽂件开头
1:当前位置
2:⽂件结尾
⽂件备份
需求:⽤户输⼊当前⽬录下任意⽂件名,程序完成对该⽂件的备份功能(备份⽂件名为xx[备份]后缀,例 如:test[备份].txt)
1.接收⽤户输⼊的⽂件名
old_name = input('请输⼊您要备份的⽂件名:')
2.规划备份⽂件名
-
2.1提取⽬标⽂件后缀
index = old_name.rfind('.')
-
2.2 组织备份的⽂件名,xx[备份]后缀
切片new_name = old_name[:index] + '[备份]' + old_name[index:]
3.备份⽂件写⼊数据
-
3.1打开源⽂件和备份⽂件
(注意因为编码格式的问题,我们为了防止出现乱码,需要在这里设置
f = open("movie.txt","w",encoding="utf8")) old_f=open(old_name,'rb') new_f=open(new_name,'wb')
-
3.2 将源⽂件数据写⼊备份⽂件
如果不确定目标文件大小,循环读取写入,当读取数据没有了结束循环
while True: con = old_f.read(1024) if len(con) == 0: break new_f.write(con)
-
3.3 关闭⽂件
注意如果⽤户输⼊ .txt ,这是⼀个⽆效⽂件,程序如何更改才能限制只有有效的⽂件名才能备份?
答:添加条件判断即可,如果变量没有定义就会报错
if index > 0: postfix = old_name[index:] new_name = old_name[:index] + '[备份]' + postfix
⽂件夹操作
导⼊os模块 os.函数名() import os
-
⽂件重命名
os.rename(⽬标⽂件名, 新⽂件名)
-
删除⽂件
os.remove(⽬标⽂件名)
-
创建⽂件夹
os.mkdir(⽂件夹名字)
-
删除⽂件夹
os.rmdir(⽂件夹名字)
-
获取当前⽬录
os.getcwd()
-
改变默认⽬录
os.chdir(⽬录)
-
获取⽬录列表
os.listdir(⽬录)
⾯向对象
⾯向对象就是将编程当成是⼀个事物,对外界来说,事物是直接使⽤的,不⽤去管他内部的情况。⽽编程就是设置事物能够做什么事。
类和对象
类和对象的关系:⽤类去创建⼀个对象。
类是对⼀系列具有相同特征和⾏为的事物的统称,是⼀个抽象的概念,不是真实存在的事物。
特征即是属性
⾏为即是⽅法
类⽐如是制造洗⾐机时要⽤到的图纸,也就是说类是⽤来创建对象。
对象是类创建出来的真实存在的事物,例如:洗⾐机。
注意:开发中,先有类,再有对象。
定义类
class 类名():
注意:类名要满⾜标识符命名规则,同时遵循⼤驼峰命名习惯。
创建对象 对象⼜名实例。
对象名 = 类名()
对象调⽤实例⽅法
haier1.wash()
self
指的是调⽤该函数的对象。
注意:打印对象和self得到的结果是⼀致的,都是当前对象的内存中存储地址。
对象属性既可以在类外⾯添加和获取,也能在类⾥⾯添加和获取
-
类外⾯添加对象属性
对象名.属性名 = 值
-
类⾥⾯获取对象属性
self.属性名=值
魔法⽅法
在Python中, xx() 的函数叫做魔法⽅法,指的是具有特殊功能的函数
-
init() ⽅法的作⽤:初始化对象。
# 定义初始化功能的函数 def __init__(self): # 添加实例属性 self.width = 500 self.height = 800
注意:
init() ⽅法,在创建⼀个对象时默认被调⽤,不需要⼿动调⽤
init(self) 中的self参数,不需要开发者传递,python解释器会⾃动把当前的对象引⽤传递过去
带参数的init()
⼀个类可以创建多个对象,对不同的对象设置不同的初始化属性传参数
def __init__(self, width, height): self.width = width self.height = height
-
str() 方法
当使⽤print输出对象的时候,默认打印对象的内存地址。如果类定义了 str ⽅法,那么就会打印从在这个⽅法中 return 的数据。
def __str__(self): return '这是海尔洗⾐机的说明书'
-
del() 方法
当删除对象时,python解释器也会默认调⽤ del() ⽅法。
综合应⽤
5.1 烤地⽠ 详情看相关代码
5.2搬家具 详情看相关代码
⾯向对象-继承
Python⾯向对象的继承指的是多个类之间的所属关系,即⼦类默认继承⽗类的所有属性和⽅法
class A(object): def __init__(self): self.num = 1 def info_print(self): print(self.num) class B(A): pass result = B() result.info_print()
在Python中,所有类默认继承object类,object类是顶级类或基类;其他⼦类叫做派⽣类
多继承
-
单继承师⽗要把这套技术传授给他的唯⼀的最得意的徒弟。
-
多继承所谓多继承意思就是⼀个类同时继承了多个⽗类。
注意:当⼀个类有多个⽗类的时候,默认使⽤第⼀个⽗类的同名属性和⽅法。
-
print(Prentice.mro)查看继承关系
⼦类重写⽗类同名⽅法和属性
⼦类和⽗类具有同名属性和⽅法,默认使⽤⼦类的同名属性和⽅法
⼦类调⽤⽗类的同名⽅法和属性
故事:很多顾客都希望也能吃到古法和⿊⻢的技术的煎饼果⼦。
class Prentice(School, Master): def __init__(self): self.kongfu = '[独创煎饼果⼦配⽅]' def make_cake(self):
# 如果是先调⽤了⽗类的属性和⽅法,⽗类属性会覆盖⼦类属性,故在调⽤属性前,先调⽤⾃⼰⼦类的初始化 self.init()
# 调⽤⽗类⽅法,但是为保证调⽤到的也是⽗类的属性,必须在调⽤⽅法前调⽤⽗类的初始化
def make_master_cake(self): Master.__init__(self) Master.make_cake(self) def make_school_cake(self): School.__init__(self) School.make_cake(self)
多层继承
class Tusun(Prentice):(详情看代码)
故事:N年后,daqiu⽼了,想要把所有技术传承给⾃⼰的徒弟
super()调⽤⽗类⽅法往上一级
如果super()继承了多个父类,且父类都有同名方法,则默认只执行第一个父类的(同名方法只执行一次,目前super()不支持执行多个父类的同名方法)
-
# ⽅法2.1 有参数
super(School, self).__init__() super(School, self).make_cake()
-
# ⽅法2.2 无参数
super().__init__() super().make_cake()
⼀次性调⽤⽗类的同名属性和⽅法
def make_old_cake(self):
# ⽅法⼀:代码冗余;⽗类类名如果变化,这⾥代码需要频繁修改
\# master.__init__(self) \# master.make_cake(self) \# school.__init__(self) \# school.make_cake(self)
注意:使⽤super() 可以⾃动查找⽗类。调⽤顺序遵循 mro 类属性的顺序。⽐较适合单继承使⽤。
重写方法后,父类调用的是自己的方法,子类是调用重写后的方法
私有权限
定义私有属性和⽅法
在Python中,可以为实例属性和⽅法设置私有权限,即设置某个实例属性或实例⽅法不继承给⼦类。
-
设置私有权限的⽅法:在属性名和⽅法名 前⾯加上两个下划线 __。
获取和修改私有属性值
在Python中,⼀般定义函数名 get_xx ⽤来获取私有属性,定义 set_xx ⽤来修改私有属性值。
-
获取私有属性
def get_money(self): return self.__money
-
修改私有属性
def set_money(self): self.__money = 500
⾯向对象三⼤特性
-
封装
将属性和⽅法书写到类的⾥⾯的操作即为封装
封装可以为属性和⽅法添加私有权限
-
继承
⼦类默认继承⽗类的所有属性和⽅法
⼦类可以重写⽗类属性和⽅法
多态
传⼊不同的对象,产⽣不同的结果
多态指的是⼀类事物有多种形态,(⼀个抽象类有多个⼦类,因⽽多态的概念依赖于继承)。
定义:多态是⼀种使⽤对象的⽅式,⼦类重写⽗类⽅法,调⽤不同⼦类对象的相同⽗类⽅法,可以产⽣不同的执⾏结果
好处:调⽤灵活,有了多态,更容易编写出通⽤的代码,做出通⽤的编程,以适应需求的不断变化!
实现步骤:
-
1.定义⽗类,并提供公共⽅法
-
2.定义⼦类,并重写⽗类⽅法
-
3.传递⼦类对象给调⽤者,可以看到不同⼦类执⾏效果不同
类属性
类属性就是类对象所拥有的属性,它被该类的所有实例对象所共有。
类属性可以使⽤类对象或实例对象访问
类属性的优点
-
记录的某项数据始终保持⼀致时,则定义类属性。
-
实例属性要求每个对象为其单独开辟⼀份内存空间来记录数据,⽽类属性为全类所共有,仅占⽤⼀份内存,更加节省内存空间。
如果类属性和实例属性名字相同,那么实例对象调用的是实例属性
修改类属性
类属性只能通过类对象修改,不能通过实例对象修改,如果通过实例对象修改类属性,表示的是创建了⼀个实例属性。
class Dog(object): def __init__(self): **定义的实例属性** self.age = 5 def info_print(self): print(self.age) wangcai = Dog() print(wangcai.age) # 5 \# print(Dog.age) # **报错:实例属性不能通过类访问** wangcai.info_print() # 5
类⽅法和静态方法
需要⽤装饰器 @classmethod 来标识其为类⽅法,对于类⽅法,第⼀个参数必须是类对象,⼀般以 cls 作为第⼀个参数。
类⽅法使⽤场景
当⽅法中需要使⽤类对象 (如访问私有类属性等)时,定义类⽅法⼀般和类属性配合使⽤
class Dog(object): __tooth = 10 @classmethod def get_tooth(cls): return cls.__tooth
静态⽅法特点
需要通过装饰器 @staticmethod 来进⾏修饰,静态⽅法既不需要传递类对象也不需要传递实例对象 (形参没有self/cls)。
静态⽅法也能够通过实例对象和类对象去访问。
静态⽅法使⽤场景
-
当⽅法中既不需要使⽤实例对象(如实例对象,实例属性),也不需要使⽤类对象 (如类属性、类⽅法、创建实例等)时,定义静态⽅法
-
取消不需要的参数传递,有利于减少不必要的内存占⽤和性能消耗
class Dog(object): @staticmethod def info_print(): print('这是⼀个狗类,⽤于创建狗实例....') wangcai = Dog() \# **静态⽅法既可以使⽤对象访问⼜可以使⽤类访问** wangcai.info_print() Dog.info_print()
-
init 构造器,当一个实例被创建的时候初始化的方法。但是它并不是实例化调用的第一个方法。
-
new才是实例化对象调用的第一个方法,它只取下 cls 参数,并把 其他参数传给 init。 new很少使用,但是也有它适合的场景,尤其是当类继承自一个像元组或者字符串这样不经常改变的类型的时候。
-
call 允许一个类的实例像函数一样被调用 。
-
getitem 定义获取容器中指定元素的行为,相当于 self[key] 。
-
getattr 定义当用户试图访问一个不存在属性的时候的行为 。
-
setattr 定义当一个属性被设置的时候的行为 。
-
getattribute 定义当一个属性被访问的时候的行为 。
面向对象是相对于面向过程而言的。面向过程语言是一种基于功能分析的、以算法为中心的程序设计方法;而面向对象是一种基于结构分析的、以数据为中心的程序设计思想。在面向对象语言中有一个有很重要东西,叫做类。面向对象有三大特性:封装、继承、多态。
异常
-
异常的写法
try:
可能发⽣错误的代码
except:
如果出现异常执⾏的代码
-
捕获指定异常
try:
可能发⽣错误的代码
except 异常类型:
如果捕获到该异常类型执⾏的代码
注意:
-
如果尝试执⾏的代码的异常类型和要捕获的异常类型不⼀致,则⽆法捕获异常。
-
⼀般try下⽅只放⼀⾏尝试执⾏的代码。
-
捕获多个异常
可以把要捕获的异常类型的名字,放到except 后,并使⽤元组的⽅式进⾏书写。
except (NameError, ZeroDivisionError):
-
捕获异常描述信息
except (NameError, ZeroDivisionError) as result:
-
捕获所有异常
Exception是所有程序异常类的⽗类。
-
异常的else
else表示的是如果没有异常要执⾏的代码。
try: print(1) except Exception as result: print(result) else: print('我是else,是没有异常的时候执⾏的代码')
-
异常的finally
finally表示的是⽆论是否异常都要执⾏的代码,例如关闭⽂件。
-
异常的传递(详情看代码pycharm)
需求:
-
尝试只读⽅式打开test.txt⽂件,如果⽂件存在则读取⽂件内容,⽂件不存在则提示⽤户即可。
-
读取内容要求:尝试循环读取内容,读取过程中如果检测到⽤户意外终⽌程序,则 except 捕获异常并提示⽤户。
import time time.sleep(2)
-
⾃定义异常
在Python中,抛出⾃定义异常的语法为 raise 异常类对象 。
需求:密码⻓度不⾜,则报异常(⽤户输⼊密码,如果输⼊的⻓度不⾜3位,则报错,即抛出⾃定义异常,并捕获该异常)。
class ShotInputError(Exception): def __init__(self,length,min_len): self.length=length self.min_len=min_len def __str__(self):# 设置抛出异常的描述信息 return f'你输入的密码长度为{self.length},不能少于{self.min_len}' def main(): try: con=input("请输入密码:") if len(con)<3: raise ShotInputError(len(con),3) except Exception as result: print(result) else: print("密码输入完成") main()
-
IOError:输入输出异常
-
AttributeError:试图访问一个对象没有的属性
-
ImportError:无法引入模块或包,基本是路径问题
-
IndentationError:语法错误,代码没有正确的对齐
-
IndexError:下标索引超出序列边界
-
KeyError:试图访问你字典里不存在的键
-
SyntaxError:Python代码逻辑语法出错,不能执行
-
NameError:使用一个还未赋予对象的变量
模块
Python 模块(Module),是⼀个 Python ⽂件,以 .py 结尾,包含了 Python 对象定义和Python语句。
模块能定义函数,类和变量,模块⾥也能包含可执⾏的代码。
导⼊模块的⽅式
-
import 模块名 不需要担心模块功能名字重复的问题
-
from 模块名 import 功能名
-
from 模块名 import *
-
import 模块名 as 别名
-
from 模块名 import 功能名 as 别名
注意:变量也会覆盖模块
制作模块
在Python中,每个Python⽂件都可以作为⼀个模块,模块的名字就是⽂件的名字。也就是说⾃定义模块名必须要符合标识符命名规则。
测试模块
在实际开中,当⼀个开发⼈员编写完⼀个模块后,为了让模块能够在项⽬中达到想要的效果,这个开发⼈员会⾃⾏在py⽂件中添加⼀些测试信息.,例如,在 my_module1.py ⽂件中添加测试代码。testA(1, 1)
此时,⽆论是当前⽂件,还是其他已经导⼊了该模块的⽂件,在运⾏的时候都会⾃动执⾏ testA 函数的调⽤。
-
只在当前⽂件中调⽤该函数,其他导⼊的⽂件内不符合该条件,则不执⾏testA函数调⽤
def testA(a, b): print(a + b) if __name__ == '__main__': testA(1, 1)
如果使⽤ from .. import .. 或 from .. import * 导⼊多个模块的时候,且模块内有同名功能。当调⽤这个同名功能的时候,调⽤到的是后⾯导⼊的模块的功能。
模块定位顺序
当导⼊⼀个模块,Python解析器对模块位置的搜索顺序是:
-
-
当前⽬录
-
-
-
如果不在当前⽬录,Python则搜索在shell变量PYTHONPATH下的每个⽬录。
-
-
-
如果都找不到,Python会察看默认路径。UNIX下,默认路径⼀般为/usr/local/lib/python/
-
注意 #name 输出模块名,是系统变量是模块的标识符,如果是自身模块那么值是**main**否则是当前的模块的名字
import my_module1 my_module1.testA(1, 1) \# 模块1代码 def my_test(a, b): print(a + b) \# 模块2代码 def my_test(a, b): print(a - b)
模块搜索路径存储在system模块的sys.path变量中。变量⾥包含当前⽬录,PYTHONPATH和由安装过程决定的默认⽬录。
注意
-
⾃⼰的⽂件名不要和已有模块名重复,否则导致模块功能⽆法使⽤
-
使⽤from 模块名 import 功能 的时候,如果功能名字重复,调⽤到的是最后定义或导⼊的功能。
-
如果⼀个模块⽂件中有 all 变量,当使⽤ from xxx import * 导⼊时,只能导⼊这个列表中的元素。
包
将有联系的模块组织在⼀起,即放到同⼀个⽂件夹下,并且在这个⽂件夹创建⼀个名字为 init.py ⽂件,那么这个⽂件夹就称之为包。
制作包
[New] — [Python Package] — 输⼊包名 — [OK] — 新建功能模块(有联系的模块)。
注意:新建包后,包内部会⾃动创建 init.py ⽂件,这个⽂件控制着包的导⼊⾏为
导⼊包
-
⽅法⼀
import 包名.模块名
包名.模块名.⽬标
-
⽅法⼆
注意:必须在 init.py ⽂件中添加 all = [] ,控制允许导⼊的模块列表
from 包名 import *
模块名.⽬标
⾯向对象版学员管理系统
⼀系统需求
使⽤⾯向对象编程思想完成学员管理系统的开发,具体如下:
系统要求:学数据存储在⽂件中
系统功能:添加学员、删除学员、修改学员信息、查询学员信息、显示所有学员信息、保存学员信
息及退出系统等功能。
⼆准备程序⽂件
2.1 分析
⻆⾊分析
学员
管理系统
⼯作中注意事项
-
为了⽅便维护代码,⼀般⼀个⻆⾊⼀个程序⽂件;
-
项⽬要有主程序⼊⼝,习惯为 main.py
2.2 创建程序⽂件
-
创建项⽬⽬录,例如: StudentManagerSystem程序⽂件如下:
-
程序⼊⼝⽂件:main.py
-
学员⽂件:student.py
-
管理系统⽂件:managerSystem.py
三书写程序
3.1 student.py
需求:
-
学员信息包含:姓名、性别、⼿机号;
-
添加 str 魔法⽅法,⽅便查看学员对象信息
3.2 managerSystem.py
需求:
-
存储数据的位置:⽂件(student.data)
-
加载⽂件数据
-
修改数据后保存到⽂件
存储数据的形式:列表存储学员对象
-
系统功能
-
添加学员
-
删除学员
-
修改学员
-
查询学员信息
-
显示所有学员信息
-
保存学员信息
-
退出系统
3.2.1 定义类
3.2.2 管理系统框架
需求:系统功能循环使⽤,⽤户输⼊不同的功能序号执⾏不同的功能。
步骤
-
定义程序⼊⼝函数
-
加载数据
-
显示功能菜单
-
⽤户输⼊功能序号
-
根据⽤户输⼊的功能序号执⾏不同的功能
-
定义系统功能函数,添加、删除学员等
3.3 main.py
3.4 功能实现
3.4.1 添加功能
需求:⽤户输⼊学员姓名、性别、⼿机号,将学员添加到系统。
步骤
-
⽤户输⼊姓名、性别、⼿机号
-
创建该学员对象
-
将该学员对象添加到列表
3.4.2 删除学员
需求:⽤户输⼊⽬标学员姓名,如果学员存在则删除该学员。
步骤
-
⽤户输⼊⽬标学员姓名
-
遍历学员数据列表,如果⽤户输⼊的学员姓名存在则删除,否则则提示该学员不存在。
3.4.3 修改学员信息
需求:⽤户输⼊⽬标学员姓名,如果学员存在则修改该学员信息。
步骤
-
⽤户输⼊⽬标学员姓名;
-
遍历学员数据列表,如果⽤户输⼊的学员姓名存在则修改学员的姓名、性别、⼿机号数据,
否则则提示该学员不存在。
3.4.5 查询学员信息
需求:⽤户输⼊⽬标学员姓名,如果学员存在则打印该学员信息
步骤
-
⽤户输⼊⽬标学员姓名
-
遍历学员数据列表,如果⽤户输⼊学员姓名存在则打印学员信息,否则提示该学员不存在。
3.4.6 显示所有学员信息
打印所有学员信息
步骤
遍历学员数据列表,打印所有学员信息
3.4.7 保存学员信息
需求:将修改后的学员数据保存到存储数据的⽂件。
步骤
-
打开⽂件
-
⽂件写⼊数据
-
关闭⽂件
思考
-
⽂件写⼊的数据是学员对象的内存地址吗?
⽂件写⼊的数据不能是学员对象的内存地址,需要把学员数据转换成列表字典数据再做存储
-
⽂件内数据要求的数据类型是什么?
拓展 dict
class A(object): a = 0 def __init__(self): self.b = 1 aa = A() \# 返回类内部所有属性和⽅法对应的字典 print(A.__dict__) \# 返回实例属性和值组成的字典 print(aa.__dict__)
3.4.8 加载学员信息
需求:每次进⼊系统后,修改的数据是⽂件⾥⾯的数据
步骤
-
尝试以 "r" 模式打开学员数据⽂件,如果⽂件不存在则以 "w" 模式打开⽂件
如果⽂件存在则读取数据并存储数据
-
读取数据
-
转换数据类型为列表并转换列表内的字典为对象
-
存储学员数据到学员列表
-
关闭⽂件
-
将字符串列表转换成原本列表new_list = eval(data)
常用的Python标准库
os操作系统,time时间,random随机,pymysql连接数据库,threading线程,multiprocessing进程,queue队列。
第三方库:
django和flask也是第三方库,requests,virtualenv,selenium,scrapy,xadmin,celery,re,hashlib,md5。
常用的科学计算库(如Numpy,Scipy,Pandas)。
python面试题
print调用Python中底层的什么方法?
print方法默认调用sys.stdout.write方法,即往控制台打印字符串
a=1,b=2,不用中间变量交换a和b的值?
方法一: \1. a = a+b \2. b = a-b \3. a = a-b 方法二: \1. a = a^b \2. b =b^a \3. a = a^b 方法三: \1. a,b = b,a
拓展题4G内存怎么读取一个5G的数据?
参考答案
方法一:
可以通过生成器,分多次读取,每次读取数量相对少的数据(比如500MB)进行处理,处理结束后在读取后面的
500MB的数据。
方法二:
可以通过linux命令split切割成小文件,然后再对数据进行处理,此方法效率比较高。可以按照行数切割,可以按照文件大小切割。
待更新。。。。。。。。。。。。