Python 基础
一、python框架
(一)、Python语言
-
对象 是python语言中最基本的概念,在python中处理的一切都是对象。内置对象 可供编程者直接使用,如数字、字符串、列表、del等;非内置对象 需要导入模块才能使用,如sin(x)、随机数产生函数random()等
-
python属于强类型编程语言 ,解释器会根据赋值或运算来自动推断变量类型
-
不可变对象:字符串、元组、数字;可变对象:列表、集合、字典
- 不可变:该数据类型对应变量的值发生变化时,此变量的内存地址发生变化;不可通过下标方式修改其中元素值
- 可变:该数据类型对应变量的值发生变化时,此变量的内存地址不发生变化
-
python采用基于值的内存管理方式,若为不同变量赋为相同值,此值在内存中只有一份,多个变量指向同一块内存地址
- python具有自动内存管理功能,会跟踪所有值,对于没有任何变量指向的值,python自动将其删除。
-
变量名必须以字母或下划线开头
-
注释: # 或’‘’ xxx ‘’’
(二)、必知内置函数
-
type(x) 可知对象x的类型
-
isinstance(对象, 类型)
-
isinstance(3, int) #True isinstance(3j, (int, float, complex)) #True 3j是否为int或float或complex中的一种类型
-
-
id(x) 可知对象x的内存地址
-
x = 3 y = x id(x) == id(y) #True x += 3 id(x) #x内存地址发生改变 id(y) #y内存地址不变 x = 3 y = 3 id(x) == id(y) #True
-
-
dir(_builtins_ ) 可列出所有内置函数
-
ord() 返回单个字符对应的unicode码; char()返回序数对应的字符; str() 把一切变为字符串
-
ord('a') #97 char(97) #"a" str([1,2,3]) #"[1,2,3]"
-
-
max() min() sum()
-
import random a = [random.randint(1,100) for i in range(10)] #[72, 26, 80, 65, 34, 86, 19, 74, 52, 40] max(a) #86 min(a) #19 sum(a) #548
-
-
map(函数, 可迭代对象) 根据提供的函数对指定的序列做映射, 返回一个map对象
-
list(map(str, range(10))) #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 单参数映射 def add(x, y): return x + y list(map(add, range(5),range(5,10))) #[5, 7, 9, 11, 13] 双参数映射
-
-
reduce(两个参数的函数,可迭代对象) 把可迭代对象的最前两个数据传入函数,得到的结果与第三个数据作为新两个参数传入函数,依此累积,返回最后的结果
-
reduce(lambda x,y:x+y, range(1,10)) #45
-
-
filter(函数,可迭代对象) 对可迭代对象进行过滤,返回满足函数返回值为True的数据
-
def func(x): return x.isalnum(); list(filter(func, ['foo', 'x41', '?!', '***'])) #['foo', x41]
-
-
range(start, stop, step) 创建一个整数序列,左闭右开,start默认为0,step默认为1
-
list(range(1, 10, 2)) #[1,3,5,7,9] list(range(9, 0, -2)) #[9,7,5,3,1] step为负时,start应该比stop大
-
-
zip(可迭代对象1,可迭代对象2,…,可迭代对象n) 把n个对象中对应的元素打包成一个个元组,返回由这些元组组成的对象
-
list(zip(['a','b','c','d'], [1, 2, 3])) #[('a',1), ('b', 2), ('c', 3)]
-
-
eval(字符串表达式) 执行一个字符串表达式,并返回表达式的值
-
eval('pow(2, 2)') #4
-
-
sorted(x) #升序排序
- sorted(x, reverse = True) #降序排序
-
len(x) 返回元素个数
-
enumerate(序列,start = 序号开始数) 给序列的每个元素加个序号
-
seq = ["dog","cat"] for i,element in enumerate(seq): print(i,elemet) #0 dog #1 cat
-
(三)、运算符和表达式
- 运算符
- + - * % < <= > >= == != or and not
- / 3/5 -> 0.6 // 3//5 ->0
- 成员测试符in 5 in range(1,10,1) #True
- 同一性测试运算符(二者内存地址是否相同) x = [300, 300, 300] x[0] is x[1] #True y = [300,300,300] x is y #False
- 'welcome '*3 #‘welcome welcome welcome’
二、python六大对象
(一)、列表 List
- 列表 [1,‘a’,[3] ] 数据项**不需具有相同类型 ** 转为列表 list(x)
- 当列表元素增加或删除时,列表对象自动进行扩展或收缩内存,保证元素之间没有缝隙
- 空列表 x = [] 或 x = list() 转换为列表 list( x )
- 列表中包含的是元素值的引用,而不是直接包含元素值,通过下标或自身方法来增加、修改、删除元素,序列对象在内存中起始地址不变
操作
a = [1, 2, 3]
+ 创建一个新列表,把原列表元素和新元素依此复制到新列表的内存空间。涉及大量元素复制,速度较慢
a = a + [7] # [1, 2, 3, 7]
列表.append(元素) 不改变列表在内存中的首地址,原地修改列表,速度较快
a.append(9) # [1, 2, 3, 9]
列表.extend(列表) 把另一个可迭代对象的所有元素添加到该列表对象尾部,原地操作
a.extend((7,9)) #[1, 2, 3, 7, 9]
列表.insert(位置, 元素) 把元素添加到列表指定位置,涉及到插入位置之后所有元素的移动,会影响处理速度
a.insert(1,5) #[1, 5, 2, 3]
列表.pop(位置) 把指定位置元素弹出,位置默认为-1
a.pop() #3
a.pop(1) #2
列表.remove(元素) 删除首次出现的指定元素
a.remove(2) #a变为[1, 3]
列表.index(元素) 返回元素首次出现的下标
a.index(2) #1
列表.count(元素) 返回元素在列表中出现的次数
a.count(3) #1
浅拷贝和深拷贝
-
浅拷贝:只复制可变类型的第一层,其他层引用 copy.copy(x)
-
深拷贝:复制可变类型所有层 copy.deepcopy(x)
-
#切片是浅拷贝 a = [1, 3, [1, 5]] b = a[::] a == b #True 值一样 a is b #False 不是同一个对象 id(a) == id(b) #False 内存地址不一样 b[2][0] = 3 #a变为[1, 3, [3, 5]] b[0] = 3 #a不变
-
排序
a = [1, 4, 3, 2]
原地排序
a.sort() #[1, 2, 3, 4] 默认升序排序
s.sort(reverse = True) #[4, 3, 2, 1] 可以降序排序
原地逆序
a.reverse() #原地逆序
列表推导式
-
语法: [表达式 for 迭代变量 in 可迭代对象 if条件表达式]
-
a = [5, 10, 15, 20] b = [n*10 for n in a if n > 5] #[100, 150, 200]
-
(二)、元组 Tuple
- 元组 ( 3, 4, ‘a’ ) 数据项不需具有相同类型,元素不能修改。 一个元素的元组必须加逗号 (3, )为元组, (3)为3
- 元组必须作为一个不可改变的整体进行操作 转为元组 tuple(x)
- 列表和元组对比
- 元组相当于定义了一系列常量值,只需要对其遍历,因此速度比列表更快。
- 元组对不需要改变的数据写保护,使代码更安全
- 元组可用作字典键,而列表不可以作为字典键
序列解封包 对列表和字典同样有效
values = 1,2,3 #序列封包 这也是一个元组(1,2,3)
x,y,z = values #序列解包 x==1 y==2 z==3 解包序列元素个数必须与赋值号左边的变量个数相同
a, *b = values #只想解出部分元素,在想拥有多个元素的变量左边加* a==1 b==[2,3]
keys = ['a', 'b', 'c']
values = [1, 2, 3, 4]
for k,v in zip(keys,values):
print((k,v), end=" ") #('a',1) ('b',2) ('c',3)
生成器推导式
-
生成器推导式的结果不是列表,也不是元组,而是一个生成器对象。
-
每个元素只能访问一遍。可用_next_()方法或内置函数next()访问元素
-
g = ((i+2)**2 for i in range(10)) tuple(g) #(4,9,16,25,36,49,64,81,100,121) list(g) #[] 上面tuple(g)已经用完了生成器对象的所有元素 g = ((i+2)**2 for i in range(10)) g.__next__() #4 next(g) #9
-
(三)、字典 Dictionary
-
字典是无序可变序列
-
{‘a’:3,‘b’:4} 键必须唯一,值不必; 值可以是任何数据类型,键必须是不可变的,如字符串、元组、数字
操作
字典创建
a = {"name":"dog", "age":18} #{"name":"dog", "age":18}
a = dict(name="dog", age=18) #{"name":"dog", "age":18}
a = dict.fromkeys(["name","age"]) #指定内容为键,值为None{"name":None, "age":None}
keys = ['name','age']
values = ['dog', 18]
a = dict(zip(keys,values)) #指定内容创建字典
字典元素读取
a["name"] #"dog" ,若键不存在则抛出异常
a.get[键,返回值] #若键不存在,可以返回指定值
a.items() #[("name","dog"),("age",18)] 返回键值对列表
a.keys() #["name","age"] 返回键列表
a.values() #["dog", 18] 返回值列表
字典元素添加与修改
b = {"sex":"man"}
a.update(b) #a变为{"name":"dog", "age":18, "sex":"man"} 把另一个字典的键值对添加到当前的字 #典对象中
a.clear() #a变为{} 删除字典中所有键值
a.pop("name") #a变为{“age”:18} 删除指定键的键值
a.popitem() #随机删除一个键值对
(四)、字符串 String
-
用单引号、双引号、三引号括起来的符号序列称为字符串,可相互嵌套
-
空串表示为 ''或""
-
三引号括起来的字符串可以换行
-
字符串界定符前面加r表示原始字符串
-
print("Hello \n World") #Hello #World print(r"Hello \n World") #Hello \n World
-
(五)、集合 Sets
- 集合{3,4}是无序可变序列,元素不可重复 set(x) 转为集合,自动去除重复元素
- 集合中只能包含字符串、元组、数字等不可变类型
操作
a = {3, 5}
a.add(7) #{3,5,7}
a.remove(5) #{3,7} .remove(元素) 删除指定元素
a.clear() #{} .clear() 清空集合
a = {3,5,7}
b = {3,6,9}
a | b #{3, 5, 6, 7, 9} 并集
a & b #{3} 交集
a - b #{5,7} 差集
x = {1,2,3}
y = {1,2,3,4}
x < y #True 真子集
x <= y #True 子集
a = [1,2,3,4,4,4,5,6]
b = set(a) #快速提取不重复元素
def randomNumber(number, start, end):
data = set()
while True:
data.add(random.randint(start, end))
if len(data) == number:
break
return data # 快速生成指定数量的不重复随机数
(六)、数字 Number
-
可表示任意大小数字
-
支持复数操作
-
a = 3 + 4j b = 5 + 6j c = a + b #(8 + 10j) c.real #8.0 查看复数实部 c.imag #10.0 查看复数虚部 a.conjugate()#3 - 4j 返回共轭复数 a*b #(-9 + 38j) 复数乘法 a/b #(0.63934426229508 + 0.3278688524590165j) 复数除法
-
三、选择与循环
-
for循环
-
for 迭代变量 in 可迭代对象: 循环体 else: else子句代码块
-
-
while循环
-
while 条件表达式: 循环体 else: else子句代码块
-
-
break 打破循环 continue跳过本次循环剩余语句,进入下一次循环
-
if语句
if xxx: elif xxx: else:
四、函数
(一)、基础话题
def 函数名(参数表):
'''注释'''
函数体
return 表达式
形参:函数定义时参数列表中的参数
实参:函数调用时向其传递的参数
可变实参:若传递给函数的是可变序列,并且在函数内部使用下标或可变序列自身的方法增加、删除、修改元素时,修改后的结果是可以反映到函数之外的
def modify(d):
d['age'] = 20
a = {'age': 18, 'name': 'dog'}
modify(a)
print(a) #{'age': 20, 'name': 'dog'}
python支持对函数参数和返回值类型进行标注,但实际上不起作用
def test(x: int, y: int) -> int:
return x+y
默认形参:必须出现在函数参数列表最右端
def test(x, y, z=3.0):
return x+y+z
print(test(3,4.0))
key传参
def test(x, y, z):
return x+y+z
print(test(y = 3, x = 4, z = 5))
可变长度参数
*parameter用来接收多个实参,并把它们放在一个元组中
def demo(*p):
print(p)
demo(1,2,3) #(1,2,3)
**parameter接收关键参数并存放在字典中
def demo(**p):
for item in p.items():
print(item,end=" ")
demo(x=1,y=2,z=3) #("x",1) ("y",2) ("z",3)
def demo (x,y,z):
return x+y+z
demo(3,*(2,3)) #8 *可以解包让其变为普通参数传给函数
return 语句若有多个参数,以元组形式返回
def mm(x,y):
return x,y #(x,y)
变量作用域
定义在函数内部的变量为局部变量,只在函数内部起作用
定义在函数外部的变量为全局变量,在函数内外部都起作用
可通过global x,随时把x变为全局变量
lambda表达式
只可以包含一个表达式,该表达式的计算结果可以看作lambda函数的返回值
f = lambda x,y=2:x+y
f(1) #3
(二)、高级话题
生成器函数yield
yield与return 语句类似,都是返回函数值。return语句只返回一次,而yield返回一次值后,把后面代码挂起,代.__next__()或next()或for遍历时再次返回值,直到满足条件不再返回
def odd():
print("step1")
yield 1
print("step2")
yield 3
print("step3")
yield 5
o = odd()
next(o) #"step1"
o.__next__() #"step2"
函数嵌套定义
一个函数内部还可以完整定义一些函数
内部函数:定义在其他函数内的函数
外部函数:内部函数所在的函数
!内部函数可以访问外部函数的局部变量!
def outfun():
def innerFun_0():
print("I am first func")
return
def innerFun_1():
print("I am second func")
return
innerFun_0()
innerFun_1()
return
outfun() #I am first func
#I am second func
def add(a,b):
def result(c):
return a+b+c
return result
add(1,2)(3) #6
装饰器-函数嵌套的应用
在代码运行期间动态增加函数功能,但又不希望修改此函数的定义,此为装饰器
def log(func):
def wrapper(*args,**kw):
print("call %s():" % func.__name__)
return func(*args,**kw)
return wrapper
@log
def now():
print("2025-2-5")
now() #call now()
#2025-2-5
----------------------------------------------
def before(func):
def wrapper(*args, **kwargs):
print('Before call')
return func(*args, **kwargs)
return wrapper
def after(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
print('After call')
return result
return wrapper
@before
@after
def now():
print(3)
return
now() #Before call
#3
#After call
五、OOP
class Student(object): #类名Student,继承大类object
number = 0 #类变量,不随实例化而变化,一直都在
def __init__(self,name,score): #类中每个函数第一个参数必须为self,表示自己
self.name = name
self.score = score
Student.numebr = Student.number+1
def show(self): #实例化方法
print("Name:{},score:{}".format(self.name,self.score))
@staticmethod #静态方法,看类
def info(self,add):
print(Student.number+add)
print(self.name)
pang = Student("John",100) #实例化类 ,它会自动调用__init__()
li = Student("Li",200)
print(Student.number) #2
pang.info(pang,44) #44
#pang
特殊方法
单下划线开头 _foo 代表不能访问的类属性,需要通过类提供的接口进行访问
双下划线开头 __foo 代表类的私有成员
双下划线开头和结尾 __foo__ 代表python类的特殊方法
下面全部假设定义在Student类中
def __str__(self):
return ("I can define the return string of class")
print(pang) #I can define the return string of class
def __len__(self):
return len(self.name)+2
print(len(pang)) #6
数据封装
public 公开 任何地方均可访问
protected 受保护的 在变量名前加_ ,只能在类内和子类内访问。但实际上可以修改,不会报错。
private 私有的 在变量名前加__ ,只能在当前类或对象中访问
多态
根据子类对象的不同,得到不同的结果,即多态。
def animal(object):
def run(self):
print("animal is running")
def dog(animal):
def run(self):
print("dog is running")
def cat(animal):
def run(self):
print("cat is running")
dog = dog()
dog.run() #dog is running
cat = cat()
cat.run() #cat is running
def run_twice(animal):
animal.run() #只知道该对象是animal类型,运行的具体结果由它的具体类型决定----多态
animal.run()
run_twice(dog) #dog is running
#dog is running
run_twice(cat) #cat is running
#cat is running