1

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

20 ...

21 ...

参考

yiled关键字及生成器


YjxGVG
8 声望3 粉丝

引用和评论

0 条评论