一个py文件就是一个模块,如果想让自己的py文件可以作为模块导入,模块名字必须遵循命名规则
import 模块名
==> 直接导入一个模块from 模块名import 函数名
==> 导入一个模块里的方法或变量form 模块名 import *
==> 导入这个模块里的””所有””方法和变量import 模块名 as 别名
==> 给模块起个别名from 模块名 import 函数名 as 别名
==> 给模块的函数起个别名
os模块: operating system,用来调用操作系统里的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14#路径分隔符 os.sep
'\\'
#获取当前路径 os.getcwd()
'C:\\Users\\fanxi\\AppData\\Local\\Programs\\Python\\Python37'
'../')#切换路径,这里的../代表返回上层文件夹 os.chdir(
os.getcwd()
'C:\\Users\\fanxi\\AppData\\Local\\Programs\\Python'
#列出当前路径所有文件和文件夹 os.listdir()
['Python37']
'1010.02.02.jpg' s=
#获取文件后缀,类似s.rpartition('.') os.path.splitext(s)
('1010.02.02', '.jpg')sys模块
1
2
3
4
5
6
7
import sys
print("fg")
sys.exit() #退出,不执行后续代码
print('kjhg')
fg1
2#导入包的时候就从以下任意路径里查找 sys.path
['C:/Users/fanxi/Desktop/Python笔试', 'C:\\Users\\fanxi\\AppData\\Local\\Programs\\Python\\Python37\\Lib\\idlelib', 'C:\\Users\\fanxi\\AppData\\Local\\Programs\\Python\\Python37\\python37.zip', 'C:\\Users\\fanxi\\AppData\\Local\\Programs\\Python\\Python37\\DLLs', 'C:\\Users\\fanxi\\AppData\\Local\\Programs\\Python\\Python37\\lib', 'C:\\Users\\fanxi\\AppData\\Local\\Programs\\Python\\Python37', 'C:\\Users\\fanxi\\AppData\\Local\\Programs\\Python\\Python37\\lib\\site-packages']1
#接受用户的输入,和input相关,与文件操作有关 sys.stdin
1
>>>sys.stdout #修改stdout,可以改变默认的输出位置,与文件操作有关
1
>>>sys.stderr#修改错误信息打印位置,比如打印到文件里面
math模块
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17import math
12.98)#向下取整 math.floor(
12
12.98)#向上取整 math.ceil(
13
3)#阶乘 math.factorial(
6
12.345) #内置函数,四舍五入 round(
12
12.567) round(
13
6) #弧度,pi=180°,sin(30°) math.sin(math.pi/
0.49999999999999994
3)#cos(60°) math.cos(math.pi/
0.5000000000000001
2) #其实是无限大!!! math.tan(math.pi/
1.633123935319537e+16random模块
1 | >>> import random |
datetime模块
1
2
3
4
5
6
7
8
9import datetime as dt
#获取当前时间 dt.datetime.now()
datetime.datetime(2020, 5, 29, 11, 6, 23, 888832)
2020,2,6)#创建日期 dt.date(
datetime.date(2020, 2, 6)
1,1,1)#创建时间 dt.time(
datetime.time(1, 1, 1)
3)#计算3天以后的时间 dt.datetime.now()+dt.timedelta(
datetime.datetime(2020, 6, 1, 11, 8, 19, 483467)time模块
1
2
3
4
5import time
#获取时间戳 time.time()
1590721802.861923
"%Y-%m-%d %H:%M:%S")#按照指定格式输出 time.strftime(
'2020-05-29 11:20:43'calendar模块
1
2
3
4
5
6
7import calendar
2020)#查看2020年的日历 calendar.calendar(
2020)#查看是否为闰年 calendar.isleap(
True
1996,2020)#从1996到2020共几个闰年 calendar.leapdays(
6
2020,5)#查看2020年5月的日历 calendar.month(hashlib和hmac模块:加密
uuid模模块:随机生成一个全局唯一的id
以下划线开头的变量或方法名,不推荐被调用。通常在模块的末尾用del删除这些组成的元组,以防止被调用
__name__
:当直接运行py文件时,为__main__
;当作为模块被导入时,为导入该模块的py文件名。通过使用
if __name__=='__main__'
,保证只有当直接运行这个代码文件时才执行,而被逼的文件导入运行时不运行一个包==多个模块(py文件)
面向对象
约定类名首字母大写,如Student
object可省略
1
2class 类名(object):
pass一个小栗子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28class Student(object):
#在__init__方法里,以参数形式定义特征,称之为属性
def __init__(self,name,age,height):
self.name=name
self.age=age
self.height=height
#行为定义为一个个的函数
def run(self):
print("正在跑步")
def eat(self):
print("正在吃东西")
#使用Student类创建两个实例对象s1,s2
#s1和s2都有name,age,height属性,同时都有run和eat方法
s1=Student('小明',18,12)#Student会自动调用__init__方法
s2=Student('小狗',12,12)
#根据逻辑,让不同的对象执行不同的行为
print("%s"%s1.name,end='')
s1.run()
print("%s"%s1.name,end='')
s1.eat()
print("%s"%s2.name,end='')
s2.eat()1
2
3小明正在跑步
小明正在吃东西
小狗正在吃东西self
1
2
3
4
5
6class Student(object):
def __init__(self,x,y):
self.name=x
self.age=y
s1=Student('fhs',12)s1=Student('fhs',12)
做了以下3件事情:#1.调用`__new__`方法,申请一段内存空间 #2.调用`__init__`方法,并让self指向申请好的那段内存空间 #3.让`s1`也指向申请好的哪那段内存空间
动态属性
实例化的对象,若直接使用等号给一个属性赋值:
- if 以前存在,则更新
- if 不存在,则添加一个新的属性
使用
__slots__
属性直接定义在类里,是一个元组,用来规定可以存在的属性1
2
3
4
5
6
7
8
9class Student(object):
__slots__=('age',)
def __init__(self,x,y):
self.name=x
self.age=y
s1=Student('fhs',12)
print(s1.age,s1.name)1
2
3
4
5
6Traceback (most recent call last):
File "C:/Users/fanxi/Desktop/Python笔试/self.py", line 8, in <module>
s1=Student('fhs',12)
File "C:/Users/fanxi/Desktop/Python笔试/self.py", line 4, in __init__
self.name=x
AttributeError: 'Student' object has no attribute 'name'因为
__slots__
元组里面只有age,只要再把name添加进就好了1
2
3
4
5
6
7
8class Student(object):
__slots__=('age','name')
def __init__(self,x,y):
self.name=x
self.age=y
s1=Student('fhs',12)
print(s1.age,s1.name)1
12 fhs
魔法方法
不需要手动调用,会在合适的时候自动调用
这些方法,都是用
__
开始,都使用__
结束方法名都是系统规定好的,在合适的时机自己调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14class Student(object):
#在创建对象时,会自动调用init方法
def __init__(self,x,y):
print('__init__方法被调用了')
self.name=x
self.age=y
def __del__(self):
#当对象被销毁时,会自动调用这个方法
print('__del__方法被调用了')
s1=Student('fhs',12)
import time
time.sleep(4)
del s11
2
3
4
5
6
7
8
9
10
11
12class Student(object):
#在创建对象时,会自动调用init方法
def __init__(self,x,y):
print('__init__方法被调用了')
self.name=x
self.age=y
def __del__(self):
#当对象被销毁时,会自动调用这个方法
print('__del__方法被调用了')
s1=Student('fhs',12)
print(s1)#直接打印一个对象,是文件的__name__.类型,内存地址1
2__init__方法被调用了
<__main__.Student object at 0x000002B0ECD20708>当打印一个对象时,会调用这个对象的
__str__
或者__repr__
方法
如果两个方法都写了,选择__str__
所以可以通过修改
__str__
或者__repr__
方法来达到打印我们想打印的对象的目的1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18class Student(object):
#在创建对象时,会自动调用init方法
def __init__(self,x,y):
print('__init__方法被调用了')
self.name=x
self.age=y
def __del__(self):
#当对象被销毁时,会自动调用这个方法
print('__del__方法被调用了')
def __str__(self):
return 'hello'
def __repr(self):
return 'good'
s1=Student('fhs',12)
print(s1)1
2__init__方法被调用了
hello#默认打印__str__方法区分:str更注重可读性,repr更注重准确性
__call__
方法
1 | class Student(object): |
运算符相关的魔法方法
1
2
3
4
5
6
7
8
9
10
11
12
13class Person(object):
#在创建对象时,会自动调用init方法
def __init__(self,name,age):
self.name=name
self.age=age
p1=Person('fhs',12)
p2=Person('fhs',12)
#p1和p2不是一个对象!因为指向了不同的内存空间
print(p1 is p2)
>>>False==
会调用对象的__eq__
方法__eq__
方法默认比较的是内存地址1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16class Person(object):
#在创建对象时,会自动调用init方法
def __init__(self,name,age):
self.name=name
self.age=age
p1=Person('fhs',12)
p2=Person('fhs',12)
a=[1,2]
b=[1,2]
print(a==b)
print(p1 == p2)
>>>True
>>>False可以重写
__eq__
方法来实现:只要两个对象对应属性的值相等,就输出True1
2
3
4
5
6
7
8
9
10
11
12
13
14
15class Person(object):
#在创建对象时,会自动调用init方法
def __init__(self,name,age):
self.name=name
self.age=age
def __eq__(self,other):
if self.name==other.name and self.age==other.age:
return True
else:
return False
p1=Person('fhs',12)
p2=Person('fhs',12)
print(p1 == p2)
>>>True1
2
3
4
5
6
7
8
9
10'a' c=
-32 c
Traceback (most recent call last):
File "<pyshell#8>", line 1, in <module>
c-32
TypeError: unsupported operand type(s) for -: 'str' and 'int'
-32 ord(c)
65
-32) chr(ord(c)
'A'面向对象的一个例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38class House(object):
def __init__(self,house_type,total_area,fru_list=None):
if fru_list is None:
fru_list=[]
self.house_type=house_type
self.total_area=total_area
self.free_area=total_area*0.6
self.fru_list=fru_list
def add_fru(self,x):
if self.free_area<x.area:
print("房子剩余面积不足,放不进去了")
else:
self.fru_list.append(x.name)
self.free_area-=x.area
def __str__(self):
return '户型={},总面积={},剩余面积={},家具列表={}'.format(self.house_type,self.total_area,self.free_area,self.fru_list)
#第一步:首先造一个房子出来
house=House('两室一厅',56)
class Furniture(object):
def __init__(self,name,area):
self.name=name
self.area=area
#第二步:然后造一堆家具出来
bed=Furniture('西蒙斯',4)
chest=Furniture('衣柜',2)
table=Furniture('餐桌',1.5)
#第三步:把家具添加到房子里
house.add_fru(bed)
house.add_fru(chest)
house.add_fru(table)
print(house)#打印str or repr的返回值
print(house.__str__())#两者效果相同,因为本质上print
!=
默认调用__ne__
方法>
调用__gt__
方法>=
调用__ge__
方法:不写ge方法会报错
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19class Person(object):
"""
这是一个人
"""
def __init__(self,name,age):
self.name=name
self.age=age
def eat(self):
print(self.name+'正在吃东西')
p=Person('zhangsan ',18)
print(dir(p)) #查看所有属性/方法
print(p.__class__)
print(p.__dict__)#把对象名和值转换成一个字典
print(p.__doc__)#查看文档1
2
3
4
5['__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__', 'age', 'eat', 'name']
<class '__main__.Person'>
{'name': 'zhangsan ', 'age': 18}
这是一个人1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25class Person(object):
"""
这是一个人
"""
def __init__(self,name,age):
self.name=name
self.age=age
def __setitem__(self,key,value):
self.__dict__[key]=value
def __getitem__(self,item):
return self.__dict__[item]
p=Person('fhs',12)
print(p.__dict__)#将对象转换为字典
#不能直接把一个对象当作一个字典来使用
p['age']=20 #[]会调用对象的__setitem__方法
p['name']='you'
print(p.name,p.age)
print(p['name'])#会调用对象的__getitem__方法1
2
3{'name': 'fhs', 'age': 12}
you 20
you私有属性:以
__
开头,比如__money
私有方法:以
__
开头,比如__eat()
访问私有属性/方法的方法:
1
2
3
4
5
6
7
8
9
10
11
12
13class Person(object):
def __init__(self,name,age):
self.name=name
self.age=age
self.__money=1000
def get_money(self):
return self.__money
def __eat(self):
print("吃ing")
return 0
def get_eat(self):
return self.__eat()
p=Person('fhs',10)
1 | #方法1. |
1 | 1000 |
类属性和对象属性
类属性:定义在类之内,函数之外
类对象和实例对象都可以获取类属性,但只有类对象才可以修改类属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15class Person(object):
type='human'
def __init__(self,name,age):
self.name=name
self.age=age
self.__money=1000
p=Person('fhs',10)
print(Person.type)
print(p.type)
#修改
Person.type='人类'
print(p.type)实例对象可以直接用
.
来调用方法,不用传入self而类对象调用方法时,需要指定self
1
2
3
4
5
6
7
8
9
10
11
12
13
14class Person(object):
def __init__(self,name,age):
self.name=name
self.age=age
def eat(self,food):
print(self.name+'正在吃'+food)
p1=Person('zhangsan ',18)
p2=Person('lisi',19)
p1.eat('zz')
Person.eat(p2,'hh')1
2zhangsan 正在吃zz
lisi正在吃hh但是对于静态方法(不需要self传参的方法),不管是实例对象还是类在调用方法时都是一样的操作
1
2
3
4
5
6
7
8
9class Cal(object):
def add(a,b):
print(a+b)
#对于静态方法,可以不实例化一个对象,而是可以直接调用
Cal.add(1,2)
>>>3还有一种叫做类方法(如果一个函数只用到了类属性)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16class Cal(object):
type='human'#定义一个类属性
def __init__(self,x,y):
self.x=x
self.y=y
def test(cls):
#自动传参
#cls指的是类对象 cls is Cal ==> True
print(cls.type)
print('yes')
p=Cal(1,2)
#类方法可以使用实例对象和类对象调用
print(p.test())
print(Cal.test())1
2
3
4
5
6human
yes
None
human
yes
None总结实例方法,静态方法和类方法
单例设计模式
面向对象的三大特性
封装,继承,多态
继承的使用:子类先调用父类的init方法(如果子类没有重写init),然后调用父类的某些方法
父类的私有属性不能被子类继承
isinstance&issubclass
子类重写父类的方法
如果子类想增加父类没有的属性,可以直接添加
如果父类有,但子类想要补充,可以重写init方法,但也有以下方法:
1. super直接调用父类的方法 2. 父类名.方法名(self,参数列表)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20class Person(object):
def __init__(self,name,age):
self.name=name
self.age=age
#Stu继承自Person类
class Stu(Person):
#添加父类没有的方法
def eat(self,food):
print(self.name+"在吃"+food)
#补充父类没有的属性
def __init__(self,name,age,school):
#方法1
#Person.__init__(self,name,age)
#方法2
#super(Stu,self).__init__(name,age)
self.school=school
p=Stu('fhs',12,'ls')
p.eat('fish')
>>>fhs在吃fish多态是基于继承,通过子类重新写父类的方法,得到不同的结果,以提高代码的灵活度
不使用多态的代码有冗余,就像这样
而使用多态优化后的代码是这样子的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26class Dog(object):
def work(self):
print('狗在工作')
class PoliceDog(Dog):
def work(self):
print("警犬正在工作")
class BlindDog(Dog):
def work(self):
print("导盲犬正在工作")
class DrugDog(Dog):
def work(self):
print("缉毒犬正在工作")
class Person(object):
def __init__(self,name):
self.name=name
def work_with_dog(self,dog):
dog.work()
p=Person('fhs')
pd=PoliceDog()
#p.dog=pd
p.work_with_dog(pd)或者
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26class Dog(object):
def work(self):
print('狗在工作')
class PoliceDog(Dog):
def work(self):
print("警犬正在工作")
class BlindDog(Dog):
def work(self):
print("导盲犬正在工作")
class DrugDog(Dog):
def work(self):
print("缉毒犬正在工作")
class Person(object):
def __init__(self,name):
self.name=name
def work_with_dog(self):
self.dog.work()
p=Person('fhs')
pd=PoliceDog()
p.dog=pd
p.work_with_dog()1
警犬正在工作
文件
内置函数open可以打开文件
在windows中,文件夹之间用
\
分隔路径,而\
常用作转义字符,所以在windows中,使用Python中写路径时用\\
分隔路径而linux用的
/
分隔windows默认编码方式为
gbk
../
表示返回上一级文件夹,./
可以省略不写,表示当前文件夹
文件的打开方式mode:
r:只读,若文件不存在,则报错
w:写入模式,不能读,若文件不存在,会创建之
b:以二进制的形式打开文件,用来操作非文本文件
rb:以二进制方式读取文件
wb:以二进制方式写入文件
a:追加模式,会在最后追加内容,若文件不存在,则创建之
文件的读取方式
file.read():一次读取整个文件
file.readline() :一次读取一行(一个换行符之前的代表一行)
file.readlines() :读取所有行的数据,保存在列表里
file.read(10):10指的是读取的字符个数
json
dumps:将数据转换成json字符串,不会将数据保存在文件里
dump:将数据转换成json字符串,同时写入文件
loads:将json字符串加载为Python里的数据
load:读取文件,把读取的内容加载成为Python里的数据
非以上对应格式在使用json时会报错
pickle
dumps:将数据转换成二进制,不会将数据保存在文件里
dump:将数据转换成二进制,同时写入文件
loads:将二进制加载为Python里的数据
load:读取文件,把读取的二进制内容加载成为Python里的数据
json和pickle的对比
pickle用来将数据原封不动的转换成为二进制,但这个二进制,只能Python识别,不能跨平台
json只能保存一些基本信息,作用是用来在不同平台里传递数据
异常
1
2
3
4
5
6
7
8
9
10age=input("几岁啦?")
try:
age=float(age)
except ValueError as e:
print('输入的非数字')
else:
if age>18:
print('欢迎')
else:
print('滚')1
2
3
4
5
6
7几岁啦?13.6
滚
================ RESTART: ================
几岁啦?123.6
欢迎
>>>1
2
3
4try:
pass
finally:#finally一定会执行
pass
注意,finally的return值会覆盖前面的
1 |
|
with
1
2
3
4
5
6
7
8
9
10
11try:
file=open('xx.txt','r')
except FileNotFoundError:
print('文件不存在')
else:
try:
file.read()
finally: #有可能读到一半就不读了,所以最后要关闭文
file.close()
文件不存在
>>>使用with之后,不需要手动关闭文件
1
2
3
4
5
6
7
8try:
with open('xx.txt','r') as file:
file.read()
#file.close#不需要手动关闭了
except FileNotFoundError:
print('文件未找到')
文件未找到
>>>with语句后面的结果对象,需要重写
__enter__
和__exit__
方法当进入到with代码块时,会自动调用
__enter__
方法里的代码当with代码块执行完成以后,会自动调用
__exit__
方法系统内置异常
自定义异常
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#自定义异常
class LengthError(Exception):
def __init__(self,x,y):
self.x=x
self.y=y
#自定义异常输出
def __str__(self):
return '长度必须在{}和{}之间'.format(self.x,self.y)
password=input('请输入密码')
m,n=6,12
if m<=len(password)<=n:
print('密码正确')
else:
raise LengthError(m,n)
#若没出错
print('将数据保存到数据库中')可迭代对象和不可迭代对象的区别就在于,类中是否写了
__iter__
方法可以用
isinstance
方法判断一个实例对象是否是由指定的类创建出来的1
2
3
4from collections.abc import Iterable
1,2,3] s=[
isinstance(s,Iterable)
True