Python基础

Python基础

  • 这里将Python常用的基础知识整理回顾,实践出真知
  • IDE使用PyCharm

Python基操

字符串

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
38
39
40
41
mystr = 'RoyKun'
result = mystr.index('R') # 获取字符索引,没找到会崩溃
print(result)

result = mystr.find('k') # 获取字符索引,如果没找到返回-1
print(result)

result = mystr.count('u') # 字符出现的个数
print(result)

result = len(mystr) # 返回字符串长度
print(result)

result = mystr.replace('u','n') # 字符替换
print(result)

mystr = 'apple,pear,orange'
result = mystr.split(',') # 分割数据
print(result) # ['apple', 'pear', 'orange']

mystr = 'aabccb'
result = mystr.partition('b')# 以指定字符串分割为3部分
print(result) # ('aa', 'b', 'ccb')

myurl = 'http://www.baidu.com'
result = myurl.startswith('http') # 是否以指定数据开头
print(result) # True

myurl = 'http://www.baidu.com'
result = myurl.endswith('xxx') # 是否以指定数据开头
print(result)

mystr = 'k'
result = mystr.join('Roy') # 以指定字符串拼接数据
print(result) # Rkoky

mystr = ' Roy '
result = mystr.strip(' ') # 去除两边指定字符
# result = mystr.lstrip(' ')
# result = mystr.rstrip(' ')
print(result)

常见数据类型及操作

  • IDE中会有操作提示
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
# 列表:以中括号表现形式的数据集合,可以放任意类型的数据
my_list = [1, 'app', True]
print(type(my_list)) # <class 'list'>
print(my_list[-2]) #

my_list.append('Roy') # 追加数据
my_list.insert(1, 'kun') # 指定位置插入数据

mylist2 = ['watermelon', '草莓']
my_list.extend(mylist2) # 添加列表元素(扩展)
print(my_list)

my_list.remove('草莓') # 删除指定严肃
del my_list[0] # 根据下标删除元素

result = my_list.pop(1) # 删除数据并返回数据值,默认删除 -1
print(result)

# 列表生成式
my_list = [value for value in range(1,6)]
print(my_list) # [1, 2, 3, 4, 5]
my_list = [value+"Hello" for value in ['ab','abc']]
print(my_list)
my_list = [(x,y) for x in range(1,3) for y in range(2,4)]
print(my_list) # [(1, 2), (1, 3), (2, 2), (2, 3)]
1
2
3
4
5
6
7
8
9
10
11
12
# 元祖:以小括号形式表现的数据集合,可以存任意类型的数据
# 不能对元祖进行数据修改
my_tuple = (1, 2, 'Roy',[3,4])
print(my_tuple)
# my_tuple[0] = 2 # 不能直接修改
list1 = my_tuple[3]
list1[0] = 4
print(list1) # 可以修改其中的列表

# 如果只有一个元素需要添加逗号,不然会判断为其他类型
my_tuple2 = (1,)
print(type(my_tuple2))
1
2
3
4
5
# 字典:以大括号形式表现的数据集合,元素使用键值对表示
# 字典中的数据是无序的(输出顺序不定)
my_dict = {'name':'Roy', 'age':18, 'hobby':'fuck'}
print(my_dict)
result = my_dict.pop('age') # 删除元素,必须指定key
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 集合set:以大括号表示的数据集合,无序,且不能重复
my_set = {1, 2, 'Roy'}
print(type(my_set)) # <class 'set'>

my_set.remove(1) # 删除指定元素,元素必须存在否则报错
print(my_set)
my_set.discard('Roy') # 不报错
print(my_set)

my_set2 = set() # 若没有元素时
print(type(my_set2))

my_set2.add('666')
print(my_set2)
# 无序,也就是说不能根据下标进行操作
  • 列表、元素、集合都叫做数据容器,可以相互转换
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
my_list = [1,2,2]
my_tuple = (4,5)
my_set = {'name', 'age'}
# 列表转集合
result = set(my_list) # 会对元素去重
# 元祖转集合
result = set(my_tuple)
# 列表转元祖
result = tuple(my_list)
# 集合转元祖
result = tuple(my_set)
# 集合转列表
result = list(my_set)
# 元祖转列表
result = list(my_tuple)
  • enumerate()函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列
    也是后面拆包的常用操作
1
2
for index, value in enumerate(['apple', 'banana']):
print(index,value)
1
2
3
4
# 针对字典
my_dict = {'name':'Roy', 'age':18, 'hobby':'fuck'}
for key, value in my_dict.items():
print(key,value)

函数相关操作

1
2
3
4
5
6
7
8
9
10
11
12
# 不定长参数函数
def fun(a, b, *args, **kwargs):# a,b是必传参数
print(a)
print(b)
print(args)
print(kwargs)

fun(1, 2, 3, 4, name = "hello", age = 20)
# 1
# 2
# (3, 4) 元祖封装
# {'name': 'hello', 'age': 20} 字典封装
1
2
3
4
5
6
7
8
9
10
11
12
13
# 递归函数:传递回归,即在函数内部再次调用函数
def cal_num(num): # 计算阶乘
if num == 1: # 结束递归的条件(必须有)
return 1
else:
return num * cal_num(num-1)

cal_num(5)

import sys
result = sys.getrecursionlimit() # 获取最大递归次数
print(result) # 1000
sys.setrecursionlimit(1100) # 设置最大递归次数
1
2
3
4
5
6
7
8
9
10
11
12
# 匿名函数:没有名称的函数
# 由于这个函数只在这里用一下,所以没有必要使用def定义,可以简化代码
func = lambda x,y: x+y # 前面是参数;后面只能写一句表达式,返回计算结果
result = func(2,4)
print(result)

func1 = lambda num: True if num%2 == 0 else False # 判断奇偶
print(func1(5))

list2 = [{'name':'roy','age':22},{'name':'kun','age':20}] # 对字典列表进行排序
list2.sort(key=lambda item: item['age']) # reverse=
print(list2) # item代表列表中的每个字典,sort函数内部循环获取所有age值排序
1
2
3
4
5
6
7
8
9
10
# 高阶函数
# 参数是函数或者返回函数的函数
def test(new_func):
new_func() # 调用
def inner():
print('内部函数')
return inner
def show():
print('我作为函数参数')
func = test(show)

装饰器

1
2
3
4
5
6
7
8
9
10
11
# 闭包
# 函数嵌套时,内部函数使用外部函数的参数或变量,并且返回这个内部函数,叫做闭包
def exfunc(msg,num):
def refunc():
print(msg*num)
return refunc # 注意不带括号

# 闭包的好处是可以根据参数得到新函数,适应不同需求
func = exfunc('roy',2)
func()
print(func)
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
# 装饰器本质上是一个函数,可以对原函数的功能进行扩展,不影响原函数的定义和调用
# 我们也可以充分发挥闭包的作用,根据参数返回装饰器

def decorator(func): # 通用装饰器:可以修饰带参数的和不带参数的函数,有返回值的和无返回值的函数
def inner(*args, **kwargs):
print('这是对被装饰函数扩展的操作')
return func(*args, **kwargs) # 需要设置原函数的参数,对于有返回值的函数需要return
return inner

@decorator # 语法糖,相当于执行 test = decorator(test) 接收闭包,扩展了原函数
def sum(num1,num2):
print(num1 + num2)
sum(1,3)

@decorator
def sum2(num1,num2):
result = num1 + num2
return result
result = sum2(3,4)
print(result)

@decorator # 语法糖,相当于执行 test = decorator(test) 接收闭包,扩展了原函数
def test():
print('Roy')
test() # 这里函数不带有参数
  • 切片
1
2
3
4
5
6
str = 'RoyKun'
result = str[0:5:1] # 起始下标:结束下标:步长 (不包含结束下标)
print(result) # RoyKu

result = str[-1:-4:-1] # nuK
print(result)

文件操作

  • 主要用到open函数和os
1
2
3
4
5
6
7
# 读取键盘输入
# Python提供了两个内置函数从标准输入读入一行文本
str = raw_input("请输入:")
print "你输入的内容是: ", str

str = input("请输入:")
print "你输入的内容是: ", str
1
2
3
4
5
6
7
8
9
10
11
12
# 打开文件使用open函数
fileObject = open('1.txt', 'r', encoding='UTF-8')# 在Windows上使用utf-8编码格式
# 使用open函数相当于创建了一个file对象,包含常用方法:
fileObject.write(string) # 写入字符串
fileObject.read([count]) # 读取文件内容 参数count是要从已打开文件中读取的字节计数
position = fileObject.tell() # 查找当前位置
fileObject.close() # 关闭对象

# 在python3中默认支持中文编码,也可以在代码首行使用:
# -*- coding: UTF-8 -*-
# 指定编码格式
# 使用'b'模式时,不需要指定编码格式,同时读取数据需要使用decode()解码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 其他方法
# 刷新文件内部缓冲,直接把内部缓冲区的数据立刻写入文件, 而不是被动的等待输出缓冲区写入
file.flush()

# 读取整行,包括 "\n" 字符
file.readline([size])

# 读取所有行并返回列表,若给定sizeint>0,则是设置一次读多少字节,这是为了减轻读取压力
file.readlines([sizeint])

# 截取文件,截取的字节通过size指定,默认为当前文件位置
file.truncate([size])

# 移动文件读取指针到指定位置
file.seek(offset[, whence])
  • 对于打开文件的模式总结如下图:

  • 文件对象还包含以下属性:

属性 描述
file.closed 返回true如果文件已被关闭,否则返回false。
file.mode 返回被打开文件的访问模式。
file.name 返回文件的名称。
file.softspace 如果用print输出后,必须跟一个空格符,则返回false。否则返回true。
  • os模块提供了帮你执行文件处理操作的方法,比如重命名和删除文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import os

# 重命名文件test1.txt到test2.txt。
os.rename( "test1.txt", "test2.txt" )

# 删除文件
os.remove(file_name)

# 创建一个新目录
os.mkdir("newdir")

# 将当前目录改为"/home/newdir"
os.chdir("/home/newdir")

# 显示当前的工作目录
os.getcwd()

# 删除目录,它的所有内容应该先被清除
os.rmdir('dirname')

json序列化

  • JSON (JavaScript Object Notation) 是一种轻量级的数据交换格式,它基于ECMAScript的一个子集

  • 使用 json 模块来对 JSON 数据进行编解码,主要包括

    1. json.dumps() 对数据进行编码
    2. json.loads()对数据进行解码
  • Python 编码为 JSON 类型转换对应表:

    Python JSON
    dict object
    list, tuple array
    str string
    int, float, int- & float-derived Enums number
    True true
    False false
    None null

高级操作

面向对象

  • 类、继承、部分特殊方法等需要了解掌握
  • 可参看菜鸟教程,过一遍就OK:

https://www.runoob.com/python3/python3-class.html

异常处理

  • 常见的异常处理方法:

    1. 使用try/except:检测try语句块中的错误,从而让except语句捕获异常信息并处理
    2. 可以使用raise语句自己触发异常
    3. 异常可以是python标准异常,也可以继承并自定义
  • 参看教程,过一遍即可

自定义包/模块

  • 大型的程序需要自定义很多的包,既增强代码的可读性,也便于维护

  • 教程

  • 需要注意:

    1. __name__属性
    1
    2
    3
    4
    5
    6
    7
    # 如果我们想在模块被引入时,模块中的某一程序块不执行,我们可以用__name__属性,使该程序块仅在该模块自身运行时执行

    # Filename: using_name.py
    if __name__ == '__main__':
    print('程序自身在运行')
    else:
    print('我来自另一模块')
    1
    2
    3
    4
    5
    6
    $ python using_name.py
    程序自身在运行

    $python
    >>> import using_name
    我来自另一模块

迭代器

  • 迭代器是访问集合元素的一种方式,对于可以使用for循环遍历的类型(字典、列表、字符串等)都可以迭代

  • 有两个基本的方法:iter()next()

    1
    2
    3
    4
    5
    6
    7
    # 如果可以查看到 __iter__ 方法,即是可迭代对象
    result = dir([1,2])
    print(result)

    # isinstance() 函数来判断一个对象是否是一个已知的类型,类似 type()
    a = 2
    isinstance (a,int) # True
  • 把一个类作为一个迭代器使用需要在类中实现两个方法 __iter____next__

    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
    38
    39
    class MyIterator:
    def __iter__(self): # 返回一个特殊的迭代器对象
    self.a = 1
    return self

    def __next__(self): # 返回下一个迭代器对象
    x = self.a
    self.a += 1
    return x

    myclass = MyIterator()
    myiter = iter(myclass) # 迭代变量在___iter__中,必须使用iter()方法

    print(next(myiter)) # 1
    print(next(myiter)) # 2
    print(next(myiter)) # 3
    print(next(myiter)) # 4
    print(next(myiter)) # 5
    ##################################################################
    class MyIterator:
    def __init__(self):
    self.list1 = [1,3,5,6]
    self.current_index = 0

    def __iter__(self):
    # 返回一个特殊的迭代器对象
    return self
    def __next__(self):
    if self.current_index < len(self.list1):
    # 返回下一个迭代器对象
    x = self.list1[self.current_index]
    self.current_index += 1
    return x
    else:
    raise StopIteration()

    myiter = MyIterator() # 实例化迭代器
    for value in myiter: # for循环就是这么强大:不用next也不用raise异常啊啊啊
    print(value)
    • 迭代器和生成器的好处是:根据需要每次生成一个值,相当于保存了之前的状态下次继续而不是从头开始,节省内存

生成器

  • 生成器是特殊的迭代器

  • 生成器的创建有两种方式

    1. 使用类似列表生成器
    1
    2
    result = (x for x in range(5))	# 换成小括号
    value = next(result) # 0
    1. 使用yield创建生成器
    1
    2
    3
    4
    5
    6
    7
    8
    def func():
    for i in range(5):
    print('before') # 例如:在深度学习项目中将数据加载部分放在这,每次只会将一部分数据拉进内存,节省消耗
    yield i # 每次迭代在这里暂停,下次迭代继续执行
    print('after')

    gene = func()
    print(next(gene)) # 或者使用for循环输出

    注:迭代器和生成器的迭代只能往后不能往前

线程和进程

  • 使用threading创建子线程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import threading
import time

def func1(num1):
for i in range(18):
print(num1)
time.sleep(0.1)

def func3(str):
for i in range(18):
print(str)
time.sleep(0.1)

def func2():
for i in range(20):
print('主线程',i)
time.sleep(0.1)

if __name__ == '__main__':
thread = threading.Thread(target=func1, args=(555,)) # 元祖形式传参
thread2 = threading.Thread(target=func3, kwargs={'str':'roy'})
thread.start()
thread2.start()
func2() # 主线程一般放在后面,不然会先执行完主进程
  • 主线程一般会等待子线程结束再退出
  • 可以通过设置守护线程,主线程结束即全部退出
1
2
3
4
5
6
7
8
9
10
if __name__ == '__main__':
thread = threading.Thread(target=func1, args=(555,)) # 元祖形式传参
thread2 = threading.Thread(target=func3, kwargs={'str':'roy'})# 字典形式
# 守护进程
thread.setDaemon(True)
thread.start()
# 必须都设置守护线程才会在主线程结束时退出
thread2.setDaemon(True)
thread2.start()
func2()
  • 互斥锁——线程同步
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 多个线程之间同时操作全局变量就会出问题,需要上锁
lock = threading.Lock() # 互斥锁
arr = 0

def lockfunc1():
lock.acquire() # 锁住
global arr # 需要拿到全局变量arr
for i in range(500):
arr += 1
print('进程1:',arr)
lock.release() # 解锁

def lockfunc2():
lock.acquire()
global arr
for i in range(400):
arr += 1
print('进程2:',arr)
lock.release()
  • 每创建一个进程操作系统都会分配运行资源,真正干活的是线程,每个进程会默认创建一个线程
  • 多进程需要多个CPU核,而多线程是在一个核里进行资源调度,可以结合并行并发的概念理解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import multiprocessing

def func1(num1):
for i in range(18):
print(num1)
time.sleep(0.1)

def func2(str):
for i in range(18):
print(str)
time.sleep(0.1)

if __name__ == '__main__':
multi1 = multiprocessing.Process(target=func1)
multi2 = multiprocessing.Process(target=func2)# 每个进程自带一个线程
multi1.start()
multi2.start()
  • 类似的可以使用守护进程退出子进程

  • 也可以使用Precess.terminate()终止

  • 进程之间是独立的,不共享全局变量

  • 那么进程之间如何通信呢?消息队列

1
queue = multiprocessing.Queue(3)    # 默认可以存任意多数据
  • Queue模块中常用到的方法
    1. Queue.qsize() 返回队列的大小
    2. Queue.empty() 如果队列为空,返回True,反之False
    3. Queue.full() 如果队列满了,返回True,反之False
    4. Queue.full 与 maxsize 大小对应
    5. Queue.get([block[, timeout]])获取队列,timeout等待时间
    6. Queue.get_nowait() 相当Queue.get(False)
    7. Queue.put(item) 写入队列,timeout等待时间
    8. Queue.put_nowait(item) 相当Queue.put(item, False)
    9. Queue.task_done() 在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列发送一个信号
    10. Queue.join() 实际上意味着等到队列为空,再执行别的操作

小结

还有一些常见的操作比如Python连接数据库、解析XML数据等,可以结合项目学习加深理解。每一门语言都是一个完备的体系,很多内容可能现在用不到,提前了解为好。

注:要注意身体,切勿慢性zs!晚安

------ ���Ľ���------