基本功-Python小例子51-100

鱼每天都练习基本功,台上十分钟台下十年功,编程写代码或许也需要这样子的,就用python小例子来练习吧

Posted by Valuebai on February 24, 2020

51 查看对象类型

class Student(object):
    def __init__(self, id, name):
        self.id = id
        self.name = name

    def __repr__(self):
        return 'id=' + self.id + ', name=' + self.name
		
xiaoming = Student(id='001',name='xiaoming')
print(type(xiaoming))
-><class '__main__.Student'>

type(tuple())
->tuple

52 聚合迭代器ZIP

# 创建一个聚合了来自每个可迭代对象中的元素的迭代器:
x = [3, 2, 1]
y = [4, 5, 6]

print(list(zip(y, x)))

a = range(5)
b = list('abcde')

print(b)
print([str(y) + str(x) for x, y in zip(a, b)])

53 nonlocal 用于内嵌函数中

# 关键词 nonlocal 常用于函数嵌套中,声明变量 i 为非局部变量;
# 如果不声明,i+=1 表明 i 为函数 wrapper 内的局部变量,因为在 i+=1 引用(reference) 时,i 未被声明,所以会报 unreferenced variable 的错误。
import time


def exceter(f, n):
    i = 0
    t1 = time.time()

    def wrapper():
        try:
            f()
        except Exception as e:
            nonlocal i
            i += 1
            print(f'{e.args[0]}:{i}')
            t2 = time.time()
            if i == n:
                print(f'spending time:{round(t2 - t1, 2)}')

    return wrapper

54 global 声明全局变量

# 先回答为什么要有 global,一个变量被多个函数引用,想让全局变量被所有函数共享。有的伙伴可能会想这还不简单,这样写:
i = 5
def f():
	print(i)
def g():
	print(i)
	pass
	
f()
g()

f 和 g 两个函数都能共享变量 i,程序没有报错,所以他们依然不明白为什么要用global. 但是,如果我想要有个函数对 i 递增,这样:

def h():
i += 1
h()

此时执行程序,bang, 出错了!抛出异常:UnboundLocalError,原来编译器在解释 i+=1 时会把 i 解析为函数 h() 内的局部变量,很显然在此函数内,编译器找不到对变量 i 的定义,所以会报错。

global 就是为解决此问题而被提出,在函数 h 内,显示地告诉编译器 i 为全局变量,然后编译器会在函数外面寻找 i 的定义,执行完 i+=1 后,i 还为全局变量,值加 1:

i = 0
def h():
global i i += 1
h()
print(i)

55 链式比较

i = 3
print(1 < i < 3) # False
print(1 < i <= 3) # True

56 不用else和if实现计算器

from operator import *

def calulator(a, b, k):
	return{
		'+': add,
		'-': sub,
		'/': mul,
		'**': pow
	}[k](a,b)
	
calulator(1, 2, '+') # 3
calulator(3, 4, '**') # 81


57 链式操作

from operator import (add, sub)

def add_or_sub(a, b, oper):
	return (add if oper == '+' else sub)(a, b)
	
add_or_sub(1, 2, '-') # -1

58 交换两元素

def swap(a, b)
	return b, a
	
print(swap(1, 0))	# (0, 1)

59 去最求平均

def score_mean(lst):
	lst.sort()
	lst2 = lst[1:(len(lst)-1)]
	
	return round((sum(lst2)/len(lst2)), 1)
	
lst=[9.1, 9.0,8.1, 9.7, 19,8.2, 8.6,9.8]
score_mean(lst) # 9.1

60 打印99乘法表

打印出如下格式的乘法表

1*1=1 
1*2=2 2*2=4 
1*3=3 2*3=6 3*3=9 
1*4=4 2*4=8 3*4=12 4*4=16
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 ␣ ,→9*9=81

一共有 10 行,第 i 行的第 j 列等于:j*i, 其中, i 取值范围:1<=i<=9 j 取值范围:1<=j<=i 根据例子分析的语言描述,转化为如下代码:

for i in range(1, 10):
	for j in range(1, i+1):
		print('%d * %d = %d' %(j,i,j*i), end='\t')
	print()

61 全展开

# 对于如下数组:
[[[1,2,3],[4,5]]]

如何完全展开成一维的。这个小例子实现的flatten是递归版,两个参数分别表示带展开的数组,输出数组。

from collections.abc import *

def flatten(lst, out_lst=None):
	if out_lst is None:
		out_lst = []
	for i in lst:
		if isinstance(i, Iterable):	#判断 i 是否可迭代
			flatten(i, out_lst)	#尾数递归
		else:
			out_lst.append(i)	# 产生结果
	
	return out_lst
	
#调用flatten:
print(flatten([[1,2,3],[4,5]]))
print(flatten([[1,2,3],[4,5]], [6,7]))
print(flatten([[[1,2,3],[4,5,6]]]))

62 列表等分

from math import ceil


def divide(lst, size):
    if size <= 0:
        return [lst]
    return [lst[i * size: (i + 1) * size] for i in range(0, ceil(len(lst) / size))]


r = divide([1, 3, 5, 7, 9], 2)
print(r)

-> [[1, 3], [5, 7], [9]]


r = divide([1, 3, 5, 7, 9], 2)
print(r)

-> [[1, 3, 5, 7, 9]]

63 列表压缩-过滤空的

def filter_false(lst):
	return list(filter(bool, lst))
	
r = filter_false([None, 0, False, '', [], 'ok', [1,2]])
print(r)

64 最长的列表是哪个

def max_length(*lst):
	return max(*lst, key=lambda v: len(v))
	
r = max_length([1,2,3], [4,5,6,7], [8])
print(f'更长的列表是{r}')

-> 更长的列表是[4, 5, 6, 7]

65 求众数

def top1(lst):
    return max(lst, default='列表为空', key=lambda v: lst.count(v))


lst = [1, 3, 3, 2, 1, 1, 2]
r = top1(lst)
print(f'{lst}中出现次数最多的元素为:{r}')

-》 [1, 3, 3, 2, 1, 1, 2]中出现次数最多的元素为:1

66 多表之最

def max_lists(*lst):
	return max(max(*lst, key=lambda v : max(v)))
	
r = max_lists([1,2,3], [6,7,8], [4,5])
print(r)
->8

67 列表查重

def has_duplicates(lst):
	return len(lst) == len(set(lst))
	
x = [1,1,2,2,3,2,3,4,5,6]
y = [1,2,3,4,5]
has_duplicates(x) # False
has_duplicates(y) # True


68 列表反转

def reverse(lst):
    return lst[::-1]


x = [1, 1, 2, 2, 3, 2, 3, 4, 5, 6]
print(reverse(x))

-》 [6, 5, 4, 3, 2, 3, 2, 2, 1, 1]

69 浮点数等差数列

def rang(start, stop, n):
    start, stop, n = float('%.2f' % start), float('%.2f' % stop), int('%.d' % n)
    step = (stop - start) / n
    lst = [start]
    while n > 0:
        start, n = start + step, n - 1
        lst.append(round((start), 2))
    return lst




r = rang(1, 8, 10)
print(r)

C:\Python36\python.exe C:/mycode/awesome-python-io/run_test_code/run_基本功_python小例子.py
[1.0, 1.7, 2.4, 3.1, 3.8, 4.5, 5.2, 5.9, 6.6, 7.3, 8.0]

70 按条件分组

def bif_by(lst, f):
    return [[x for x in lst if f(x)], [x for x in lst if not f(x)]]


records = [25, 89, 31, 34]
r = bif_by(records, lambda x: x < 80)
print(r)
-》 [[25, 31, 34], [89]]

71 map 实现向量运算

# 多序列运算函数-map(fuction, iterabel, iterabel2)
lst1 = [1, 2, 3, 4, 5, 6]
lst2 = [3, 4, 5, 6, 3, 2]
r = list(map(lambda x, y: x * y + 1, lst1, lst2))
print(r)

C:\Python36\python.exe C:/mycode/awesome-python-io/run_test_code/run_基本功_python小例子.py
[4, 9, 16, 25, 16, 13]

72 值最大的字典

def max_pairs(dic):
    if len(dic) == 0:
        return dic
    max_val = max(map(lambda v: v[1], dic.items()))
    return [item for item in dic.items() if item[1] == max_val]


r = max_pairs({'a': -10, 'b': 5, 'c': 3, 'd': 5})
print(r)
C:\Python36\python.exe C:/mycode/awesome-python-io/run_test_code/run_基本功_python小例子.py
[('b', 5), ('d', 5)]

73 合并两个字典

def merge_dict(dict1, dict2):
    return {**dict1, **dict2}  # python3.5后支持一行代码实现合并字典


r = merge_dict({'a': 1, 'b': 2}, {'c': 3})
print(r)

C:\Python36\python.exe C:/mycode/awesome-python-io/run_test_code/run_基本功_python小例子.py
{'a': 1, 'b': 2, 'c': 3}


# 一行代码实现
# 一行代码实现
a = {'c': 3}
b = {'a': 1, 'b': 2}
a.update(b)
print(a)

74 topn字典

from heapq import nlargest


# 返回字典d 前n个最大值对应的键
def topn_dict(d, n):
    return nlargest(n, d, key=lambda k: d[k])


r = topn_dict({'a': 1, 'b': 8, 'c': 8, 'd': 11}, 3)
print(r)

C:\Python36\python.exe C:/mycode/awesome-python-io/run_test_code/run_基本功_python小例子.py
['d', 'b', 'c']

75 异位词

from collections import Counter


# 检查两个字符是否 相同字母异序词,简称:互为变位词

def anagram(str1, str2):
    return Counter(str1) == Counter(str2)


r = anagram('eleven+two', 'twelve+one')  # True 这是一对神器的变位词
print(r)
anagram('eleven', 'twelve')  # False

76 逻辑上合并字典

(1) 看73,修改 merged[‘x’]=10,dic1 中的 x 值不变,merged 是重新生成的一个新字典。
(2)但是,ChainMap 却不同,它在内部创建了一个容纳这些字典的列表。因此使用
ChainMap 合并字典,修改 merged[‘x’]=10 后,dic1 中的 x 值改变,如下所示:

from collections import ChainMap

dict1 = {'x': 1, 'y': 2}
dict2 = {'y': 3, 'z': 4}
merged2 = ChainMap(dict1, dict2)
print(merged2)

C:\Python36\python.exe C:/mycode/awesome-python-io/run_test_code/run_基本功_python小例子.py
ChainMap({'x': 1, 'y': 2}, {'y': 3, 'z': 4})

77 命名元组提高可读性

from collections import namedtuple

Point = namedtuple('Point', ['x', 'y', 'z'])  # 定义名为Point的元组,字段数组有x,y,z
lst = [Point(1.5, 2, 3.0), Point(-0.3, -1.0, 2.1), Point(1.3, 2.8, -2.5)]
print(lst[0].y - lst[1].y) # 3

78 样本抽样

# 使用sample抽样,如下例子从100个样本中随机抽样10个
from random import randint, sample

lst = [randint(0, 50) for _ in range(100)]
print(lst[:5])
lst_sample = sample(lst, 10)
print(lst_sample)

79 重洗数据集

# 使用shuffle 来冲洗数据集,值得注意"shuffle"是对lst就地(in place)洗牌,节省存储空间

from random import shuffle
from random import randint

lst = [randint(0, 50) for _ in range(100)]
print(lst)
shuffle(lst)
print(lst[:5])

80 10个均匀分布的坐标点

# random模块中的uniform(a,b)生成[a,b)内的一个随机数,如下生成10个均匀分布的二维坐标点
from random import uniform

r = [(uniform(0, 10), uniform(0, 10)) for _ in range(10)]
print(r)


81 10个高斯分布的坐标点

random模块中的gauss(u, sigma)生成均值为u, 标准差为sigma的满足高斯分布的值,如下生成10个二维坐标点,样本误差(y-2*x-1)满足均值为0,标准差为1的高斯分布:
from random import gauss

x = range(10)
y = [2 * xi + 1 + gauss(0, 1) for xi in x]
points = list(zip(x, y))
print(points)

82 chain高效串联多个容器对象

chain函数串联a和b,兼顾内存效率同时写法更加优雅

from itertools import chain

a = [1, 3, 4, 0]
b = (2, 4, 6)

for i in chain(a, b):
    print(i)


83 操作函数对象

def f():
	print('i\'m f')
	
def g():
	print('i\'m g')

[f,g][1]()

84 生成逆序序列

list(range(10, -1, -1))		# [10,9,8,7,6.5,4,3,2,1,0]

第三个参数为负时,表示从第一个参数开始递减,终止到第二个参数(不包括此边界)


85 函数的五类参数使用例子

python 五类参数:位置参数,关键字参数,默认参数,可变位置或关键字参数的使用

def f(a, *b, c=10, **d):
	print(f'a:{a}, b:{b}, c:{c}, d:{d}')

默认参数“c”不能位于可变关键字参数“d”后。

调用f: In [10]: f(1,2,5,width=10,height=20) a:1,b:(2, 5),c:10,d:{‘width’: 10, ‘height’: 20}

可变位置参数b实参后被解析为元组(2, 5);而取得默认值10;d被解析为字典

再次调用f: In [11]: f(a=1,c=12) a:1,b:(),c:12,d:{}

a=1 传入时 a 就是关键字参数,b,d 都未传值,c 被传入 12,而非默认值。 注意观察参数 a, 既可以 f(1), 也可以 f(a=1) 其可读性比第一种更好,建议使 用 f(a=1)。如果要强制使用 f(a=1),需要在前面添加一个星号:

def f(*, a, *b):
	print(f'a:{a}, b:{b}')

此 时 f(1) 调 用, 将 会 报 错:TypeError: f() takes 0 positional arguments but 1 was given 只能 f(a=1) 才能 OK. 说明前面的 * 发挥作用,它变为只能传入关键字参数,那么如何查看这个参数的 类型呢?借助 python 的 inspect 模块:

for name, val in signature(f).parameters.items():
	print(name, val.kind)

a KEYWORD_ONLY
b VAR_KEYWORD

可看到参数 a 的类型为 KEYWORD_ONLY,也就是仅仅为关键字参数。 但是,如果 f 定义为

def f(a, *b):
	print(f'a:{a}, b:{b}')

查看参数类型:

for name, val in signature(f).parameters.items():
	print(name, val.kind)

a POSITIONAL_OR_KEYWORD
b VAR_POSITIONAL

可以看到参数 a 既可以是位置参数也可是关键字参数。

86 使用slice对象

生成关于蛋糕的序列cake 1:

cake1 = list(range(5, 0, -1))
b  = cake1[1:10:2]
print(b)
->[4, 2]
print(cake1)
-> [5, 4, 3, 2, 1]

再生成一个序列:
from random imporr randint
	cake2 = [randint(1, 100) for _ in range(100)]
	# 同样以间隔为2切前10个元素, 得到切片d
	d = cake2[1:10:2]
print(d)
-> [75, 33, 63, 93, 15]

你看,我们使用同一种切法,分别切开两个蛋糕 cake1,cake2. 后来发现这种切法极 为经典,又拿它去切更多的容器对象。 那么,为什么不把这种切法封装为一个对象呢?于是就有了 slice 对象。 定义 slice 对象极为简单,如把上面的切法定义成 slice 对象:

perfect_cake_slice_way = slice(1,10,2) # 去切 cake1
cake1_slice = cake1[perfect_cake_slice_way]
cake2_slice = cake2[perfect_cake_slice_way]
In [11]: cake1_slice
Out[11]: [4, 2]
In [12]: cake2_slice
Out[12]: [75, 33, 63, 93, 15]

与上面的结果一致。 对于逆向序列切片,slice 对象一样可行:

a = [1,3,5,7,9,0,3,5,7]
a_ = a[5:1:-1]
named_slice = slice(5,1,-1)
a_slice = a[named_slice]
In [14]: a_
Out[14]: [0, 9, 7, 5]
In [15]: a_slice
Out[15]: [0, 9, 7, 5]

频繁使用同一切片的操作可使用 slice 对象抽出来,复用的同时还能提高代码可读 性。

上面的基础实际为86个

Python 字符串和正则22个

字符串无所不在,字符串的处理也是最常见的操作。本章节将总结和字符串处理相关的 一切操作。主要包括基本的字符串操作;高级字符串操作之正则。目前共有 20 个小例 子

1 反转字符串

str = "python"
# 方法1
''.join(reversed(str))

# 方法2
str[::-1]

2 字符串切片操作

# 字符串切片操作——查找替换 3 或 5 的倍数
[ str("java"[i%3*4:] + "python"[i%5*6:]) for i in range(1,15)]
OUT[1]:['1',
'2',
'java',
'4',
'python',
'java',
'7',
'8',
'java',
'python',
'11',
'java',
'13',
'14']

3 join 串联字符串

mystr = ['1', '2', 'java', '4','python']
','.join(mystr) # 用逗号连接字符串

4 字符串的字节长度

def str_byte_len(mystr):
	return (len(mystr.encode('utf-8')))
	
str_byte_len('i love python') # 13(个字节)
str_byte_len('字符') # 6(个字节)

5 查找第一个匹配串

import re
s = 'i love python very much'
pat = 'python'
r = re.search(pat, s)
print(r.span())	# (7,13)

6 查找所有1的索引

s = '山东省潍坊市青州第 1 中学高三 1 班'
pat = '1'
r = re.finditer(pat,s)
for i in r:
print(i)

7 \d 匹配数字0-9

findall 找出全部位置的所有匹配

s = '一共 20 行代码运行时间 13.59s'
pat = r'\d+' # + 表示匹配数字 (\d 表示数字的通用字符)1 次或多次
print(r)
-> ['20', '13', '59']

8 匹配浮点数和整数

? 表示前一个字符匹配 0 或 1 次

s = '一共 20 行代码运行时间 13.59s'
pat = r'\d+\.?\d+'   # ? 表示匹配小数点 (\.)0 次或 1 次,这种写法有个小bug,不能匹配到个位数的整数

r = re.findall(pat, s)
print(r)
->  ['20', '13.59']

# 更好的写法:
pat = r'\d+\.\d+|\d+'  # A| B, 匹配A失败才匹配B

9 ^ 匹配字符串的开头

s = 'This module provides regular expression matching operations, similar to those found in Perl'
pat = r'^[emrt]' # 查找以字符 e,m,r 或 t 开始的字符串
r = re.findall(pat,s)
print(r)
# [], 因为字符串的开头是字符`T`,不在 emrt 匹配范围内,所以返回为空
IN [11]: s2 = 'email for me is guozhennianhua@163.com'
re.findall('^[emrt].*',s2)# 匹配以 e,m,r,t 开始的字符串,后面是多个任意字符
Out[11]: ['email for me is guozhennianhua@163.com']

10 re.I 忽略大小写

s = 'That'
pat = r't' r = re.findall(pat,s,re.I)
In [22]: r
Out[22]: ['T', 't']


11 理解 compile 的作用

如果要做很多次匹配,可以先编译匹配串:

import re
pat = re.compile('\W+') # \W 匹配不是数字和字母的字符
has_special_chars = pat.search('ed#2@edc')
if has_special_chars:
print(f'str contains special characters:{has_special_chars.
,→group(0)}')
### 输出结果:
# str contains special characters:#
### 再次使用 pat 正则编译对象 做匹配
again_pattern = pat.findall('guozhennianhua@163.com')
if '@' in again_pattern:
print('possibly it is an email')

12 使用 () 捕获单词,不想带空格

s = 'This module provides regular expression matching operations␣ ,similar to those found in Perl'
pat = r'\s([a-zA-Z]+)' r = re.findall(pat,s)
print(r) #['module', 'provides', 'regular', 'expression', 'matching
,', 'operations', 'similar', 'to', 'those', 'found', 'in', 'Perl']

看到提取单词中未包括第一个单词,使用? 表示前面字符出现 0 次或 1 次,但是此 字符还有表示贪心或非贪心匹配含义,使用时要谨慎。

s = 'This module provides regular expression matching operations␣ ,similar to those found in Perl'
pat = r'\s?([a-zA-Z]+)'


r = re.findall(pat,s)
print(r) #['This', 'module', 'provides', 'regular', 'expression',
,'matching', 'operations', 'similar', 'to', 'those', 'found', 'in',
, 'Perl']

13 split 分割单词

使用以上方法分割单词不是简洁的,仅仅是为了演示。分割单词最简单还是使用 split 函数。

s = 'This module provides regular expression matching operations␣ ,→similar to those found in Perl'
pat = r'\s+' r = re.split(pat,s)
print(r) # ['This', 'module', 'provides', 'regular', 'expression',
,→'matching', 'operations', 'similar', 'to', 'those', 'found', 'in',
,→ 'Perl']
### 上面这句话也可直接使用 str 自带的 split 函数:
s.split(' ') # 使用空格分隔
### 但是,对于风格符更加复杂的情况,split 无能为力,只能使用正则
s = 'This,,, module ; \t provides|| regular ; '
words = re.split('[,\s;|]+',s) # 这样分隔出来,最后会有一个空字符串
words = [i for i in words if len(i)>0]

14 match 从字符串开始位置匹配

注意 match,search 等的不同: 1) match 函数

import re
### match
mystr = 'This'
pat = re.compile('hi')
pat.match(mystr) # None
pat.match(mystr,1) # 从位置 1 处开始匹配
Out[90]: <re.Match object; span=(1, 3), match='hi'>

2) search 函数 search 是从字符串的任意位置开始匹配

 In [91]: mystr = 'This' ...: pat = re.compile('hi') ...: pat.search(mystr)
Out[91]: <re.Match object; span=(1, 3), match='hi'>

15 替换匹配的子串

sub 函数实现对匹配子串的替换

content="hello 12345, hello 456321"
pat=re.compile(r'\d+') # 要替换的部分
m=pat.sub("666",content)
print(m) # hello 666, hello 666

16 贪心捕获

(.*) 表示捕获任意多个字符,尽可能多的匹配字符

content='<h>ddedadsad</h><div>graph</div>bb<div>math</div>cc'
pat=re.compile(r"<div>(.*)</div>") # 贪婪模式
m=pat.findall(content)
print(m) # 匹配结果为: ['graph</div>bb<div>math']

17 非贪心捕获

仅添加一个问号 (?),得到结果完全不同,这是非贪心匹配,通过这个例子体会贪心和 非贪心的匹配的不同。

content='<h>ddedadsad</h><div>graph</div>bb<div>math</div>cc'
pat=re.compile(r"<div>(.*?)</div>") m=pat.findall(content)
print(m) # ['graph', 'math']

18 常用元字符总结

. 匹配任意字符
^ 匹配字符串开始位置
$ 匹配字符串中结束的位置
* 前面的原子重复 0 次、1 次、多次
? 前面的原子重复 0 次或者 1 次 + 前面的原子重复 1 次或多次
{n} 前面的原子出现了 n 次
{n,} 前面的原子至少出现 n 次
{n,m} 前面的原子出现次数介于 n-m 之间
( ) 分组, 需要输出的部分

19 常用通用字符总结

\s 匹配空白字符
\w 匹配任意字母/数字/下划线
\W 和小写 w 相反,匹配任意字母/数字/下划线以外的字符
\d 匹配十进制数字
\D 匹配除了十进制数以外的值
[0-9] 匹配一个 0-9 之间的数字
[a-z] 匹配小写英文字母
[A-Z] 匹配大写英文字母

20 爬取百度首页标题


import re
from urllib import request
# 爬虫爬取百度首页内容
data=request.urlopen("http://www.baidu.com/").read().decode()
# 分析网页, 确定正则表达式
pat=r'<title>(.*?)</title>'
result=re.search(pat,data)
print(result) <re.Match object; span=(1358, 1382), match='<title> 百
度一下,你就知道</title>'>
result.group() # 百度一下,你就知道

21 批量转化为驼峰格式 (Camel)

数据库字段名批量转化为驼峰格式 分析过程

# 用到的正则串讲解
# \s 指匹配: [ \t\n\r\f\v]
# A|B:表示匹配 A 串或 B 串
# re.sub(pattern, newchar, string):
# substitue 代替,用 newchar 字符替代与 pattern 匹配的字符所有.


# title(): 转化为大写,例子:
# 'Hello world'.title() # 'Hello World'


# print(re.sub(r"\s|_|", "", "He llo_worl\td"))
s = re.sub(r"(\s|_|-)+", " ", 'some_database_field_name').title().replace(" ", "") # 结果: SomeDatabaseFieldName


# 可以看到此时的第一个字符为大写,需要转化为小写
s = s[0].lower()+s[1:] # 最终结果

整理以上分析得到如下代码:

import re
def camel(s):
	s = re.sub(r"(\s|_|-)+", " ", s).title().replace(" ", "")
	return s[0].lower() + s[1:]
# 批量转化
def batch_camel(slist):
	return [camel(s) for s in slist]

测试结果:

s = batch_camel(['student_id', 'student\tname', 'student-add'])
print(s)
# 结果
['studentId', 'studentName', 'studentAdd']

22 密码安全检查

密码安全要求:1) 要求密码为 6 到 20 位; 2) 密码只包含英文字母和数字

pat = re.compile(r'\w{6,20}') # 这是错误的,因为\w 通配符匹配的是字母,数字和下
划线,题目要求不能含有下划线
# 使用最稳的方法:\da-zA-Z 满足`密码只包含英文字母和数字`
pat = re.compile(r'[\da-zA-Z]{6,20}')

选用最保险的 fullmatch 方法,查看是否整个字符串都匹配

pat.fullmatch('qaz12') # 返回 None, 长度小于 6
pat.fullmatch('qaz12wsxedcrfvtgb67890942234343434') # None 长度大于 22
pat.fullmatch('qaz_231') # None 含有下划线
pat.fullmatch('n0passw0Rd')
Out[4]: <re.Match object; span=(0, 10), match='n0passw0Rd'>

【环境】 win10_x64 + python3.6.5

【Me】 https://github.com/Valuebai/ https://valuebai.github.io/

【参考】 1、出处:https://github.com/jackzhenguo/python-small-examples