python基础
1、判断字符串是否为字母或数字
1) 用str.isdigit()函数判断是否数字
字符串中含有小数点、空格等其他字符时,返回False。
2) 用str.isalpha()判断是否字母
不区分大小写,含有除字母以外的字符则返回False
3) 用str.isalnum()判断是否数字和字母的组合
不区分大小写,含有除字母以外的字符则返回False,只含有数字或字母是True,同时含字母和数字返回True。
2、Python文本格式化
2.1使用百分号%
name = 'yyy'
age = 18
msg = '''
***information***
name: %s
age:%d
''' % (name, age)
print(msg)
2.2使用format(),大括号内可以通过序号表示要写入的信息
name = 'yyy'
age = 18
msg = '''
***information***
name: {}
age:{}
'''.format(name, age)
print(msg)
3、copy和deepcopy
import copy
res_df = copy.deepcopy(df)
深度复制时,修改原数据不会改变新复制的数据
4、python文件读写和异常
4.1 csv/文本文件
f.open()
open(file, mode='r', buffering=None, encoding=None, errors=None, newline=None, closefd=True)
mode:打开文件的模式,r,w,a等
file_path = './file/df1.csv'
f = None
try:
f = open(file_path, 'r')
except FileNotFoundError as e:
print('未找到指定文件')
except UnicodeDecodeError as e:
print("读取文件时解码错误!")
except Exception as e:
print(e)
finally:
if f:
print(f.read())
f.close()
with open() as f:
不需要手动关闭文件,只能在with语句下进行操作,结束with语句时自动关闭文件。
with open(file_path, 'r') as f:
print(f.read())
按行读取
with open(file_path, 'r') as f:
for line in f:
print(line)
或:
lines = f.readlines()
for line in lines:
print(line)
4.2 json文件
import json
mydict = {
'name': 'yjx',
'age': 18,
'qq': 888,
'cars': [
{'brand': 'BYD', 'max_speed': 180},
{'brand': 'Audi', 'max_speed': 280},
{'brand': 'Benz', 'max_speed': 320}
]
}
try:
with open('data.json', 'w', encoding='utf-8') as fs:
json.dump(mydict, fs)
except IOError as e:
print(e)
print('保存数据完成!')
5、os.listdir
适用于Unix和Windows,返回指定文件夹下包含的文件及文件夹,list
判断路径dir_path是否存在,不存在则创建
if not os.path.exists(dir_path):
os.makedirs(dir_path)
6、连接mysql数据库
6.1 prepare a cursor object using cursor() method
execute SQL query using execute() method.
db = pymysql.connect(host=db_host, user=username, password=psw, database=db_name, port=int(db_port), charset='utf8')
cursor = db.cursor()
sql = "SELECT price FROM y_temp_price"
cursor.execute(sql)
data = cursor.fetchall()
6.2 连接mysql数据库——返回结果为dataframe格式
db = pymysql.connect(host=db_host, user=username, password=psw, database=db_name, port=int(db_port), charset='utf8')
sql1 = "SELECT price FROM y_temp_price"
df_after = pd.read_sql(sql1, db, index_col=None, coerce_float='price')
db.close()
read_sql()函数的参数意义:
sql:SQL命令字符串
con:连接sql数据库的engine,一般可以用SQLalchemy或者pymysql之类的包建立
index_col: 选择某一列作为index
coerce_float:非常有用,将数字形式的字符串直接以float型读入
parse_dates:将某一列日期型字符串转换为datetime型数据,与pd.to_datetime函数功能类似。可以直接提供需要转换的列名以默认的日期形式转换,也可以用字典的格式提供列名和转换的日期格式,比如{column_name: format string}(format string:"%Y:%m:%H:%M:%S")。
columns:要选取的列。一般没啥用,因为在sql命令里面一般就指定要选择的列了
chunksize:如果提供了一个整数值,那么就会返回一个generator,每次输出的行数就是提供的值的大小
7、读配置文件
import configparser
conf = configparser.ConfigParser()
conf.read('config.ini')
username = conf.get('config', 'username')
8、将dataframe格式的数据append到list
将dataframe格式的数据append到list后,修改df的值会影响list中对应的值
list1.append(df1)
print('修改前:', list1)
df1['Q2'] = df3['Q3']
print('修改后:', list1)
output:
修改前:
[ Q1 Q2
0 asset path
1 asset path
2 asset path
3 asset path
4 asset path
5 asset path
6 asset path
7 asset path
8 asset path
9 asset path]
修改后:
[ Q1 Q2
0 asset 0.664235635
1 asset 0.664235635
2 asset 0.664235635
3 asset 0.664235635
4 asset 0.664235635
5 asset 0.664235635
6 asset 0.664235635
7 asset 0.664235635
8 asset 0.664235635
9 asset 0.664235635]
开始时,df1的Q2列值为'path',list中同样;将df3的Q3列值赋值给df1的Q2列值后,df1的Q2列值为0.664235635,同时,list中的值也被改变。
9、enumerate() 函数
enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。
enumerate(sequence, [start=0])
# 参数:
sequence -- 一个序列、迭代器或其他支持迭代对象。
start -- 下标起始位置的值。
# 1、数据对象是list,将数据和数据下标整体输出与分开输出时,数据类型不同。
seasons = ['Spring', 'Summer', 'Fall', 'Winter']
print('下标默认从0开始:')
for element in enumerate(seasons):
print(element, type(element))
print('设置下标从1开始:')
for element in enumerate(seasons,start=1):
print(element, type(element))
print('下标与元素分别输出:')
for i, element in enumerate(seasons):
print(i, element, type(i), type(element))
# output:
下标默认从0开始:
(0, 'Spring') <class 'tuple'>
(1, 'Summer') <class 'tuple'>
(2, 'Fall') <class 'tuple'>
(3, 'Winter') <class 'tuple'>
设置下标从1开始:
(1, 'Spring') <class 'tuple'>
(2, 'Summer') <class 'tuple'>
(3, 'Fall') <class 'tuple'>
(4, 'Winter') <class 'tuple'>
下标与元素分别输出:
0 Spring <class 'int'> <class 'str'>
1 Summer <class 'int'> <class 'str'>
2 Fall <class 'int'> <class 'str'>
3 Winter <class 'int'> <class 'str'>
# 2、数据对象是字典
dic = {"a": "one", "b": "two", "c": "three"}
for i, element in enumerate(dic, start=1):
print(i, element)
# output:
1 a
2 b
3 c
# 3、数据对象也可以是可迭代的文件
for index, line in enumerate(open(filepath,'r')):
10、取整
10.1 向下取整:int()函数
In:
int(3.7)
Out:
3
10.2 四舍五入:round()函数,小数部分为0.5时,取偶数
round(3.6)
4
round(3.4)
3
round(3.5)
4
round(4.5)
4
10.3 向上取整:ceil()函数,向上取整需要用到 math 模块中的 ceil()方法
In:
import math
math.ceil(4.25)
Out:
5
10.4 将整数部分和小数部分同时取整:math 模块中的 modf()方法,返回元组
In:
import math
math.modf(4.25)
Out:
(0.25, 4.0)
11、repr()函数和str()函数
Python中将任意值转为字符串的方法:repr() 或str() 函数。
函数str() 用于将值转化为适于人阅读的形式,而repr() 转化为供解释器读取的形式。
b = 'CQ-cqu'
c1 = str(b)
c2 = repr(b)
c1
c2
Output:
'CQ-cqu'
"'CQ-cqu'"
12、 Python多进程
q = Queue()
pro_list = []
for code in ['A', 'M', 'S', 'HI']:
p = Process(target=calibrateParas, args=(id, code, date, q, initial_para, n_paths,seed))
p.start()
pro_list.append(p)
for p in pro_list:
p.join()
if not q.empty():
for i in range(0, len(['A', 'M', 'S', 'HI'])):
df = q.get(block=True, timeout=5)
13、 进程池
Multiprocessing.Pool可以提供指定数量的进程,供用户调用,当有新的请求提交到pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到规定最大值,那么该请求就会等待,直到池中有进程结束,才会创建新的进程来它。
class multiprocessing.pool.Pool([processes[, initializer[, initargs[, maxtasksperchild[, context]]]]])
参数
参数名 含义 默认值 processes 最大进程数。如果进程是None,那么使用返回的数字os.cpu_count()。也就是说根据本地的cpu个数决定 initializer None maxtasksperchild 工作进程退出之前可以完成的任务数,完成后用一个新的工作进程来替代原进程,来让闲置的资源被释放 None(只要Pool存在工作进程就会一直存活) 方法
方法名 含义 apply_async(func[, args[, kwds[, callback]]]) 非阻塞 apply(func[, args[, kwds]]) 阻塞运行(串行), join() 主进程阻塞,等待子进程的退出, join方法要在close或terminate之后使用 close() 关闭pool,使其不在接受新的任务 start() 用于启动进程 terminate() 结束工作进程,不在处理未完成的任务
# 定义在子进程中执行的函数
def cal_test(i, j):
print(f"i={i}, start")
re = i+j
time.sleep(0.2)
print(f"i={i}, re={re},end")
return re
def cal_test_map(iseq):
i, j = iseq[0], iseq[1]
print(f"i={i}, start")
re = i
time.sleep(0.2)
print(f"i={i}, re={re},end")
return re
- 非阻塞运行apply_async
for循环中执行步骤:
(1)循环遍历,将10个子进程添加到进程池(相对父进程会阻塞)
(2)每次执行3个子进程,等其中某个子进程执行成后,立马启动新的子进程。(相对父进程不阻塞)
apply_async为异步进程池写法:
异步指的是启动子进程的过程,与父进程本身的执行(print test, close)是异步的,而for循环中往进程池添加子进程的过程,与父进程本身的执行却是同步的。
当for循环中所有子进程执行完成后,再执行 p1.join()
from multiprocessing import Pool
def _pool_apply_async():
p1 = Pool(3)
for i in range(10):
j = i / 10
p1.apply_async(cal_test, args=(i, j)) # 维持执行的进程总数为3,当一个进程执行完后启动一个新进程.
print("test")
p1.close()
print('close')
p1.join()
print('join')
_pool_apply_async()
# output:
test
close
i=0, start
i=1, start
i=2, start
i=0, re=0.0,end
i=2, re=2.2,end
i=1, re=1.1,end
i=3, start
i=4, start
i=5, start
i=5, re=5.5,end
i=3, re=3.3,end
i=4, re=4.4,end
i=6, start
i=7, start
i=8, start
i=8, re=8.8,end
i=6, re=6.6,end
i=7, re=7.7,end
i=9, start
i=9, re=9.9,end
join
阻塞运行apply
将上述代码中的apply_async()换成apply()即可。从输出的i,'test'和'close'的位置可以看出,在阻塞状态下,多进程其实只起到了单进程的作用。# output: i=0, start i=0, re=0.0,end i=1, start i=1, re=1.1,end i=2, start i=2, re=2.2,end i=3, start i=3, re=3.3,end i=4, start i=4, re=4.4,end i=5, start i=5, re=5.5,end i=6, start i=6, re=6.6,end i=7, start i=7, re=7.7,end i=8, start i=8, re=8.8,end i=9, start i=9, re=9.9,end test close join
Pool()与map_async()结合
当pool与map_async结合使用时,可以直接输入可迭代的参数,不在需要用for循环。此时,进程池内的多个进程是并行状态(看输出的i的顺序),且不会阻塞在p.map()处,会直接执行close(),最后在执行join前等待子进程执行完毕。def _pool_map(): lists = range(10) j = 2.5 seq_ = zip(lists, [j]*len(lists)) p1 = Pool(3) re = p1.map_async(cal_test_map, seq_) print("test") p1.close() print('close') p1.join() print('join') _pool_map() # output: test close i=0, start i=1, start i=2, start i=0, re=0,end i=2, re=2,end i=1, re=1,end i=3, start i=4, start i=5, start i=5, re=5,end i=3, re=3,end i=4, re=4,end i=6, start i=7, start i=8, start i=7, re=7,end i=8, re=8,end i=6, re=6,end i=9, start i=9, re=9,end join
Pool()与map()结合
当pool与map结合使用时,可以直接输入可迭代的参数,不在需要用for循环。此时,进程池内的多个进程是并行状态(看输出的i的顺序),但是会阻塞在p.map()处,不会直接执行close()。def _pool_map(): lists = range(10) j = 2.5 seq_ = zip(lists, [j]*len(lists)) p1 = Pool(3) re = p1.map(cal_test_map, seq_) print("test") p1.close() print('close') p1.join() print('join') _pool_map() # output: i=0, start i=1, start i=2, start i=0, re=0,end i=1, re=1,end i=3, start i=4, start i=2, re=2,end i=5, start i=3, re=3,end i=4, re=4,end i=6, start i=7, start i=5, re=5,end i=8, start i=7, re=7,end i=6, re=6,end i=9, start i=8, re=8,end i=9, re=9,end test close join
Pool(),map(),partial()结合
在pool与map结合使用时,map中的iterable参数需要是可迭代且只能是单个参数(多个参数可用zip压缩,然后在函数中分别取出);但是在实际中,可能函数有多个参数,且部分参数是不迭代的(即部分参数固定不变),此时可以在map()函数中使用partial()函数,将不需要变动的参数与函数固定在一起,当作一个参数传给map函数。def _pool_map(): lists = range(10) j = 2.5 seq_ = zip(lists, [j]*len(lists)) p1 = Pool(3) # partial函数中的第一个参数是子进程中要执行的函数名,后面的是固定参数。map函数的第二个参数是可迭代对象。 re = p1.map(partial(cal_test, j=j), lists) print("test") p1.close() print('close') p1.join() print('join') _pool_map() # output: i=0, start i=1, start i=2, start i=0, re=2.5,end i=3, start i=2, re=4.5,end i=1, re=3.5,end i=4, start i=5, start i=3, re=5.5,end i=6, start i=5, re=7.5,end i=4, re=6.5,end i=7, start i=8, start i=6, re=8.5,end i=9, start i=7, re=9.5,end i=8, re=10.5,end i=9, re=11.5,end test close join
14 Lambda关键字
定义匿名函数。匿名函数的作用是简化函数的定义过程,一般用来实现简单的功能。
lambda关键字的使用方法:使用冒号分割函数的参数和函数的返回值,冒号的左边为函数的参数,冒号的右边为函数的返回值,如果有多个参数,中间使用逗号隔开即可。执行完lambda语句后实际上返回一个函数对象,如果要对函数对象进行调用,只需要给它绑定一个临时的名字即可
实现简单函数的功能
add = lambda x, y, z: x+y/z
print(add(1, 2, 0.5))
output:
5.0
应用在函数式编程中
lambda函数可以应用在函数式编程中如:map、reduce、filter、sorted等,这些函数都支持函数作为参数,
# 将列表中的元素按照绝对值大小进行升序排列
list1 = [3,5,-4,-1,0,-2,-6]
print(sorted(list1, key=lambda x: abs(x)))
output:
[0, -1, -2, 3, -4, 5, -6]
15 yield关键字
yield关键字的用法类似于return,但是区别在于yield关键使得函数返回一个generator对象。
yiled关键字的next()函数是从上一个终止点开始,到下一个yield结束,返回值就是yield表达式的值。send()函数用于给yield左边的变量赋值,从yield之后开始,到下一个yield结束,这也就意味着第一次调用必须使用next()函数。
def create_generator(n):
print(f"function create_generator start")
i = 0
while i < n:
x = yield i * i
print(f"x={x}")
i += 1
myGenerator = create_generator(5)
print(f"第一个print的结果:\n {myGenerator}")
print(myGenerator.__next__())
print(myGenerator.send(0.5))
print(f"第一次for循环中print的结果:")
for ele in myGenerator:
print(ele)
print(f"第二次for循环中print的结果:")
for ele in myGenerator:
print(ele)
print('done!')
从输出结果可以看出,yield关键字让函数返回了一个generator,且generator只能被循环一次。
当函数create_generator()被调用时,事实上其执行函数中的任何代码,也不会返回函数中的任何值,此时该函数返回的是一个generator对象。且函数实际上也并没有退出,而是处于一种暂停的状态。
当我们使用for循环来遍历generator的时候,函数将会从暂停的状态恢复,并继续执行函数中的代码。在create_generator()中每执行一行yield语句,就会将yield中的值返回给for循环,这个过程会持续到函数执行至结尾退出之前(函数退出,或者说generator为空意味着函数持续运行但无法发现yield语句。这可能是由于函数已经执行至结尾,也可能是因为我们的函数中包含的if/else条件无法被继续满足)。此时generator会抛出StopIteration异常,for循环结束。需要注意的是,在for循环第一次调用generator时,函数将会从开头执行至第一个yield并返回该语句中的值。
第二次for循环的结果可以看出,当我们对generator执行一次完整的for循环之后,generator的结果就已经被删除,不会返回任何结果。
output:
第一个print的结果:
<generator object create_generator at 0x000001F85D075AF0>
function create_generator start
0
x=0.5
1
第一次for循环中print的结果:
x=None
4
x=None
9
x=None
16
x=None
第二次for循环中print的结果:
done!
也可以通过list()函数对generator隐形循环,直接返回最终list格式的结果。
print(list(myGenerator))
output:
[0, 1, 4, 9, 16]
如果将关键字yield换成return返回函数结果,那么该结果可以多次循环,不会在循环中被删除。
def create_generator(n):
print(f"function create_generator start")
i = 0
re = list()
while i < n:
r = i * i
i += 1
re.append(r)
return re
myGenerator = create_generator(5)
print(f"第一个print的结果:\n {myGenerator}")
print(f"第一次for循环中print的结果:")
for ele in myGenerator:
print(ele)
print(f"第二次for循环中print的结果:")
for ele in myGenerator:
print(ele)
print('done!')
output:
function create_generator start
第一个print的结果:
[0, 1, 4, 9, 16]
第一次for循环中print的结果:
0
1
4
9
16
第二次for循环中print的结果:
0
1
4
9
16
done!
16 拼接两个list
将列表value_list0和value_list1拼接,将value_list1的所有元素接在value_list1的末尾。
1)extend函数
value_list0.extend(value_list1)
2)切片
value_list0[len(value_list0): len(value_list0)] = value_list1
17 获取对应年份、月份的最后一天
from calendar import monthrange
weekday, last_day = monthrange(2019, 12)
print(last_day)
output:31
18 从当前年月往之前推n个月
比如当前为2020年1月7日,之前12个月就是2019年1月
from calendar import monthrange
import datetime, math
import pandas as pd
minus_month = 12
last_date = datetime.datetime.strptime('2020-1-7', "%Y-%m-%d")
month = last_date.month - 1 - minus_month
year = math.floor(last_date.year + month / 12)
month = month % 12 + 1
_, day = monthrange(year, month)
minus_start_date = pd.Timestamp(year, month, day)
print(minus_start_date)
19 list.rsplit(‘,’,1)
将list根据英文逗号‘,’分割,函数的第二个参数表示再分割出n个子串,示例是根据最后一个逗号再分割出一个子串,即总共有分割出两个子串。
formu_list = ['0.5*YC(GovtBond,10)+0.6*YC(CorpBond,7),3']
varibale_list = formu_list[0].rsplit(',',1)
print(varibale_list)
print(len(varibale_list))
output:
['0.5*YC(GovtBond,10)+0.6*YC(CorpBond,7)', '3']
2
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。