一、Python背景介绍
Python是一种面向对象的编程语言,由吉多·范罗苏姆开发,1991年发布,它常被昵称为胶水语言,能够把其他语言之作的各种模板连接在一起
1.Python解释器
- Cpython
- PyPy
- Jython
2.Python的优点
- 简单易学
- 第三方库很丰富
- 可移植
- 既面向过程又面向对象
3.Python的缺点
- C语言是编译型语言,Python是解释型语言
- 代码不能加密
- 强制缩进
- GIL全局解释器锁
4.Python就业方向
- Web后台开发
- 爬虫开发
- 数据分析
- 运维开发
- 机器学习
- 人工智能
二、基本语法
1.流程控制
1.if语句
score = int(input("请输入您的成绩:"))
if score < 60: # python中无需括号,但是要注意一定要有冒号
print("成绩不合格") # python中"和'一样
pass
elif score < 70: # python中没有switch函数
print("成绩合格")
pass
elif score < 90:
print("成绩不错")
pass
else: # else为可选条件
print("成绩优秀")
pass
# if语句单行写法(相当于java中的?:)
c = a if a>b else b
2.while语句
- 必须有初始值
- 需要条件表达式
- 需要终止条件
# 打印等腰三角形
row = 1
while row <= 5: # 条件表达式
j = 1
while j < = 5-row:
print("")
j+=1
pass
k = 1
while k < = 2*row - 1:
print("*")
k+=1
pass
print()
row+=1
pass
3.for循环
- range(起始,结束,步长),步长不能为0,其中结束为开区间
- break表示退出当前循环
- continue表示跳过此次循环
# 简单的加法
sum = 0
for item in range(1,51): # item是一个临时变量
if sum > 100:
print("循环执行到%d就退出来了"%item)
break
pass
sum += item
pass
print("sum=%d"%sum)
2.高级数据类型
1.字符串(str)
1.常用方法
# 1.首字母转换为大写
name.capitalize();
# 2.查看对象内存地址
id(name)
# 3.检查对象是否以x结束/开始,输出为布尔值
name.endswith("p")
name.startswith("p")
# 4.返回查找的第一个索引的值,没找到返回-1
name.find("e")
# 5.判断是否为全小写
name.islower()
# 6.字符串全部大小写转换
name.lower()
name.upper()
# 7.大写变小写,小写变大写
name.swapcase()
# 8.把每个单词的首字母变成大写
name.title()
# 9.统计出现的次数
name.count()
# 10.切片操作
name[start:end] # 相当于substring,不包括end
name[start:] # 表示从start索引开始到最后
name[:end] # 表示从开始到end
name[::-1] # 倒序输出
# 11.替换字符
name.place(old,new,count = None) # old表示就字符,new为替换字符串,count为替换个数,None表示全部替换
2.列表(list)
- list是一种有序的集合,可以随时添加和删除其中的元素
- 列表的下表取值/切片/是否越界与字符串一致,区别就是列表获取元素
1.常用方法
# 1.定义列表
list = ["peter", 26, "school", "python engineer"] # 主义为中括号
# 2.修改数据
list[0] = "faker" # 括号内为索引值
# 3.删除元素
del list[0] # 单个删除
del list[1:3] # 批量删除,与基本切片操作语法一样
# 4.remove()
list.remove("peter") # 移除具体的元素,如果元素不存在会报错,如果有多个该元素只会删除第一个
# 5.pop()
list.pop(1) # 移除指定项,参数是索引值,如果不填参数,则删除最后一个元素
# 6.index()
list.index() # 获取指定的元素的索引值,如果有多个相同元素,则返回第一个的索引值
# 7.insert()
list.insert(1,"ss") # 在索引值之前插入元素
# 8.append()
list.append("ss") # 在列表后面追加元素
# 9.count()
list.count(26) # 统计某元素出现的次数
# 10.extend()
list.extend([1,2,3,4]) # 扩展,相当于批量添加,注意添加的元素必须为列表,区分与append的区别
# 11.遍历list
for item in list:
print(item)
3.元组(tuple)
- 不可变
- 内部元素可以是任何类型(包括list类型)
- 除了不能修改,其他的搜索方法均可适用
1.常用方法
# 1.创建元组
tuple = (1,) # 单个元素需要加,
cre_tuple = (("1","2","3")) # 注意双括号
tuple = ("peter",26,"school",[1,2,3,4]) # 用()创建元组
# 2.更改元组中的列表元素
tuple[3][0] = 10 # 元组类型不能改变,但其中的列表类型可以修改
# 3.转换为列表
tes_list = list(cre_tuple)
4.字典(dict)
- 以键值对的形式创建
- 键不能重复,且只能是不可变的类型,如数字,字符串和元组,但值可以重复
- 通常用键来访问数据,支持增删改查
- 不是序列类型,没有索引的概念,是一个无序的键值集合
1.常用方法
# 1.定义字典
dict = {"fff":"string",12:(1,2,3)} # 适用{}定义字典
dic = dict() # 用dict()定义
# 2.添加
dict["name"] = "peter"
dict["age"] = 26
# 3.len
len(dict) #字典的键值对数
# 4.修改
dict["name"] = "peter" # 可以直接通过键修改
dict.update({"age":26}) # 添加或更新
# 5.keys()
dict.keys() # 获取所有键
# 6.values()
dict.values() # 获取所有值
# 7.遍历
for i,j in dict:
# 8.查找元素
dict["name"] # 这种方式如果找不到对应的key,会报一个KeyError错误
dict.get("name") # 这种方式不会引发KeyError,会返回一个默认值(None)
dict.get("name", "找不到名称") # 返回一个默认值“找不到名称”
dict.setdefault("name", "找不到名称") # 该方法同get
5.集合(set)
- 无序且不重复的元素集合
- 不支持索引和切片,因为是无序的
1.常用方法
# 1.创建集合
set1 = ["1","2"]
# 2.类型转换
list1 = [1,5,4]
set1 = set(list1)
# 3.添加元素
set1.add("python")
# 4.清空集合
set1.clear()
# 5.移除指定数据
set1.discard("1")
6.公用方法
1.合并操作(+)
- 列表、字符串、元组都能合并,但不适用于字典
strA = "hello"
strB = "world"
strC = strA + strB
2.复制操作(*)
strB = strB * 3
3.判断对象是否存在(in)
"A" in strA
4.排序方法(sorted)
sorted([1,2,3,5,6,9], reverse=True)
5.范围函数(range)
range(start,stop,step) # 不包含stop
6.打包函数(zip)
- 函数用于将可迭代对象作为参数,将对象中对应的元素打包成一个个元组,然后返回这些元组组成的列表
- 如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同
a = zip([1,2,3],['a','b','c'])
7.枚举函数(enumerate)
- 该函数用于将一个可遍历的数据对象组合成一个索引序列,同时列出数据和数据下标,一般用于for循环
- 默认从0开始计数
# 列表索引
list = ["o","b","j"]
for index,i in enumerate(list):
print(index,i)
# 字典索引
dict = {"name":"周杰伦","hobby":"唱歌","pro":"艺术"}
for i in enumerate(dict):
print(i) # 只对键进行索引
3.常用函数
1.print()
print(a)
2.type()
# 查看变量a的数据类型
type(a)
4.各类运算符
1.算术运算符
算术运算符 | 功能 |
---|---|
+ | 加 |
- | 减 |
* | 乘 |
/ | 除 |
% | 取余 |
// | 地板除,相除取整 |
** | 指数,左底右幂 |
2.逻辑运算符
优先级:()>not>and>or
- or
- and
- not
3.运算函数
# 1.求绝对值
abs(num)
# 2.四舍五入
round(1.232,2) # 后面的参数表示保留几位小数
# 3.求最大值
max(num)
# 4.求最小值
min(num)
# 5.求和
sum(a+b)
# 6.执行字符串表达式
eval("a+b+c")
5.字符串输入输出
1.输入
# input
name = input("请输入您的姓名:") # input获取的所有类型都是str类型的
a = int(input()) # 转换类型
2.输出
1.格式化输出符号
格式化输出符号 | 对应类型 |
---|---|
%c | 字符 |
%s | 字符串 |
%i | 有符号十进制整数 |
%d | 有符号十进制整数 |
%u | 无符号十进制整数 |
%o | 八进制整数 |
%x | 十六进制整数 |
%e | 索引符号 |
%E | 索引符号 |
%f | 浮点实数 |
%g | %f和%e的简写 |
%G | %f和%E的简写 |
name = "peter"
age = 26
print("我的名字是%s,今年%d"%(name,age))
2.格式化输出
# format
print("姓名:{}".format(name))
print("QQ:{}".format(QQ)) # 不需要指定数据类型
6.定义函数
1.定义参数
# 1.定义函数
def printInfo(n):
'''
这个函数用来打印信息
param n:打印次数
return:返回信息
'''
print("hello\n"*n)
pass
# 2.必选函数
def sum(a,b): # a,b为必选参数,不能省略
sum = a+b
pass
# 3.默认参数(缺省参数)
def sum(a,b = 30): # b为默认参数,默认参数必须放在参数列表最后面
sum = a+b
pass
# 4.可变参数
def getComputer(*args): # *定义可变参数,args为元组类型
result = 0;
for i in args:
result+=i
pass
pass
# 5.关键字可变参数(必须放到可选参数之后)
def keyFunc(**kwargs): # 用**来定义参数,参数关键字是一个字典类型,key是一个字符串
pass
# 6.返回值
'''
如果在函数内部有return,则返回实际值
如果执行了return,则执行完退出
'''
def sum(a,b):
sum = a+b
return sum
# 冒号作用:参数的类型建议符
# 箭头:函数返回值的类型建议符
def sum(a:int,b:int) -> int:
sum = a+b
return sum
2.匿名函数
# 用lambda关键字来创建匿名函数
# 特点:冒号后面的表达式有且只有一个
# 匿名函数自带return,且这个return结果就是表达式计算后的结果
# 缺点:只能是单个表达式,不是一个代码块,其设计就是为了满足简单函数的场景
M = lambda x,y:x+y
print(M(23,19))
3.主函数调用
if __name__="__main__":
main()
-
这个脚本被执行的时候,name 值就是 main ,才会执行 main()函数
-
如果这个脚本是被 import 的话,__name__的值不一样。main()函数就不会被调用。
-
这个句子用来写既能直接运行,又能给其他python程序import,提供库调用的脚本
7.定义变量
1.局部变量
- 局部变量势函数内部定义的变量,作用于仅局限在函数的内部
- 不同函数可以定义相同的局部变量
2.全局变量
# 当全局变量与局部变量出现重复定义时,优先执行局部变量
# 函数内部修改全局变量是无效的
name = "Peter"
def editName():
name = "Peter"
pass
def globalEditName():
global name # 在函数内部对全局变量进行修改,需要global关键字声明
name = "Peter"
pass
三、类和对象
# 定义类
class Person: # 建议定义类名时首字母大写
name = "Peter"
age = 26 # 类属性
def _init_(self):
self.color = "黄" # 实例属性
pass
def eat(self): # 实例方法
print("大口吃饭")
pass
pass
yq = Person() # 实例化,创建对象
Person.name # 访问类属性
yq.color # 访问了类属性
yq.eat() # 调用方法
1.类属性
- 类属性是所有对象公用一份的,指向同一地址
- 类属性不能通过实例对象直接修改
Person.name="PPPAAA" # 只能通过类名修改
yq.name = "aaa" # 实例对象的属性修改后,另一个对象的name并不会改变
2.类方法
实例方法,不同与普通函数,必须包含self参数,也可以不用self作为关键字,但一定不能少
- self和对象指向同一内存地址,可以认为self就是对象的引用
- self可以理解为对象自己,相当于java中的this
- 某个函数调用其方法时,python解释器会把这个对象作为第一个参数传递给self
- 特点:只有在类中定义实例化方法时才有意义,在调用时不必传入相应的参数,解释器会自动去指向
3.魔术方法
python中内置的方法,方法名为"_XXX_",在进行特定操作时会被调用
1._init_()
# 创建对象时自动调用,无需手动调用
# 用来做数据初始化工作,也可以认为是实例的构造方法
class Animal:
def __init__(self,name,color="red"):
self.name = name
self.color = color
pass
2._str_()
# 将对象转换成字符串str测试时,打印对象信息
# 如果不加此方法,会输出内存地址
class Aninaml:
def __str__(self):
return "它的名字是%s,他的颜色是%s"%(self.name,self.color)
3._new_()
- new先执行,再执行init
# 创建并返回一个实例对象
# 实例化方法必须要返回该实例,否则对象创建不成功,必须要有return这行语句
class Animal:
def __new__(cls,*args,**kwargs):
print("hello world")
return super().__new__(cls) # python默认的__new__结构
4._class_()
# 获得已知对象的类
对象.__class__()
5._del_()
# 对象在程序运行结束后进行对象销毁时调用该方法,以释放内存资源
# 当一个对象被删除或销毁时,python解释器默认调用一个析构方法
class Animal:
def __del__(self):
print("该对象已被删除")
6._call_()
# 如果一个对象定义了 __call__ 方法,那么这个对象就可以作为一个函数调用
class MyCallableClass:
def __call__(self, *args, **kwargs):
print('Called with arguments:', args, kwargs)
obj = MyCallableClass()
obj()
# 实际上,通过定义 __call__ 方法,可以将一个类的实例转化为可调用对象,这是类似于函数的对象,可以使用括号调用
4.类方法
类对象所拥有的方法称为类方法,需要用装饰器@classmethod来标识
- 对于类方法第一个参数必须是类对象,一般以cls作为第一个参数
- 类方法可以通过类对象直接调用,也可以通过实例对象调用
class Person:
country = "China"
@classmethod
def get_country(cls):
return print(country)
pass
Person.get_country(); # 类方法可以通过类对象直接调用
a = Person()
a.get_country() # 也可以通过实例对象访问
5.静态方法
静态方法需要用@staticmethod来标识
- 静态方法不需要任何参数
- 静态方法主要用来存放逻辑型代码,本身和类以及实例对象没有交互,不涉及到类中方法和属性的操作
class Person:
country = "China"
@staticmethod
def get_country():
return Person.country
6.Property方法
可以使实例方法用起来像实例属性一样,对应于某个方法,使用property属性,简化调用者获取数据的流程
class Price:
def __init__(self):
self.__price = 100
pass
@property # getter方法
def price(self):
return self.__price
@price.setter # setter方法
def price(self,f):
self.__price = f
pass
@price.deleter #deleter方法
def price(self):
del self.price
7.抽象方法
用于程序接口的控制,正如上面的特性,含有@abstractmethod修饰的父类不能实例化,但是继承的子类必须实现@abstractmethod装饰的方法
class Foo(ABC):
@abstractmethod
def fun(self):
"""
你需要在子类中实现该方法, 子类才允许被实例化
"""
class SubFoo(Foo):
def fun(self):
print("子类实现父类的抽象方法")
- ABC(Abstract Base Class)抽象基类:ABC 是 Python 中用于定义抽象基类的模块。抽象基类是具有一组共同特征的类的抽象表示。通过继承 ABC 类和使用 @abstractmethod 装饰器,可以定义抽象方法和属性
- @abstractmethod:强制子类实现父类中指定的一个方法
- 具体类可以继承抽象基类并实现其定义的抽象方法和属性
8.封装
1.私有化属性
- 双下划线开头,声明该属性为私有
- 不能在类的外部被使用或直接访问
- 应用场景
- 把特定的一个属性隐藏起来,不想让类的外部进行直接调用
- 想保护这个属性,不让属性的值随意改变
- 保护这个属性,不想让派生类去继承
# 可以通过类的方法来访问私有属性
class Student:
__name = "小明"
def get_name(self):
print(self.__name)
pass
pass
2.私有化方法
- 有些重要的方法,不允许外部调用,防止子类意外重写,把普通方法设置成私有化方法
class A:
def _myname(self):
print("小明")
3.下划线的说明
- 单下划线表示protected类型的变量,保护类型只能允许其本身与子类进行访问,不能使用from xx import *的方式导入
- 前后两个双下划线表示魔术方法
- xxx_后面单下划线,是为了避免属性名与python关键字冲突,没有别的含义
- 双下划线表示私有变量
9、继承
python中,子类可以继承多个父类
class XM(Person,Adult):
def __init__(self,name,age,school):
Father.__init__(self,name,age) # 这种方法参数需要保留self
super().__init__(name,age) # 也可以用这种方式,二选一,参数不需要self
def work(self): # 重写方法
print("要工作")
10、多态
python不支持java和C++这类强类型语言中多态的写法,但支持原生多态,崇尚鸭子类型
1.多态的前提
- 必须存在继承关系
- 子类重写父类的方法
- 好处
- 可以用同一种方法,根据不同对象作出不同应对
2.多态的实现
class Animal:
def run(self):
print("The animal is running")
pass
pass
class Dog(Animal):
def run(self):
print("The dog is running")
pass
pass
class Cat:
def run(self):
print("The cat is running")
pass
pass
def makeRun(animalType):
animalType.run() # 不一定要是Animal的子类
四、异常处理
python解释器检测到一个错误时,就无法继续执行,出现了错误的提示,这就是异常
1.异常的抛出机制
- 如果在运行时没有异常,解释器会查找相应的异常捕获类型
- 如果在当前函数里面没有找到的话,他就会将异常传递给上层的调用函数,看能否处理
- 如果最外层没找到,解释器就会退出,程序down掉
try:
print(b) # 捕获异常代码
pass
except NameError as msg: # 捕获到错误,会在这里执行,根据具体的错误类型来捕获
print(msg)
pass
else:
print("未出现异常") # 未出现异常时执行
pass
finally:
print("程序运行结束") # 无论如何都会执行
2.主要的错误类型
- FileNotFoundError:找不到指定文件的异常
- NameError:未声明or未初始化对象(没有属性)
- BaseException:所有异常的基类(父类),即包含所有的异常
- SyntaxErrorPython:语法错误
- ZeroDivisionError:除(或取模)零(所有数据类型)
- Exception:万能异常类型,捕获所有异常,当对出现的问题或错误不确定的情况下可以使用
3.自定义异常类
- 自定义异常,都要直接或间接继承Error或Exception类
- 由开发者主动抛出自定义异常,在python中使用raise关键字
# 自定义一个异常类
class LeNumException(Exception):
def __str__(self):
return "[error]:你输入的数字小于0,请输入大于0的数字"
pass
try:
num = int(input("请输入一个数字:"))
if num < 0:
raise LeNumExcept()
except LeNumExcept as e:
print(e) # 捕获异常
else:
print("没有异常")
五、动态添加
运行时可以改变其结构的语言,例如新的函数、对象、甚至代码可以被引进,已有的函数可以被删除或是其他结构上的变化
1.动态添加属性
# python可以在程序运行过程中添加属性和方法
class Animal:
def _init_(self,name,age):
self.name = name
self.age = age
pass
pass
cat = Animal("小白",5)
cat.color = "白色" # 动态绑定实例属性
print(cat.color)
Animal.food = "fish" # 动态添加类属性
2.动态添加方法
import types
def dymicMethod(self):
print("------")
pass
zm.printInfo = types.MethodType(dynamicMethod,zm) # 动态绑定方法
@classmethod
def eat(cls):
print("吃东西")
pass
@staticmethod
def drink():
print("喝水")
pass
Animal.eat = eat # 给类绑定类方法
Animal.drink = drink # 给类绑定静态方法
3.__slots__属性
- python是动态语言,在运行时可以动态添加属性,如果限制在运行时给类添加属性,python允许在定义class时,python允许在定义class时,定义一个特殊的__slots__变量,来限制该class实例能添加的属性
- 只有在slots变量中的属性才能被添加,没有的属性会添加失败,这样可以防止其他人在调用类的时候不安全
- 子类未声明slots变量时,不会继承父类中的slots属性,可以随意赋值属性;子类声明了slots变量后,范围是自身+父类的slots变量
- 定义了slots变量后,__dict__不存在,节约了内存空间(所有的可用属性都会存储在__dict__中,但占用的内存空间很大)
class Student:
__slots__ = ("name","age") # 只允许添加name和age属性,限制了添加的属性
# 但不会限制动态添加类属性
六、导包操作
1.模块
- 一个模块可以被看做是一个文件,一个文件也可以被当做一个独立的模块被别的程序导入调用
- 模块的文件名是模块的名字加上扩展名.py
- 模块首次导入(或重载)时,python会立即执行模块文件的顶层代码(也即不在函数内的代码),而位于函数主体内的直到函数被调用后才会执行,之后的调用都是引用内存
2.模块的搜索
-
python的解释器在import模块时查找模块的顺序:
-
程序的主目录
-
python的PATH目录(如果设置了此变量),可以使用以下命令查看python的PATH目录
-
标准链接库目录,就是python安装目录下的lib文件夹这个目录
-
任何.pth文件的内容(如果存在.pth文件)这四个组件组合起来即为sys.path所包含的路径,而Python会选择在搜索路径中的第一个符合导入文件名的文件
import sys >>>sys.path
-
3.语法操作
1.import…as…
import numpy as np
# 这种方式调用模块内部函数时,需要np.xxx的形式
- import语句导入指定的模块时会执行三个步骤
- 在指定路径下搜索模块文件,找到模块文件
- 指定的模块在被导入时就会被编译成字节码,即编译成.pyc文件
- 依靠模块的代码中的定义来创建其所定义的对象,模块文件中的所有语句回一次执行,从头至尾,而此步骤中任何对变量名的赋值运算,都会产生所得到的模块文件的属性
- 注意:模块只在第一次导入时执行上述步骤,后续的导入操作只不过是提取内存中已加载的模块对象,可以使用reload()命令重新加载指定的模块
2.from…import…
from tensorflow.keras import data
# 只导入模块的部分属性或者函数,此时的函数可以直接调用而不用创建对象
七、IO流
1.文件操作
python自带文件的基本操作方法,但是借助OS等模块更加方便快捷
- 文件操作的一般步骤
- 打开文件
- 读写文件
- 保存文件
- 关闭文件
2.打开文件
打开一个已存在的文件,或创建一个新文件
# windows默认的编码是GBK,这个是中文编码,最好的习惯是我们打开一个文件时给它制定一个编码类型
fobj = open("./Text.txt","w")
fobj = write("Hello World")
fobj.close()
# 以二进制形式写入数据
fobj = open("Text.txt","wb")
fobj.write("在乌云和大海之间",encode("utf-8"))
fobj.close()
- 文件打开模式
- r:以只读方式打开文件
- w:打开一个文件只用于写入,如果文件已存在则将其覆盖,如果不存在,则创建新文件
- a:打开一个文件用于追加,如果文件已存在,指针放在文件的结尾;新内容会被写入到已有内容之后。如果该文件不存在,则创建新文件进行写入
- wb:以二进制的形式写入数据
3.读取数据
f = open("Text.txt","r")
print(f.read()) # 读取全部数据
print(f.read(12)) # 读取指定字符个数read(num)
print(f.readline()) # 按行读取,返回一行
# 二进制读取
f = open("Text.txt","rb")
data = f.read()
print(data)
print(data.decode("gbk")) # 需要解码
f.close()
4.with上下文管理
- 优点:自动释放关联的对象
- with语句:不管在处理文件过程中是否发生异常,都能保证with语句执行完毕后已经关闭打开的文件句柄
with.open("Text.txt","r") as f: # 以这种方式可以替代f.close()
print(f.read())
八、内置函数
1.hasattr
用于检查对象是否具有特定的属性
- 参数
- object:需要检查的对象
- name:需要检查的属性名称,必须是字符串
- 输出
- 如果对象具有指定的属性,则返回True,否则返回False
- 用例
class Myclass:
def __init__(self):
self.attribute = "Hello"
object = MyClass()
if hasattr(obj, 'attribute'):
print('obj has attribute attribute')
else:
print('obj does not have attribute attribute')
2.yield
用于定义生成器函数,生成器函数可以在每次被调用时生成一个值,而不是一次性生成所有值并将其存储在内存中
def my_generator():
yield 1
yield 2
yield 3
# 调用生成器函数,返回一个生成器对象
my_gen = my_generator()
# 1.使用生成器对象进行迭代
print(next(my_gen)) # 输出: 1
print(next(my_gen)) # 输出: 2
print(next(my_gen)) # 输出: 3
# 2.利用for循环来进行迭代
for item in my_generator():
print(item)
- 调用next()函数时,生成器函数会从上次停止的地方继续执行,直到遇到yield
- yeild返回一个值并暂停函数的执行,直到下一次调用