一、基础概念
fp = open ( 'D:/text.txt' , 'a+' ) ;
print ( 'Hello world' , file = fp) ;
fp. close( )
print ( 1 , 2 , 'Hello' )
print ( 1 , 2 , end= ‘ ’)
"""
\\:反斜杠
\':单引号
\":双引号
\n:换行
\r:回车
\t:水平制表符
\b:退格
"""
print ( "http:\\\\www.baidu.com" )
print ( r"http:\\www.baidu.com" )
print ( R"http:\\www.baidu.com" )
print ( R"http: \\www. baidu. com\")
''' 进制
二进制0b开头指定例如:0b11001 就是二进制11001
八进制0o开头,零+欧
十六进制0x开头
十进制是默认进制
'''
''' 数据类型转换
str() 将数据转换为字符串 也可以用引号转换 str(123) 或'123'
int() 将数据转换为整数 文字类,小数点类数据无法转整数
浮点数转化成整数,抹零取整 int('123') 或 int(9.8)
float() 将数据转换为浮点数 文字类无法转换成整数
整数转成浮点数,末尾为.0 float('9.9') 或 float(9)
'''
print ( True + 1 )
print ( False + 1 )
'''
input()函数:输入函数,要求用户用键盘输入一个值,无论输入什么,都会按str类型处理
一般需要配合类型转换函数使用比如
age = int(input("请输入年龄\n"))
上面一行含义是,先提示用户输入年龄,然后换行
获取到用户输入的值,通过int函数将其转换为int型数值,然后
存储到变量age中
'''
age = int ( input ( "请输入年龄\n" ) )
print ( age, type ( age) )
'''算数运算符
+ 加
- 减
* 乘
/ 除
// 整除
% 取余
** 幂运算
'''
print ( 9 // 4 )
print ( - 9 // - 4 )
print ( - 9 // 4 )
print ( - 9 % 4 )
print ( 9 % - 4 )
print ( 2 ** 2 )
'''
比较运算符,最终结果一定是布尔(bool)值True或False
> 大于
>=大于等于
< 小于
<= 小于等于
!= 不等于
== 恒等于,=是赋值,==是比较值是否相等,注意是比较值
is 比较是否是同一个对象,比较对象的标识
is not
'''
a, b = 10 , 10
print ( id ( a) )
print ( id ( b) )
print ( a is b)
print ( a == b)
'''
运行结果
140719238902304
140719238902304
True
True
'''
'''
布尔运算符,只能对bool类型值True和False值进行运算
not 非运算符,非真为假 not True = False 非假为真 not False = True
and 与运算符,并且的意思,两个都是真,为真,有一个假为假。 True and True = True ,True and False = False , (5>6) and (6>5) ---> False and True = False
or 或运算符,或者的意思,有一个为真就是真,True or False = True ,False or False = False , (5>6) or (6>5) ---> False or True = True
in 在的意思,如果在就是真,'a' in 'lala' = True ,'a' in 'hello' = False
not in 不在的意思 ,如果不在就是真,'a' in 'hello' = True
'''
'''
位运算符,将数据转换为二进制,然后一位一位的进行比较,全部都按8位一组比较,比如0b110就是0b00000110
& 位与运算符,按位比较,两个都是1结果为1,有一个是0结果为0。0b110 & 0b110 = 0b110,0b111 & 0b110 = 0b110
| 位或运算符,有一个为1结果为1,0b110 | 0b111 = 0b111
<< 左位移运算符,让每一位向左移动一位,高位溢出舍弃,低位补0,比如0b110 = 0b00000110,进行左位移一位 0b110<<1 ---> 0b00001100。 又比如0b11000001<<1左位移后结果---> 0b10000010
>> 右位移运算符,让每一位向右移动一位,低位溢出舍弃,高位补0
'''
print ( bin ( 0b11000001 << 1 ) )
print ( bin ( 0b110 << 1 ) )
print ( 2 << 1 )
print ( 2 >> 1 )
'''
结果
0b110000010
0b1100
4
1
'''
运算符优先级 0、():有括号先算括号 1、** 2、*、/、//、%、 3、+、- 4、<< 、>> 5、& 6、 7、<、<=、 >、 >=、 ==、 != 8、not 9、and 10、or 11、=
'''
赋值
'''
a, b, c = 10 , 20 , 30
print ( a, b, c)
d, e = 10 , 20
print ( "值交换前:" , d, e)
d, e = e, d
print ( "值交换后:" , d, e)
'''上面代码的执行结果
10 20 30
值交换前: 10 20
值交换后: 20 10
'''
二、流程控制
Python一切皆对象,每一个对象都有一个对应的布尔值,以下对象对应布尔值都是False,其它对象都是True bool():此函数用来获取对象的布尔值,bool(0) -->False False 数值0 None 空字符串 空列表 空元组 空字典 空集合
'''单分支if
if 条件表达式 :
语句
else:
上面条件不成立执行的语句
'''
if 5 > 3 :
print ( "执行" )
'''多分支if
if 条件表达式1 :
语句1
elif 条件表达式2 :
语句2
elif 条件表单式3 :
语句3
else:
上面条件都不成立执行的语句
'''
if 5 > 6 :
print ( "5>6" )
elif 6 > 7 :
print ( "6>7" )
elif 5 < 4 < 7 :
print ( "5<4<7 相当于 4>5 and 4<7" )
else :
print ( "5<6 6<7" )
'''
if嵌套
'''
if 6 > 5 :
if 6 == 6 :
print ( "6>5 and 6==6" )
if 6 > 7 :
print ( "6>7" )
else :
print ( "6<7" )
'''单行if'''
print ( "条件为真获取这个值" if 5 > 6 else "条件为假获取这个值" )
print ( "条件为真获取这个值" if 7 > 6 else "条件为假获取这个值" )
a = 5 if 5 > 6 else 6
print ( "5和6对比" , a, "更大" )
pass语句 什么都不做,字面意思,过,跳过,通过的意思,用于占位,适用于语法需要语句但暂时还不知道写什么的时候
if 5 > 6 :
pass
for i in "123456789" :
pass
for i in "987654321" :
print ( i)
'''range()
生成一个整数序列,返回的是一个迭代器对象
无论整数序列有多长,range对象占用的内存空间都相同,因为存储的只有start,stop,step3个值,用到range对象才去计算序列中相关元素
前面学过的in 和 not in 可以判断一个序列或数 是不是在另一个序列中
1、range(stop):创建一个0(包含)到stop(不包含stop)的整数序列,步长为1
2、range(start,stop):创建一个start(包含)到stop(不包含)的整数序列,步长为1
3、range(start,stop,step):创建键一个start到stop的整数序列,步长为step
'''
print ( range ( 1 , 10 , 2 ) )
print ( list ( range ( 1 , 10 , 2 ) ) )
'''while循环 条件为假跳出循环
while 条件表达式:
循环体(重复执行的语句)
'''
a = 1
while a <= 5 :
print ( a)
a+= 1
'''for 循环
for - in
in:表示从字符串,序列等可迭代对象中依次取值
for 变量或_ in 可迭代对象
循环体
'''
for i in range ( 1 , 10 , 2 ) :
print ( i)
for _ in range ( 1 , 5 ) :
print ( "aaa" )
'''
break: 用来退出当前循环
continue:用来跳过本次循环,执行下次循环,比如现在第5次循环,碰到continue就不在向下执行,直接进行第6次循环
else:和if的else差不多,表示,如果循环从始至终没有执行过break语句,就执行else
else语句可以和for循环以及while循环搭配使用
'''
b = 1
while b <= 5 :
if b > 6 :
break
b+= 1
else :
print ( "没有执行break" )
三、列表、字典、元组、集合、字符串
'''列表
列表对象由[]作为定界符,列表对象可以存储任意类型的数据,不同元素之间通过逗号分隔
[1,2,3,4,"hello",[1,2,3,4],[]]
[]:代表空列表,对应布尔值为False
特点
列表是有序的,元素按顺序排列
通过索引映射元素
元素可以重复
不限制元素类型
动态分配和回收内存
'''
list1 = [ 1 , 2 , 3 , 4 , "hello" , [ 1 , 2 , 3 , 4 ] , [ ] ]
list2 = list ( [ 1 , 2 , 3 , 4 ] )
list3 = [ str ( i* i) + "是由列表生成式生成的第" + str ( i) + "个元素" for i in range ( 10 ) ]
print ( "通过列表生成式生成的列表" , list3)
print ( "\n列表id" , id ( list1) )
print ( "列表对象类型" , type ( list1) )
print ( "列表元素" , list1)
print ( "\n列表中第一个元素" , list1[ 0 ] )
print ( "列表中最后一个元素" , list1[ - 1 ] )
print ( "列表第一个元素id" , id ( list1[ 0 ] ) )
print ( "列表第一个元素类型" , type ( list1[ 0 ] ) )
print ( "\n列表中\"hello\"元素的索引" , list1. index( "hello" , 3 , 5 ) )
print ( "\n不写步长,start在stop左边(就是索引start比stop小,在左边)" , list1[ 1 : 3 ] )
print ( "写正数步长,start在stop左边" , list1[ 1 : 3 : 1 ] )
print ( "写负数步长,start在stop右边" , list1[ 3 : 1 : - 1 ] )
print ( "省略start,stop,step" , list1[ : : ] )
print ( "省略start,stop,指定负数步长,正好实现反转列表的功能" , list1[ : : - 1 ] )
print ( "\n判断元素5是不是在列表list1中?" , "在" if 5 in list1 else "不在" )
list1. append( "word" )
print ( "\n通过append()向列表中添加一个元素\"word\"" , list1)
list1. extend( [ 1 , 2 , 3 , 4 ] )
print ( "通过extend()追加一个列表[1,2,3,4]的所有元素到list1列表末尾" , list1)
list1. insert( 4 , 5 )
print ( "通过insert()添加元素5到list1列表索引为4的位置上" , list1)
list1[ 1 : ] = [ 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 ]
print ( "通过切片将list1从索引为1的位置切开,添加列表[2,3,4,5,6,7,8,9,10],原来的元素会被替换" , list1)
list1[ 0 ] = 10
list1[ 3 : 5 ] = [ 1 , 1 ]
print ( "\n修改后的列表" , list1)
list1. sort( )
print ( "\n通过sort()函数排序的list1" , list1)
list_new = sorted ( list1, reverse= True )
print ( "通过sorted()排序的list1" , list1)
print ( "可以看到sorted不改变原列表,以下是通过sorted排序产生的新列表" , list_new)
list1. remove( 1 )
print ( "\n通过remove()删除元素1" , list1)
list1. pop( 0 )
list1. pop( )
print ( "通过pop()删除索引为0的和最后位置的元素" , list1)
list1[ 1 : ] = [ ]
print ( "通过切片删除从下标1到末尾的元素" , list1)
list1. clear( )
print ( "通过clear()清除列表" , list1)
del list1
print ( "通过del()删除列表" )
'''字典
通过键值对存储数据的无序数据结构,以{}作为定界符
语法:字典名 = {键1:值1,键2:值2,.....}
为什么无序
字典的键,必须是一个不可变序列,因为Python会通过hash()函数以键为参数去计算存储位置,
那么,因为键值是不可变的,所以何时通过键获取值,都会找到相同的存储位置,获取对应值
而因为其通过hash()函数计算存储,位置,所以是无序的
用什么做键合适
一般用常量最合适,不推荐用数字常量,比如1,2,4这些
推荐使用字符串,比如存储学生信息 student = {"username":"张三","age":15} 这样就存储了一个学生,名字叫张三,年龄15岁
特点:
key不可重复,value可以重复
元素无序
key必须是不可变对象
可根据需要动态伸缩
比较浪费内存空间,但是速度快,典型的空间换时间
'''
dict1 = { 1 : "张三" , 2 : 15 , "avatar" : "无头像" }
print ( dict1[ 1 ] , dict1[ 2 ] , dict1[ "avatar" ] )
dict2 = dict ( username = "张三" , age = 15 , avatar= "无头像" )
print ( dict2)
dict3 = { }
print ( dict3)
keys = [ "username" , "age" , "avatar" ]
values = [ "生成式" , 15 , "无头像" ]
dict4 = dict ( zip ( keys, values) )
print ( "\n通过zip函数配合dict函数直接生成字典" , dict4)
dict5 = { "生成式" + key: "生成式" + str ( value) for key, value in zip ( keys, values) }
print ( "\n通过字典生成式生成字典" , dict5)
print ( "\n通过[键]的形式获取值" , dict2[ 'username' ] )
print ( "通过get()函数获取值" , dict2. get( "username" ) )
print ( "通过get()函数获取值,键不存在时,返回" , dict2. get( "home" ) , "也可以设置默认值" , dict2. get( "home" , "键没有找到,返回默认值" ) )
print ( "\n字典中所有的键为" , dict2. keys( ) )
print ( "字典中所有的值为" , dict2. values( ) )
print ( "字典中所有的键值对为" , dict2. items( ) )
print ( list ( dict2. items( ) ) )
print ( "\n判断键\"home\"是否在字典中" , "在" if "home" in dict2 else "不在" )
del dict1[ 1 ]
print ( "\n删除键值为1的键值队后字典元素为" , dict1)
dict1[ 5 ] = "新增的键值对"
print ( "\n新增 5:\"新增的键值对\" 后字典为" , dict1)
dict1[ 5 ] = "修改的键值对"
print ( "\n修改值后字典为" , dict1)
print ( "\n字典的遍历" )
for item in dict2:
print ( "键为:" , item, "值为" , dict2[ item] )
'''元组(元组是没有元组生成式的)
有序序列
和字符串一样是一个不可变序列,不可增删改
使用()作为定界符,不同元素用逗号分隔
语法:元组名 = (元素1,元素2,.......)
可变序列,更改时,地址不发生改变,而不可变序列如果你让它改变,比如
s = "11111"
s += "2222"
那么此时,s的地址是发生变化的
为什么设计为不可变序列
多任务环境下,同时操作对象又不需要加锁时,在程序中尽量使用不可变序列
因为如果多个人操作一个可变序列,显然会出现问题,就需要在第一个人操作时,将其锁住,不让其他人用
而不可变序列,无需加锁,因为所有人都无法对其进行操作,只能用,不能改
元组中存储的是什么,以及可变序列改值问题
是对象的引用地址
如果元组中的元素是不可变对象,那么不可以在引用其他对象,就是不能改了
如果元组中的元素是可变的对象,此对象的引用依旧不能改变,但是值可以改变,比如你元组中放了一个list列表,那么这块地方,就是这个列表的不能给其它列表了,
但是,这个列表自身的值可以改变
'''
tuple1 = ( "Python" , 1 , "123" )
tuple2 = tuple ( ( "Pythone" , 2 , "321" ) )
tuple3 = ( "只有一个元素,需要使用逗号" , )
tuple4 = "Python" , 4 , [ 1 , 2 ]
tuple5 = ( )
tuple4[ 2 ] . append( 3 )
print ( "\n元组中可变序列的值可以改变,其它情况都不可改变" , tuple4)
print ( "\n遍历元组" )
for i in tuple4:
print ( i)
'''集合
可变序列,可以叫集合是没有value的字典
除了没有value,它和字典基本相同,只能存不可变序列
无序的,都使用hash()存引用,所以存的值不能重复
经常在去重时使用(去掉重复数据)
'''
print ( "\n集合======================" )
set1 = { "Python" , 2 , "set" , "set" }
set2 = set ( "Python" )
set3 = set ( range ( 10 ) )
set4 = set ( )
print ( "可以看到集合是不允许有重复元素的,两个set只剩下了一个" , set1)
set5 = { i* i for i in range ( 10 ) }
set4. add( 5 )
set4. update( "123455" )
set4. update( [ 1 , 2 , 3 , 4 ] )
print ( set4)
set1 = { 1 , 2 , 3 , 4 }
set2 = { 1 , 2 , 3 , 4 , 5 }
print ( set1. issubset( set2) )
print ( set2. issuperset( set1) )
print ( set1. isdisjoint( set2) )
print ( "交集" , set1. intersection( set2) , set1 & set2)
print ( "并集" , set1. union( set2) , set1 | set2)
print ( "差集" , set1. difference( set2) , set1 - set2)
print ( "对称差集" , set1. symmetric_difference( set2) , set1^ set2)
'''字符串
字符串拥有驻留机制,普遍理解就是相同的字符串不会重复创建对象,而是在字符串池中进行调取
但是使用原生的交互窗口使用Python时,并不是所有相同的字符串都不重复创建,但是因为我们不用,就不去了解哪些情况重复创建了
一般我们开发Python都用PyCharm开发工具,这些开发工具会自动帮我们优化驻留
'''
str1 = "abcdefgabcdef"
str2 = '''abc'''
print ( str1. find( str2) )
print ( str1. rfind( 'h' ) )
print ( str1. upper( ) )
print ( str1. lower( ) )
print ( str2. center( 15 ) )
print ( str2. ljust( 15 , "$" ) )
print ( str2. zfill( 15 ) )
print ( "a b c" . split( ) )
print ( "a,b,c" . rsplit( "," , 1 ) )
print ( str1. isalpha( ) )
print ( "abcdef" . replace( "abc" , "aaa" ) )
print ( " " . join( [ "Hello" , 'word' ] ) )
print ( str2 is "abc" )
print ( "abcdef" [ 3 : ] )
print ( "abcdef" [ - 1 : : 1 ] )
print ( "我叫%s,今年%d岁" % ( "张三" , 45 ) )
print ( "我叫{0},今年{1}岁" . format ( "张三" , 45 ) )
print ( "我叫{name},今年{age}岁" . format ( name= "张三" , age= 45 ) )
print ( "%10d" % 45 )
print ( "%.3f" % 3.1415926 )
print ( "%10.3f" % 3.1415926 )
print ( "{0:.3}" . format ( 3.1415926 ) )
print ( "{0:.3f}" . format ( 3.1415926 ) )
print ( "{0:10.3f}" . format ( 3.1415926 ) )
print ( '天涯何处无芳草' . encode( encoding= "UTF-8" ) )
print ( '天涯何处无芳草' . encode( encoding= "UTF-8" ) . decode( encoding= "UTF-8" ) )
四、函数
'''函数
创建:
def 函数名([输入参数]):
函数体
[return 返回值]
调用函数
函数名([参数])
'''
def getTotal ( num1, num2) :
sum = num1 + num2
return sum
print ( getTotal( 1 , 2 ) )
print ( getTotal( num2= 10 , num1= 20 ) )
'''参数
个数可变的位置参数,使用*定义个数可变位置参数,结果为一个元组
def fun(*nums):
print(nums)
fun(5) # (5,)
fun(10,20,30,40) # (10,20,30,40)
个数可变的关键字参数,使用**定义,结果为字典
def fun(**args):
print(args)
fun(a=5) # {'a':5}
fun(a=10,b=20,c=30,d=40) #{'a':10,"b":20,"c":30,"d":40}
注意:
同一个函数中,只能同时存在一个位置参数和关键字参数
如果两种参数要同时出现,位置参数必须在关键字参数前面定义
fun(*args,**keys): √
fun(**keys,*agrs): ×
fun(*args1,*args2):×
fun(**key1,**key2):×
实参与形参
def fun(arg1,arg2): # 这里接收到的是形参
arg1+=1 # 这里改变了arg1的值,
arg2.append(10) # 这里追加了一个arg2列表的参数
print(arg1,arg2) # 11,[5,20,30,10]
n1 = 10
n2 = [5,20,30]
fun(n1,n2) # 这里传的是实参
print(n1,n2) # 10,[5,20,30,10]
可以看出,如果我们将可变序列,比如上面的n2列表传入函数,在函数中的更改,会影响到实际参数,n2,我们将这种传递方式称为传引用
如果我们传的是不可变参数,比如n1,那么函数中修改不会影响原来的值,这种叫传值
传引用,函数中修改会对实参也做更改
传值,仅仅将值传递,不会影响原来的对象
'''
''' 返回多值
多个值用return返回,用逗号分隔
返回结果为元组
'''
def fun1 ( ) :
return 10 , [ 1 , 2 , 3 , 4 ] , ( 5 , 6 , 7 , 8 ) , set ( { 1 , 2 , 3 , 4 } )
print ( fun1( ) )
'''默认值参数
def fun(a,b=10):
print(a,b)
fun(10) # 只传一个参数,b会采用默认值10
fun(10,20) # 传两个,就不用默认值了
'''
''' 局部变量
就是局部范围内定义的变量,比如函数内定义的变量
全局变量
就是全局都可以使用的变量,比如函数外定义的变量
global关键字可将局部变量声明为全局变量
'''
def fun2 ( ) :
global s
s = "我是使用global定义的局部变量,全局都可以使用我"
fun2( )
print ( s)
五、异常
'''异常
语法:
try:
可能出现异常的代码
except 异常类型1:
异常处理代码,报错后就会执行这里的代码
except 异常类型2:
异常处理代码
...
except 异常类型n:
处理代码n
except BaseException as e:
print(e)
else:
try没有抛异常执行的代码
finally:
无论有没有抛异常,都执行此块代码
常见异常类型:
BaseException: 是最大的异常类,所有异常都继承这个类,捕获它相当于捕获所有异常
IndexError: 索引越界异常
ZeroDivisionError:除数为0
KeyError:键值不存在
NameError:没有声明/没有初始化的对象
SyntaxError:语法错误
ValueError:传入无效参数
异常信息
import traceback # 引入此模块
try:
。。。
except XXX:
traceback.print_exc() # 打印异常
'''
六、类和对象
'''
创建类
class 类名:
a = 5 #成员变量,此变量可直接通过类名调用,也可以被所有类对象共享
#函数是类之外的def 总称,直接函数名调用即可,方法是类中的def,需要通过类的实例对象调用
# 构造方法,self相当于类对象当前的实例对象(就是我们new出来的每个类对象,都叫实例)
def __init__(self,name,age): # 构造方法必须传递self参数,剩下的随意
self.name = name # 相当于java中this,将参数name的值,赋值给当前类实例的name
self.age = age # 相当于java中this
# 成员方法
def info(self): # 成员方法必须传递self参数
print(self.name,self.age)
# 类方法
@classmethod
def cm(cls): # 类方法必须传递cls参数
print("类方法")
# 静态方法
@staticmethod
def sm(): # 静态方法没有必须传递的参数
print("静态方法")
创建类实例
实例名 = 类名()
# 通过实例名调用类中的成员变量
实例名.变量名
# 通过实例名调用成员方法
实例名.成员方法
'''
class Student :
name = "无名氏"
def __init__ ( self, name= "无名氏" , age= 0 ) :
self. name = name
self. age = age
def info ( self) :
print ( "我叫" , self. name, "今年" , self. age, "岁" )
@classmethod
def cm ( cls, age) :
print ( "类方法" , age)
@staticmethod
def sm ( age) :
print ( "静态方法" , age)
student1 = Student( )
student2 = Student( name= "张三" , age= 15 )
print ( student1. name, student2. name)
student1. info( )
student2. info( )
print ( Student. name)
Student. name = "通过类名直接修改类成员变量"
print ( Student. name)
print ( student2. name)
Student. cm( 15 )
Student. sm( 15 )
student1. gender = "女"
print ( student1. gender)
def show ( ) :
print ( "show方法" )
student1. show = show( )
student1. show
七、封装,继承,多态
''' 封装
私有化
_ 声明时前面加一个下划线,代表私有,for 包名 import * 禁止导入,类对象和子类可以访问,使用对象._变量名调用
__ 声明时前面加两个下划线,代表私有,避免与子类中的属性命名冲突,无法在外部直接访问,应使用对象._类名__变量名调用
__xx__:双前后下划线,用于定义类的魔法属性/模法方法,例如:__init__,__str__等,无法直接调用;
xx_:单后置下划线,用于避免与python关键字的冲突。
'''
class Student :
def __init__ ( self, name, age) :
self. __age = age
self. _name = name
def __show ( self) :
print ( self. __age, self. _name)
stu = Student( "张三" , 15 )
print ( dir ( stu) )
print ( stu. _name)
print ( stu. _Student__age)
stu. _Student__show( )
''' 继承
继承需要子类使用super()调用父类构造方法
另外如果想多继承,只需要 用逗号隔开即可
class Parent(A,B,C):
重写
重写只要让子类有一个与父类同名同参数的方法即可完成重写
'''
print ( "-------------------继承----------------------" )
class Parent ( object ) :
def __init__ ( self, name, age) :
self. name= name
self. age= age
def parentMethod ( self) :
print ( "父类方法" )
class Children ( Parent) :
def __init__ ( self, name, age, hobby) :
super ( ) . __init__( name, age)
self. hobby = hobby
def show ( self) :
print ( self. name, self. age, self. hobby)
def parentMethod ( self) :
super ( Children, self) . parentMethod( )
print ( "重写了parentMethod方法" )
children = Children( "张三" , 5 , "篮球" )
children. show( )
children. parentMethod( )
'''多态
就是不同的类,比如动物类,有eat方法
人类,eat方法吃杂食
狼,eat方法,吃肉
羊,eat方法,吃草
每个不同的对象,同样的方法具有不同的状态特征,称为多态
'''
'''特殊属性
__dict__ :获取类对象或实例对象所绑定的所有属性和方法的字典
__class__ :对象所属的类
__bases__ :当前类的父类(返回一个元组)
__mro__ :类的层次结构
'''
print ( children. __dict__)
'''特殊方法
__len__():通过重写__len__()方法,让内置函数len()的参数可以是自定义类型
__add__():通过重写__add__()方法,可使用自定义对象具有"+"功能
__new__():用于创建对象
__init__():对创建的对象进行初始化
__subclasses__():返回当前类的子类(返回元组)
'''
'''对象的浅拷贝与深拷贝
stu1 = Student()
stu2 = stu1
此时,stu1与stu2指向同一个对象引用
浅拷贝:
import copy
stu2 = copy.copy(stu1)
此时 进行浅拷贝,不指向同一个对象引用,就是将stu1的引用拷贝了一份,然后重新赋予id,赋值给stu2
就是,除了对象的id不一样,其它对象内部子对象指向还是相同的
深拷贝:
使用copy模块的deepcopy函数,递归拷贝对象中包含的子对象,源对象和拷贝对象所有的子对象也不相同
import copy
stu2 = copy.deepcopy(stu1)
此时,进行深拷贝,所有的对象引用,包括子对象,都不相同,重新在内存分配空间存储
'''
import copy
children2 = copy. copy( children)
print ( children, children2)
children3 = copy. deepcopy( children)
print ( children, children3)
八、模块和包
'''模块
一个.py文件就是一个模块
导入模块
import 模块名 [as 别名] # 引入整个模块
from 模块名 import 函数/变量/类 # 仅仅引入模块中特定内容,节省空间
注意:
当我们导入某个模块时,你导入的内容,会在导入的一刻,全部执行
除非你某些代码使用
if __name__ == '__main__':
这里的代码只有直接运行当前模块是才执行,为什么后面会讲解
'''
import math
print ( math. pi)
print ( dir ( math) )
from math import pi as PI
print ( PI)
'''以主程序模式运行
每个模块,都有一个变量__name__,程序会检测此变量,以确定它们在哪个模块中执行。
如果一个模块不是被导入到其他程序中执行,可能会在解释器的顶级模块中执行。
顶级模块的__name__变量值为__main__
就是类似java的主程序入口,main方法
语法:
if __name__ == '__main__':
....
何时运行
只有点击运行当前模块,此时此模块的__name__变量的值才是__main__
此时,里面的代码才会执行
而我们不是直接运行当前模块,那么这个模块中的__main__中代码就不会执行,因为__name__变量中的值不是__main__
'''
'''python中的包
包的概念
为了防止模块名冲突,将同名的模块,放在不同包下,起到区分的作用
包就是一个文件夹目录,里面放自己的模块
包与目录的区别
包是一个Python的概念,和目录功能一样,用于存放资源
但是包中会有一个__init__.py的文件,而普通目录中不会有此文件
包的引入
import 包名.模块名 [as 别名]
import 包名.* # 引入包中所有模块 [as 别名]
'''
'''常用内置模块
sys:python解释器及其环境操作相关的标准库
time:提供与时间相关的各种函数的标准库
os:提供了访问操作系统服务功能的标准库
calendar:提供与日期相关的各种函数的标准库
urllib:用于读取来自网上(服务器)的数据标准库
json:用于使用JSON序列化和反序列化对象
re:用于在字符串中执行正则表达式匹配和替换
math:提供标准算数运算函数的标准库
decimal:用于进行精确控制运算精度、有效数位和四舍五入操作的十进制运算
logging:提供了灵活的记录事件、错误、警告和条数信息等日志信息的功能
'''
'''第三方模块的安装与使用
安装
打开dos命令行,windows的cmd
pip install 模块名
使用
import 模块名
'''
九、文件读写
'''编码格式
Python文件默认编码格式是UTF-8
可以在模块文件第一行写
#encoding=gbk
来改变文件编码
gbk编码格式文件,所占字节会少
'''
'''文件读写
创建文件对象
可使用内置函数open()创建文件对象,使用Output输出流将内容写到文件,使用Input输入流将内容从文件拿到内存(当前程序中)
语法:
file = open(要创建或打开的文件路径,[打开模式(比如只读),编码格式(默认gbk)])
常用打开模式
r:以只读模式打开,文件指针在文件开头
w:只写,文件不存在创建,存在覆盖文件内容,指针在文件开头
a:追加,不存在创建(此时指针在开头),存在(指针在末尾,追加内容)
b:二进制方式打开,不能单独使用,需要配合其它模式,如rb,wb
+:读写方式打开,不可单独使用,需要配合其它模式使用,如a+
常用方法(注意,文件指针是针对字节来判断位置,不是文字个数)
read([size]):从文件中读取size个字节或字符的内容返回。若省略[size],则读取到文件末尾(所有内容)
readline():从文本文件中读取一行内容
readlines():从文本文件中每一个都作为一个独立的字符串对象,读取到一个列表中
write(str):将字符串str内容写入文件
writelines(s_list):将字符串列表写入文本文件,不添加换行符
seek(offset[,whence]):移动文件指针,offset为相对于whence的位置
offset:如果是一个正数,表示往结束方向移动,就是从左往右,如果是负数,就从后往前
whence:不同的值,不同含义
0:从文件头开始计算(默认)
1:从当前位置开始计算
2:从文件末尾开始计算
文件指针是一个位置,我们读取,写入都是根据这个位置来决定我们操作的内容在哪里
offset是相对于一个地方的偏移量,是移动指针的数值
whence是offset移动的依据,如果是0,那么offset=10就从文件开头移动10个位置
tell():返回文件指针当前的位置
flush():将缓冲区的内容写入文件,但不关闭文件
close():把缓冲区的内容写入文件,同时关闭文件,释放文件对象相关资源
'''
file = open ( r'D:/a.txt' , 'w' )
file . write( "我是写入的内容" )
file . close( )
'''with语句(上下文管理器)
with语句可以自动管理上下文资源,不论什么原因跳出with块,
都能确保文件正确的关闭,以此来达到释放资源的目的
语法
with open('logo.png','rb') [as src_file]:
src_file.read()
with:关键字
首先遵守上下文管理协议,实现了__enter__()方法和__exit__()方法
open('logo.png','rb'):上下文表达式结果为上下文管理器,同时创建运行时上下文(自动调用__enter__()方法,并将返回值赋值给as后面的上下文对象 src_file)
as src_file:可选项,上下文管理器对象的引用
最后,离开运行时上下文,自动调用上下文管理器特殊方法__exit__()
'''
''' 这是一个帮助你理解的例子
此类,实现了__enter__()和__exit__()这两个特殊方法
此类对象,遵循了上下文管理器协议
该类实例对象,称为上下文管理器
'''
class MyContentMgr ( object ) :
def __enter__ ( self) :
print ( "enter方法被调用执行了" )
return self
def __exit__ ( self, exc_type, exc_val, exc_tb) :
print ( "exit方法被调用执行了" )
def show ( self) :
print ( "调用show方法" )
with MyContentMgr( ) as myContnetMgr:
myContnetMgr. show( )
with open ( r"D:/a.txt" , "r" ) as file :
print ( file . read( ) )
'''目录操作
os模块,是Python内置模块
用来操作系统功能和文件系统相关的功能
该模块的语句执行结果通常与操作系统相关,不同系统操作,结果可能不一样
os模块,os.path模块用于对目录或文件进行操作
'''
import os
os. system( "notepad.exe" )
os. system( "calc.exe" )
os. startfile( r"D:\qq\Bin\QQScLauncher.exe" )
'''os模块常用操作目录的方法
getcwd():返回当前的工作目录
listdir(path):返回指定路径下的文件和目录信息
mkdir(path[,mode]):创建一个目录
makedirs(path1/path2...[,mode]):创建多级目录
rmdir(path):删除目录
removedirs(path1/path2......):删除多级目录
chdir(path):将path设置为当前工作目录
os.walk(top[, topdown=True[, οnerrοr=None[, followlinks=False]]]) 方法用于通过在目录树中游走输出在目录中的文件名,向上或者向下。
是一个简单易用的文件、目录遍历器,可以帮助我们高效的处理文件、目录方面的事情。
top -- 是你所要遍历的目录的地址, 返回的是一个三元组(root,dirs,files)。
root 所指的是当前正在遍历的这个文件夹的本身的地址
dirs 是一个 list ,内容是该文件夹中所有的目录的名字(不包括子目录)
files 同样是 list , 内容是该文件夹中所有的文件(不包括子目录)
topdown --可选,为 True,则优先遍历 top 目录,否则优先遍历 top 的子目录(默认为开启)。如果 topdown 参数为 True,walk 会遍历top文件夹,与top 文件夹中每一个子目录。
onerror -- 可选,需要一个 callable 对象,当 walk 需要异常时,会调用。
followlinks -- 可选,如果为 True,则会遍历目录下的快捷方式(linux 下是软连接 symbolic link )实际所指的目录(默认关闭),如果为 False,则优先遍历 top 的子目录。
'''
'''os.path模块操作目录相关方法
abspath(path):用于获取文件或目录的绝对路径
exists(path):用于判断文件或目录是否存在,如果存在返回True,否则返回False
join(path,filename):将目录与目录或文件名拼接起来
split(path):分离目录与文件名,返回元组
splitext(filename):分离文件名和扩展名,返回元组
basename(path):从一个目录中提取文件名
dirname(path):从一个路径中提取文件路径,不包括文件名
isdir(path):用于判断路径是否是目录
'''
import os. path
print ( os. path. abspath( r"D:/a.txt" ) )
十、操作Excel
注意:需要先安装微软的Office软件(Excel),WPS之类的,很多库都无法操作从而报错
B站有很多免费安装激活微软的Office的教程
1、xlwings库
对于.xls文件只支持读操作,但支持.xlsx读和写操作 安装
pip install xlwings
pip uninstall xlwings
pip install pywin32
先选中后操作
新建:创建一个不存在的工作蒲或工作表 打开:打开一个已经存在的工作蒲 引用:指明要操作的对象,例如有A、B、C三个工作蒲,想要操作A就得先引用A 激活:我们可以同时打开多个工作蒲,但同一时间只能操作一个,当前操作的工作蒲称为当前活动工作蒲
层级关系
App:每个App代表一个Excel程序,多个Excel程序集合用Apps来表示 Book:代表单个工作蒲,工作蒲集合用Books表示 Sheet:代表单个工作表,工作表集合用Sheets表示 Range:代表一个单元格或一片单元格区域
测试
import xlwings as xw
with xw. App( visible= True , add_book= False ) as app:
book = app. books. add( ) ;
sht = book. sheets. add( 'sheetTest1' ) ;
sht. range ( 'A1' ) . value = 'Hello' ;
book. save( './excel/test.xlsx' ) ;
1.1 基础操作
每个app代表一个excel程序(未创建工作蒲),apps可管理所有app实例,每个app实例都是独立的,有独属于自己的pid
import xlwings as xw
app1 = xw. App( ) ;
app2 = xw. App( ) ;
app1Pid = app1. pid;
app2Pid = app2. pid;
print ( 'app1Pid:' , app1Pid, 'app2Pid:' , app2Pid) ;
apps = xw. apps
print ( 'apps中有' , apps. count, '个App' )
app1. kill( )
app2. kill( )
通过app实例创建工作蒲book,然后通过book创建工作表sheet,然后通过sheet操作单元格或单元格区域range
import xlwings as xw
app1 = xw. App( ) ;
app1Pid = app1. pid;
print ( 'app1Pid:' , app1Pid) ;
'''1.apps对象操作指定app'''
app1 = xw. apps[ app1Pid]
print ( 'app1Pid:' , app1Pid, '和apps[pid]获取的app对象的Pid值相同,apps[pid].pid:' , app1. pid) ;
'''2.想要操作app,必须引用,相当于用鼠标选择要操作的excel程序(假设你有3个excel程序,你必须告诉它你要操作哪一个)'''
app1. activate( )
'''3.建立工作蒲,工作表,操作单元格'''
app1_book1 = app1. books. add( ) ;
app1_book1_sht1 = app1_book1. sheets[ 'Sheet1' ]
app1_book1_sht1. range ( 'A1' ) . value = '测试1'
app1_book1. save( '../excel/测试1.xlsx' ) ;
'''4.没有使用with语句的话,需要手动关'''
app1_book1. close( )
app1. kill( )
可以直接操作Book而不需要人为控制App实例来操作Book(它们封装了操作App的步骤,我们不需要手动操作)
import xlwings as xw
'''
一、创建Book对象
1.创建一个新的App并在App中新建一个Book。
1.1 xw.Book()
1.2 xw.Book('Book1') #创建并指定名称
1.3 xw.Book(r'C:/path/to/file.xlsx') # 指定路径,否则会在.py文件同级目录创建
2.在当前App下新建Book
2.1 xw.books.add()
2.2 xw.books['Book1']
2.3 xw.books.open(r'C:/path/to/file.xlsx')
二、打开已存在的Book(下面两种方法皆可)
book1 = app.books.open('excel文件的绝对或相对路径')
book1 = xw.Book('excel文件的绝对或相对路径')
'''
book1 = xw. Book( '../excel/测试1.xlsx' )
book1. activate( steal_focus= True )
sheet1 = book1. sheets[ 'Sheet1' ]
sheet1. range ( 'B2' ) . value = '打开已存在的Book'
book1. save( ) ;
book1. close( ) ;
book2 = xw. Book( )
sheet2 = book2. sheets[ 'Sheet1' ]
sheet2. range ( 'B2' ) . value = '覆盖已存在的Book'
book2. save( '../excel/test.xlsx' ) ;
book2. close( ) ;
app = xw. App( visible= True , add_book= False )
app. display_alerts = False
app. screen_updating = False
book3 = app. books. open ( '../excel/test.xlsx' )
book3. save( )
book3. close( ) ;
app. quit( ) ;
Sheet的创建和使用
import xlwings as xw
'''
一、创建Sheet对象
sheet = book.sheets.add() # 直接添加一个sheet到当前工作蒲book,添加到最前面
sheet = book.sheets.add('test',after = 'sheet2') #指定名称和插入位置:添加一个名称为test的sheet 到 sheet2后面
二、引用Sheet(获取已存在sheet对象)
sheet = book.sheets['sheet1'] # 按名称获取工作表
sheet = book.sheets('sheet1') # 等价于book.sheets['sheet1']
sheet = book.sheets(1) # 按照序号获取工作表
sheet = book.sheets.active # 获取当前活动工作表
三、常用操作
sheet1.clear() # 清除工作表所有内容和格式
sheet1.clear_contents() # 清除内容但保留格式
sheet1.delete() # 删除这个工作表
sheet1.autofit('c') # 自动调整行高列宽
sheet1.select() # 在活动工作蒲中选择
四、常用属性
sheet1.name # 工作表名字
sheet1.cells # 工作表所有单元格,返回一个Range实例
sheet1.index # 工作表索引
'''
app = xw. App( visible= True , add_book= False )
app. display_alerts = False
app. screen_updating = False
book1 = app. books. add( )
'''工作表创建'''
book1. sheets. add( '工作表1' )
book1. sheets. add( '工作表2' , after = '工作表1' )
book1. sheets. add( '工作表1.5' , before = '工作表2' )
'''引用工作表进行操作'''
sheet1 = book1. sheets( 1 )
sheet1. clear( )
sheet1. clear_contents( )
sheet1. range ( 'A1' , 'C1' ) . value = 'alkdjflksadjlfkjsadlfjdslkf'
sheet1. autofit( 'c' )
sheet1. select( )
print ( sheet1. name, sheet1. cells, sheet1. index)
book1. save( '../excel/test3.xlsx' )
book1. close( )
app. quit( )