笔记对应视频链接:python教程
快捷键
Ctrl + ] 选中的代码行右缩进一个Tab
Ctrl + [ 选中的代码行左缩进一个Tab
Alt + 3 在选中代码行的最左端添加注释符号’##’
Alt + 4 删除选中代码行最左端的注释符号’##’
F5 运行编辑器内的程序文件
pip list 查看以及安装的库
print函数
输出数字:print(222)
输出字符串:print(‘hello’) print(“hello”)
输出表达式:print(2 + 4)
输入文件:
fp = open("F:/test.txt",'a+')
print("hello world",file = fp)
fp.close()
不进行换行输出用逗号隔开:
print('hello','world')
转义字符与原字符
换行:\n
退格:\b
制表符:\t
覆盖符:\r
反斜杠:\
单引号:\’
双引号:\"
原字符:不希望字符串中的转义字符起作用,就使用原字符,就是在字符串之前加上r或者R
print(r'hello\nworld\') //最后一个不能是反斜线
print(r'hello\nworld\\')
二进制与字符编码
二进制0,1->ASCII->Unicode(几乎包含了全世界的字符,都是用2个字节表示)->utf-8(中文3个字节表示,英文1个字节表示)
print(chr(0b100111001011000)) //打印'乘'字
print(ord('乘')) //打印0b100111001011000的十进制20056
标识符和保留字
输出python保留字
import keyword
print(keyword.kwlist)
#['False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']
标识符:变量、函数、类、模块和对其它对象起的名字
规则:字母、数字、下划线;不能以数字开头;不能与保留字重名;严格区分大小写
变量的定义和使用
name = '玛利亚'
print('标识',id(name)) #2633937837872
print('类型',type(name)) #<class 'str'>
print('值',name) #玛利亚
#赋值
name = '杰西卡' #'玛利亚'被垃圾回收
数据类型
整数类型(int)
n1 = 90
n2 = -76
n3 = 0
#整数可以表示为二进制、十进制、八进制、十六进制
print('十进制',118)
print('二进制',0b10101111) #175
print('八进制',0o176) #126
print('十六进制',0x1EAF) #7855
浮点类型(float)
a = 3.14
print(a,type(a)) #<class 'float'>
n1 = 1.1
n2 = 2.2
print(n1 + n2) #3.3000000001(有误差)
#增加精度
from decimal import Decimal
print(Decimal('1.1') + Decimal('2,2')) #3.3
布尔类型(bool)
f1 = True
f2 = False
print(f1,type(f1)) # True <class 'bool'>
#布尔类型可以直接当成整数计算
print(f1 + 1) #2
字符串类型(str)
str1 = '人生苦短 我用Python'
str2 = "人生苦短"
str3 = '''人生苦短
我用Python'''
#<class 'str'>
数据类型转换
#str、int、float、bool类型可以相互转换
name = '张三'
age = 20
print('我叫' + name + '今年' + (str)age + '岁')
#我叫张三今年20岁
#str转int,必须是数字串
#float转int,截取整数部分
#str转float,必须是数字串
#int转float,加小数点
注释
单行注释:以’#'开头,直到换行
多行注释:并没有单独的多行注释,将一对三引号之间的代码成为多行注释
中文编码声明注释:在文件开头加上中文声明注释,用以指定源码文件的编码格式 #coding:gbk、#coding:utf-8
输入函数input()
present = input('大圣想要什么礼物?') #大圣想要什么礼物?定海神针
print(present) #定海神针
a = input('请输入一个加数:')
b = input('请输入另一个加数')
print((int)a + (int)b) #或者a = int(input('请输入一个加数:'))
运算符
除法运算(/)
整除运算(//):一正一负向下取整 9//-4 = -3
取余运算(%):一正一负要公式->余数 = 被除数-除数*商
幂运算(**)
赋值运算符(=):a,b,c = 20,30,40 #a = 20, b = 30, c = 40
交换两个变量的值:a,b = b,a
比较运算符:>、<、>=、<=、==、!=
id比较:is #a is not b a的id与b的id是不相等的
布尔运算符:and 、or、not、in #s = ‘hello’ print(‘e’ in s) True
位运算符:位于(&)、位或(|)、左移(<<)、右移(>>)
运算符的优先级
括号>算术运算符>位运算符>比较运算符>布尔运算符>赋值运算符
程序的组织结构
顺序结构:程序语句按顺序执行
对象的布尔值
0、空字符串、列表、元组、字典、集合的布尔值都是False
分支结构
单分支结构 if 条件表达式: 条件执行体
双分支结构 if 条件表达式:条件执行体1 else:条件执行体2
多分支结构 if 条件表达式1:条件执行体1 elif 条件表达式2:条件执行体2 else:条件执行体3
嵌套if
条件表达式
格式 条件执行体1 if 条件表达式 else 条件执行体2
True执行1,False执行2
Pass语句
什么都不做,只是一个占位符,用到需要语句的地方
if ans == ‘yes’:
pass
else:
pass
range函数
三种创建方式 range(start,stop,step)
1.r = range(10) #查看序列 print(list®) [0,1,2,3,4,5,6,7,8,9]
2.r = range(1,10) #[1,2,3,4,5,6,7,8,9]
3.r = range(1,10,2) #[1,3,5,7,9]
while循环
while 条件表达式:
条件执行体(循环体)
for_in循环
语法结构
for 自定义变量 in 可迭代变量
循环体
如果不需要自定义变量用’_'代替
流程控制语句break和continue
break用于结束循环结构,通常与分支结构一起使用
continue用于结束当前循环
列表
列表对象的id与列表中元素的id都不同
列表的创建方式:1.使用中括号 2.使用内置函数list #obj = list([‘hello’,‘world’,98])
列表的特点:1.列表元素按顺序有序排序
2.索引映射唯一一个数据
3.列表可以存储重复数据
4.任意数据类型可以混存
5.根据需要动态分配和回收内存
列表的查询操作
obj.index(元素) 返回对应的索引,如果有重复,返回第一个,找不到就抛出异常
通过索引:正向[0:N-1] 逆向[-1:-N]
可以通过in、not in来判断元素是否在列表中
获取列表中的多个元素-切片
[start:stop:step] 获得列表的一个拷贝[start, stop)
lis1 = list([1,2,3,4,5])
lis2 = lis1[1:4:1] #lis2 = [2,3,4]
列表元素的增删改操作
在列表的结尾添加一个元素:lst.append(x)
在列表的末尾至少添加一个元素:lst.extend(x) x可以是列表
在列表指定位置添加元素:lst.insert(pos,x)
在任意的位置添加N多个元素:lst[1:] = lst3 #将1到最后的元素替换为lst3的元素
在列表中移除一个元素:lst.remove(x) #或有重复,移除第一个
删除一个指定位置的元素:lst.pop(pos) #不指定参数将删除列表中的最后一个元素
删除至少一个元素,但是将产生一个新的列表对象:new_lst = lst[1:3]
不产生新的列表对象:lst[1:3] = []
清除列表中的所有元素:lst.clear() #直接删除列表
为指定索引的元素赋予新值:lst[pos] = x
为指定的切片赋予新值:lst[1:3] = [300,400,500,500]
列表的排序操作
1.调用sort()方法:lst.sort() #默认升序,降序lst.sort(reverse = True)
2.调用sorted()方法,产生一个新的排序列表:dest_lst = sorted(lst, reverse = True)
lst中的元素顺序不变
列表生成式
lst = [i的表达式 for i in range(1,10)]
字典
Python内置的数据结构之一,与列表一样是个可变序列
以键值对的方式存储数据,字典是一个无序的序列
字典的实现原理与查字典类似,查字典是先根据部首或拼音查找对应的页码,Python中的字典是根据key查找value所在的位置
字典的创建:
1.使用花括号
socres = {'张三':100,'李四':90,'王五':85}
2.用dict()创建
student = dict(name = 'jack',age = 20)
#{'name': 'jack', 'age': 20}
字典中元素的获取:
1.[]
socres = {'张三':100,'李四':90,'王五':85}
print(socres['张三']) #100
print(socres['陈六']) #KeyError
2.get()方法
print(sorces['陈六']) #None
key的判断:
in 或者 not in
socres = {'张三':100,'李四':90,'王五':85}
print('张三' in socres)
print('张三' not in socres)
键值对的删除、清空和添加
del socres['张三']
socres.clear() #{}
socres['陈六'] = 98
字典的常用操作:
socres = {'张三':100,'李四':90,'王五':85}
keys = socres.keys() #得到所有键
values = socres.values() #得到所有值
items = socres.items() #得到所有键值对
字典元素的遍历:
for item in socres:
print(socres[item],socres.get(item))
字典的特点:
1.字典中的所有元素都是一个key-value对,key不允许重复,value可以重复
2.字典中的元素是无序的
3.字典中的key必须是不可变对象
4.字典也可以根据需要动态地伸缩
5.字典会浪费较大的内存,是一种使用空间换时间的数据结构
字典生成式:
内置函数zip():用于将可迭代的对象作为参数,将对象中对应的元素打包成一个元组,然后返回由这些元组组成的列表
items = ['Fruits','Books','Others']
prices = [96,78,85]
lst = zip(items, prices)
print(list(lst))
#[('Fruits', 96), ('Books', 78), ('Others', 85)]
d = {item.upper():price for item, price in zip(items,prices)}
print(d)
#{'FRUITS': 96, 'BOOKS': 78, 'OTHERS': 85}
元组
Python内置的数据结构之一,是一个不可变序列(没有增删改操作)
元组的创建方式:
#coding:gbk
t1 = ('Python','world',98) #或者t = 'Python','world',98
print(t1) #('Python','world',98)
#只包含一个元素需要使用逗号
t3 = ('Python',)
print(type(t3)) #<class 'tuple'>
t2 = tuple(('Python','world',98))
print(type(t2)) #<class 'tuple'>
将元组设计成不可变序列的原因:
在多任务环境下,同时操作对象时不需要加锁
注意事项: 元组中存储的是对象的引用
1.如果元组中对象本身不可对象,则不能再引用其它对象
2.如果元组中的对象是可变对象,则可变对象的引用不允许改变,但数据可以改变
t = [10,[10,20],50]
t[1].append(30)
print(t)
#[10, [10, 20, 30], 50] 列表是可变序列
元组的遍历:for … in 遍历
t = [10,[10,20],50]
for item in t:
print(item)
集合
与列表、字典一样都属于可变类型的序列
集合是没有value字典,集合中没有重复元素,集合中的元素是无序的
集合的创建方式:
s = {2,3,4,4}
print(s) #[2,3,4]
s1 = set(range(6))
print(s1) #[0,1,2,3,4,5]
集合的相关操作:
#判断操作
s = {2,3,4,5}
print(2 in s)
print(3 not in s)
#新增操作
s.add(8)
print(s) #{2, 3, 4, 5, 8}
s.update({20,10,1}) #可以放集合、列表、元组
print(s) #{1, 2, 3, 4, 5, 8, 10, 20}
#删除操作
s.remove(100) #移除一个元素,没有就KeyError
s.discard(100) #不会报错误
s.pop() #删除随机一个元素
s.clear() #清空集合
集合间的关系:
1.相等(元素是否相同)
2.一个集合是否是另一个集合的子集 s1.issubset(s2)
3.一个集合是否是另一个集合的超集 s1.issuperset(s2)
4.两个集合是否没有交集 s1.isdisjoint(s2) #没有返回True
集合的数学操作:
#coding:gbk
s1 = {10, 20, 50, 40}
s2 = {20, 30, 40, 50, 60}
#交集
print(s1.intersection(s2))
print(s1 & s2)
#{40,50,20}
#并集
print(s1.union(s2))
print(s1 | s2)
#{40, 10, 50, 20, 60, 30}
#差集
print(s1.difference(s2))
print(s1 - s2)
#{10}
#对称差集
print(s1.symmetric_difference(s2))
print(s1 ^ s2)
#{10, 60, 30}
集合生成式:
s = {i * i for i in range(6)}
print(s) #{0, 1, 4, 9, 16, 25}
字符串
1.字符串的驻留机制
仅保存一份相同且不可变字符串的方法,不同的值被存放在字符串的驻留池中,Python的驻留机制对相同的字符串只保留一份拷贝,后续创建相同字符串时,不会开辟新空间,而是把该字符串的地址赋给新创建的变量
驻留机制的几种情况(交互模式):
(1)字符串的长度为0或1时
(2)符合标识符的字符串
(3)字符串只在编译时进行驻留,而非运行时
(4)[-5,256]之间的整数数字
在需要进行字符串拼接时建议使用str类型的join方法,而非+,因为join()方法是先计算出所有字符串中的长度,然后再拷贝,只new一次对象,效率要比"+"效率高
2.字符串查询操作
s = 'hello, hello'
print(s.index('lo')) #查找最先出现的目标子串,没找到抛异常
print(s.rindex('lo')) #查找最后出现的目标子串,没找到抛异常
print(s.find('lo')) #查找最先出现的目标子串,否则返回-1
print(s.rfind('lo')) #查找最后出现的目标子串,否则返回-1
3.字符串的大小写转换操作的方法
s = 'hello,python'
a = s.upper() #转化成大写字母后产生一个新的字符串
b = s.lower() #同理
print(a) #HELLO,PYTHON
print(b) #hello,python
print(s) #hello,python
s2 = s.swapcase() #大小些互换
print(s2) #HELLO,PYTHON
s3 = s.title() #每个单词的首字母大写
print(s3) #Hello,Python
s4 = s.capitalize() #字符串第一个字母大写
print(s4) #Hello,python
4.字符串内容对齐操作的方法
s = 'hello,python'
print(s.center(20,'@')) #居中对齐,默认空格字符填充
#@@@@hello,python@@@@
print(s.ljust(20,'#')) #左对齐,默认空格填充
#hello,python########
print(s.rjust(20,'$')) #右对齐,默认空格填充
#$$$$$$$$hello,python
print(s.zfill(20)) #右对齐,左边用0填充
#00000000hello,python
5.字符串的劈分
s = 'hello world python'
print(s.split()) #默认空格分割['hello', 'world', 'python']
print(s.split(sep=' ', maxsplit=1))
#指定分隔符和分割数 ['hello', 'world python']
print(s.rsplit()) #从右往左开始分割['hello', 'world', 'python']
print(s.rsplit(sep= ' ',maxsplit=1))
#['hello world', 'python']
6.字符串的判断方法
#isidentifier()判断字符串是否是合法的标识符
print('hello_world'.isidentifier()) #True
print('12_h'.isidentifier()) #False
#isspace()判断字符串是否全部由空白字符组成(回车、空格、制表符)
print(' \t\n'.isspace()) #True
print('a '.isspace()) #False
#isalpha()判断字符串是否全部由字母组成
print('abs'.isalpha()) #True
#isdecimal()判断字符串是否全部由十进制的 数字组成
print('135'.isdecimal()) #True
print('a24'.isdecimal()) #False
#isnumerica()判断字符串是否全部由数字组成
print('943'.isnumeric()) #True
print('aaa'.isnumeric()) #False
#isalnum()判断字符串是否全部由字母和数字组成
print('a234'.isalnum()) #True
7.字符串的其它操作
s = 'hello Python python'
s1 = s.replace('Python','Java')
print(s1) #hello Java python
#str.join(iter)方法将一个可迭代对象的元素用指定字符串连接成一个字符串
lst = ['Python','Java','C++']
print('*'.join(lst))
#Python*Java*C++
tup = tuple(lst)
print('|'.join(tup))
#Python|Java|C++
ts = ''.join(lst)
print(ts) #PythonJavaC++
print('.'.join(ts)) #P.y.t.h.o.n.J.a.v.a.C.+.+
8.字符串的比较操作
print('app' <= 'apple') #True
print('adc' >= 'bac') #False
#> < == != >= <=
9.字符串的切片操作
字符串是不可变类型,不具备增删改操作,切片操作将产生新的对象
s = 'hello,Python'
s1 = s[:5:2]
s2 = s[6:]
s3 = s[-6::1]
print(s1) #hlo
print(s2) #Python
print(s3) #Python
10.格式化字符串
#格式化字符串常用的三种方法
name = '张三'
age = 20
# % 占位符
print('我叫%s 今年%d岁' % (name, age))
# {}占位符
print('我叫{0} 今年{1}岁'.format(name, age))
# f-string
print(f'我叫{name} 今年{age}岁')
#我叫张三 今年20岁
print('%10.3f' % 3.1415926)
# 3.142
print('{0:10.3f}'.format(3.1415926))
# 3.142
11.字符串的编码转换
s = '你好呀'
#编码
print(s.encode(encoding='GBK')) #一个汉字两个字节
print(s.encode(encoding='UTF-8')) #一个汉字三个字节
#b'\xc4\xe3\xba\xc3\xd1\xbd'
#b'\xe4\xbd\xa0\xe5\xa5\xbd\xe5\x91\x80'
#解码
byte = s.encode(encoding= 'GBK')
print(byte.decode(encoding='GBK'))
#你好呀
函数
1.函数的创建和调用
def calc(a,b): #a b为形参
c = a + b
return c
result = calc(10,20) #10 20为实参
print(result) #30
2.函数的参数传递
#使用了关键字就按名称赋值
def Print(a,b):
print(a,b)
Print(b = 10, a = 20)
#20 10
def fuc(a1, a2):
print(a1, a2) #100 ['20', '50']
a1 = 20
a2.append('10')
n1 = 100
n2 = ['20','50']
print(n1, n2) #100 ['20', '50']
fuc(n1, n2)
print(n1, n2) #100 ['20', '50', '10']
#参数的值是否改变取决于是不是可变对象
#如果函数没有返回值,return可以不用写
#如果返回值是一个,直接返回类型
#函数返回多个对象时,结果为元组
def fun(num):
odd = []
even = []
for i in num:
if i % 2:
even.append(i)
else:
odd.append(i)
return odd, even
num = [1,2,3,4,5,6]
res = fun(num)
print(res)
#([2, 4, 6], [1, 3, 5])
3.函数的参数定义
def fun(a, b = 10):
print(a, b)
fun(100) #100 10
fun(20,30) #20 30
print('hello', end = '^^')
#hello^^
#使用*定义个数可变的位置形参,只能定义一个
def fun(*args): #个数可变的位置参数
print(args)
fun(1,2,3) #(1, 2, 3)
#使用**定义个数可变的关键字形参,当两者都有时位置形参放在前面
def fun1(**kwargs):
print(kwargs)
fun1(a = 1, b = 2, c= 3) #{'a': 1, 'b': 2, 'c': 3}
def func(a, b, c):
print(a, b, c)
lst = [2,5,6]
func(*lst) #2 5 6
dic = {'a':12, 'b':13, 'c':14}
func(**dic) #12 13 14
4.异常处理try-except
try:
a = int(input('输入第一个数'))
b = int(input('请输入第二个数'))
print(a/b)
except ZeroDivisionError:
print('分母不能为零')
except ValueError:
print('输入了非数字')
else:
print('无异常')
finally:
print('无论是否异常都会执行')
常见的异常类型
1.ZeroDivisionError 除(或取模)零(所有数据类型)
2.IndexError 序列中没有此索引(Index)
3.KeyError 映射中没有这个键
4.NameError 未声明/初始化对象(没有属性)
5.SyntaxError Python语法错误
6.ValueError 传入无效的参数
面向对象
1.类的定义
命名规范:首字母大写,其余小写
类的组成:1.类属性 2.实例方法 3.静态方法 4.类方法
#类的定义
class Student:
native_place = '哈啰' #类属性:类中方法外的变量,被该类的所有对象所共享
#类的初始化
def __init__(self, name, age):
self.name = name
self.age = age
#实例方法(类里定义的函数叫做方法)
def Print(self):
print(self.name, self.age)
#静态方法:使用@staticmethod修饰的方法,使用类名直接访问的方法
@staticmethod
def method(): #不允许有self
print('静态方法')
#类方法:使用@classmethod修饰的方法,使用类名直接访问的方法
@classmethod
def fun(cls):
print('类方法,自带一个cls参数')
2.对象的创建
语法:实例名 = 类名()
stu1 = Student('张三',20)
stu1.Print() #调用实例方法
Student.Print(stu1) #效果同上
#使用对象的属性
print(stu1.name, stu1.age)
stu1.method() #静态方法调用
stu1.fun() #类方法调用
3.动态绑定属性和方法
#类的定义
class Student:
native_place = '哈啰' #类属性
#类的初始化
def __init__(self, name, age):
self.name = name
self.age = age
#实例方法(类里定义的函数叫做方法)
def Print(self):
print(self.name, self.age)
def show():
print('一个函数')
stu1 = Student('张三',20)
stu1.gender = '男' #动态绑定性别
print(stu1.gender)
stu1.show = show #动态绑定方法
stu1.show()
4.封装
封装:提高程序的安全性
1.将数据(属性)和行为(方法)包装到类对象中。在方法内部对属性进行操作,在类对象的外部调用方法。这样,无需关心方法内部的具体实现细节,从而隔离了复杂度
2.在Python中没有专门的修饰符用于属性的私有,如果该属性不希望在类对象外部被访问,前边使用两个"_"
class Student:
def __init__(self, name, age):
self.name = name
self.__age = age
def show(self):
print(self.name, self.__age)
stu = Student('小明',20)
print(stu.name)
#stu.__age不能在类的外部被使用,可以被实例方法使用
print(dir(stu))
print(stu._Student__age) #可以通过_类名__属性名访问,不建议
5.继承
语法格式
class 子类命( 父类1,父类2...):
pass
如果一个类没有继承任何类,则默认继承object
python支持多继承
定义子类时,必须在其构造函数中调用父类的构造函数
#类的定义
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
def show(self):
print(self.name, self.age)
#类的继承
class Student(Person):
def __init__(self, name, age, stu_number):
super().__init__(name, age)
self.stu_number = stu_number
def show_stu(self):
print(self.name, self.age, self.stu_number)
stu = Student('张三',15,135)
stu.show_stu()
#python支持多继承
class A(object):
pass
class B(object):
pass
class C(A, B): #C继承了A和B
pass
6.方法重写
如果子类对继承自父类的某个属性或方法不满意,可以在子类中对其(方法体)进行重新编写
子类重写后的方法中可以通过super().xxx()调用父类中被重写的方法
#类的定义
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
def show(self):
print(self.name, self.age)
#类的继承
class Student(Person):
def __init__(self, name, age, stu_number):
super().__init__(name, age)
self.stu_number = stu_number
#方法重写
def show(self):
super(Student, self).show()
print('学号:',self.stu_number)
stu = Student('张三',15,135)
stu.show()
#张三 15
#学号: 135
7.object类
object类是所有类的父亲,因此所有类都有object类的属性和方法
内置函数dir()可以查看指定对象所有属性
Object有一个____str____()方法,用于返回一个对于"对象的描述",对应于内置函数str()经常用于print()方法,帮我们查看对象的信息,所以我们经常会对____str____()进行重写
#类的定义
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
#重写object类的__str__()方法
def __str__(self):
return '姓名:{0} 年龄:{1}'.format(self.name, self.age)
def show(self):
print(self.name, self.age)
#类的继承
class Student(Person):
def __init__(self, name, age, stu_number):
super().__init__(name, age)
self.stu_number = stu_number
def show(self):
super(Student, self).show()
print('学号:',self.stu_number)
stu = Student('张三',15,135)
print(stu) #默认调用__str__()方法
#姓名:张三 年龄:15
8.多态
简单地说,多态就是"具有多种形态",它指的是:即便不知道一个变量所引用的对象到底是什么类型,仍然可以通过这个变量调用方法,在运行过程中根据变量所引用对象的类型,动态决定调用哪个对象中的方法。
class Animal(object):
def eat(self):
print('动物要吃东西')
class Dog(Animal):
def eat(self):
print('狗吃骨头')
class Person(object):
def eat(self):
print('人吃饭')
def func(obj):
obj.eat()
func(Dog())
func(Person())
#狗吃骨头
#人吃饭
静态语言和动态语言关于多态的区别
静态语言实现多态的三个必要条件:
1.继承
2.方法重写
3.父类引用指向子类对象
动态语言的多态崇尚"鸭子类型"当看到一只鸟走起来像鸭子、游泳起来像鸭子、收起来也像鸭子,那么这只鸟就可以被称为鸭子。在鸭子类型中,不需要关心对象是什么类型,到底是不是鸭子,只关心对象的行为
9.特殊方法和特殊属性
特殊属性:
__dict__:获得类对象或实例对象所绑定的所有属性和方法的字典
特殊方法:
__len__():通过重写__len__()方法,让内置函数len()的参数可以是自定义类型
__add__():通过重写__add__()方法,可以用自定义对象具有"+"功能
__new__():用于创建对象
__init__():对创建的对象进行初始化
class A:
pass
class B:
pass
class C(A, B):
def __init__(self, name):
self.name = name
#创建C类对象
s = C('Jack') #s是C类型的实例对象
print(s.__dict__) #实例对象的属性字典
#{'name': 'Jack'}
print(s.__class__) #输出对象所属的类型
#<class '__main__.C'>
print(C.__bases__) #输出C类的父类的元组
#(<class '__main__.A'>, <class '__main__.B'>)
print(C.__mro__) #查看类的层次结构
#(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
print(A.__subclasses__()) #查看类的子类
#[<class '__main__.C'>]
特殊方法
a = 10
b = 20
c = a.__add__(b)
print(c)
class Student:
def __init__(self, name):
self.name = name
def __add__(self, other):
return self.name + other.name
def __len__(self):
return len(self.name)
stu1 = Student('Jack')
stu2 = Student('Bob')
s = stu1 + stu2 #s = stu1.__add__(stu2)
#实现了两个对象的加法运算(因为在Student中重写了__add__()方法)
print(s)
#JackBob
print(len(stu1)) #stu1.__len__()
#4
10.__new__ 与__init__演示创建对象的过程
class Person(object):
def __new__(cls, *args, **kwargs):
print('__new__被调用执行了,cls的id值为{0}'.format(id(cls)))
obj = super().__new__(cls)
print('创建对象的id为:{0}'.format(id(obj)))
return obj
def __init__(self, name, age):
print('__init__被调用了,self的id值为{0}'.format(id(self)))
self.name = name
self.age = age
print('object这个类对象的id为:{0}'.format(id(object)))
print('Person这个类对象的id为:{0}'.format(id(Person)))
#创建Person类的实例对象
p1 = Person('张三',20)
print('p1这个Person的实例对象的id为:{0}'.format(id(p1)))
#object这个类对象的id为:8791185532960
#Person这个类对象的id为:39448216
#__new__被调用执行了,cls的id值为39448216
#创建对象的id为:32185096
#__init__被调用了,self的id值为32185096
#p1这个Person的实例对象的id为:32185096
11.类的赋值与浅拷贝
变量的赋值操作
只是形成连个变量,实际上还是指向同一个对象
浅拷贝
Python拷贝一般都是浅拷贝,拷贝时,对象包含的子对象内容不拷贝,因此,源对象与拷贝对象会引用用一个子对象
#类的赋值
class Student(object):
def __init__(self, name, age):
self.name = name
self.age = age
stu1 = Student('小明',15)
stu2 = stu1
print(id(stu1), id(stu2)) #指针指向同一个实例对象
#31176328 31176328
#类的浅拷贝
import copy
class Cpu:
pass
class Disk:
pass
class Computer:
def __init__(self, cpu, disk):
self.cpu = cpu
self.disk = disk
cpu = Cpu()
disk = Disk()
computer1 = Computer(cpu, disk)
computer2 = copy.copy(computer1) #对computer1进行浅拷贝:也就是只拷贝当前对象,其子对象不拷贝
print(id(computer1), id(computer1.cpu), id(computer1.disk))
print(id(computer2), id(computer2.cpu), id(computer2.disk))
#35818376 35816136 35816264
#35818120 35816136 35816264
深拷贝
使用copy模块的deepcopy函数,递归拷贝对象中包含的子对象,源对象和拷贝对象所有的子对象也不相同
#深拷贝(不仅拷贝当前对象,其子对象都会拷贝)
computer3 = copy.deepcopy(computer1)
print(id(computer1), id(computer1.cpu), id(computer1.disk))
print(id(computer3), id(computer3.cpu), id(computer3.disk))
#35818376 35816136 35816264
#35840456 35840520 35923784
模块(Moudules)
函数与模块的关系:一个模块中可以包含N多个函数
在Python中一个扩展名为.py的文件就是一个模块
使用模块的好处:
1.方便其它程序和脚本的导入并使用
2.避免函数名和变量名冲突
3.提高代码的可维护性
4.提高代码的可重用性
自定义模块
创建模块:新建一个.py文件,名称尽量不要与Python自带的标准模块名称相同
导入模块:
import 模块名称 [as 别名] #导入整个模块
from 模块名称 import 函数/变量/类 #导入模块中的指定部分
#自定义calc.py模块
def add(x, y):
return x + y
def div(x, y):
return (float)(x) / y
#test1.py文件
#导入自定义模块
#方法一
import calc
a = 10
b = 20
c = calc.add(a, b)
d = calc.div(a, b)
print(c, d) #30 0.5
#方法二
from calc import add, div
a = 10
b = 20
c = add(a, b)
d = div(a, b)
print(c, d) #30 0.5
以主程序形式运行
在每个模块的定义中都包含一个记录模块名称的变量__name__,程序可以检查该变量,以确定他们在哪个模块中执行。如果一个模块不是被导入到其它程序中执行,那么它可能在解释器的顶级模块中执行。顶级模块的__name__变量的值为__main__
if __name__ = '__main__':
pass
#calc2.py
def add(a, b):
return a + b
if __name__ == '__main__':
print(add(10, 20)) #只有当点击运行calc2时,才会执行运算
#main.py
import calc2
print(calc2.add(100, 200)) #300
Python中的包
包是一个分层次的目录结构,它将一组功能相近的模块组织在同一个目录下
作用:(1)代码规范(2)避免模块名称冲突
包与目录的区别:(1)包含__init__.py文件的目录称为包(2)目录里通常不包含__init__.py文件
包的导入:import 包名.模块名
包的引用:包名.模块名.(函数名、变量名等)
#导入packet1包中的模块
import packet1.module1 as mod1
print(mod1.Abs(-20))
#导入带有包的模块时注意事项
#使用import方式进行导入时,只能跟包名或模块名
#使用from...import...方式可以导入模块名、函数名、变量名
Python中常用的内置模块
sys:与Python解释器及其环境操作相关的标准库
time:提供与时间相关的各种函数的标准库
os:提供了访问操作系统服务功能的标准库
calendar:提供与日期相关的各种函数的标准库
urllib:用于读取来自网上(服务器)的数据标准库
json:用于使用JSON序列化和反序列化对象
re:用于在字符串中执行正则表达式匹配和替换
math:提供标准算术运算函数的标准库
decimal:用于进行精确控制运算精度、有效数位和四舍五入操作的十进制运算
logging:提供了灵活的记录事件、错误、警告和调试信息等日志信息的功能
import sys
import time
import urllib.request
import math
print(sys.getsizeof(24)) #28
print(sys.getsizeof(True)) #28
print(sys.getsizeof(False)) #24
print(time.time())
print(time.localtime(time.time()))
print(urllib.request.urlopen('http://www.baidu.com').read())
print(math.pi)
编码格式
常见的字符编码格式
Python的解释器使用的是Unicode(内存)
.py文件在磁盘上使用UTF-8存储(外存)
文件的读写操作
#tex1.txt (gbk)
第一行
第二行
#demo1.py
#coding:gbk
f = open('text1.txt','r') #注意打开文件的编码格式与.py文件的格式是否统一
print(f.readlines()) #['第一行\n', '第二行']
f.close()
常用的文件打开模式
文件类型:按文件中数据的组织形式,文件分为以下两大类
(1)文本文件:存储的是普通"字符"文本,默认为unicode字符集,可以使用记事本程序打开
(2)二进制文件:把数据内容用"字节"进行存储,无法用记事本打开,必须使用专用的软件打开,举例:mp3音频文件,jpg图片,.doc文档等
打开模式:
r:以只读模式打开文件,文件的指针将会放在文件的开头
w:以只写模式打开文件,如果文件不存在则创建,如果文件存在,则覆盖原有内容,文件指针在文件的开头
a:以追加模式打开文件,如果文件不存在则创建,文件指针在文件开头,如果文件存在,则在文件末尾追加内容,文件指针在原文件末尾
b:以二进制方式打开文件,不能单独使用,需要与其它模式一起使用,rb或者wb
+:以读写方式打开文件,不能单独使用,需要与其它模式一起使用,a+
文件对象的常用方法
with语句(上下文管理器)
with语句可以自动管理上下文资源,不论什么原因跳出with块都能确保文件的正确的关闭,以此来达到释放资源的目的
#离开with语句,自动释放资源
with open('text1.txt','r') as file:
print(file.read())
#举例
class Content:
def __enter__(self):
print('enter方法被调用了')
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print('exit方法被调用了')
def show(self):
print('show方法被调用了')
with Content() as f: #相当于f = Content()
f.show()
'''
enter方法被调用了
show方法被调用了
exit方法被调用了
'''
os模块操作目录相关函数
getcwd():返回当前的工作目录
listdir(path):返回指定路径下的文件和目录信息
mkdir(path[,mode]):创建目录
makedirs(path1/path2…[,mode]):创建多级目录
rmdir(path):删除目录
removedirs(path1/path2…):删除多级目录
chdir(path):将path设置为当前工作目录
os.path模块操作目录相关函数
abspath(path):用于获取文件目录的绝对路径
exists(path):用于判断文件或目录是否存在,如果存在返回True,否则返回False
join(path, name):将目录 与目录或者文件名拼接起来
splitext():分离文件名和扩展名(返回元组)
basename(path):从一个目录中提取文件名
dirname(path):从一个路径中提取文件路径,不包括文件名
isdir(path):用于判断是否为路径