Python基础 - 字符串处理

引入

平时工作中, 80% 时间都在跟字符串打交道, 字符串的处理,是编程语言中, 尤其重要的. Python 变得比较流行, 一个大原因, 用 Pandas 的第一作者的话说, 大概是 Python 提供了大量能处理 字符串的 api 了吧.

type("油哥")
str
type('油哥'.encode('gbk'))  # 编码成字节串,采用GBK编码 
bytes
type('油哥'.encode()) == bytes
True
'中国'.encode()  # 默认使用 Utf-8 进行编码
b'\xe4\xb8\xad\xe5\x9b\xbd'
_.decode()  # 默认用 Utf-8 进行解码
'中国'
bytes('油哥', 'gbk')
b'\xd3\xcd\xb8\xe7'
str(_, 'gbk')
'油哥'

字符串编码格式简介

  • ASCII码: 仅对0-9, A-Z, a-z,特殊字符,进行了编码,1个字节byte对字符编码,最多只能表示256个字符
  • UTF-8: 1个字节表示英文字符(兼容ASCII),以3个字节byte表示中文,还有些使用2或4字节的
  • GB2312: 我国制定,英文1byte, 中文2byte,GBK是GB2312上的扩充
  • CP936: GB2312, GBK, CP936, 都是使用2byte 表示中文
  • 不同的编码格式意味着不同的表示和存储形式,对字符的编码, 解码在一定程度上具有加密的效果
  • Python3 完全支持中文字符,默认用UTF-8编码,甚至可以用中文作为变量名, 函数名等标识符
import sys
sys.getdefaultencoding()  # 查看默认编码格式 为 UTF-8
'utf-8'
s = '油哥'
len(s)  # 字符串长度,包含字符的个数
2
s = '油哥 ABCDEFG'
len(s)  # 中英文同样对待,都是一个字符(空格算一个字符)
10
姓名 = '油哥'  # 使用中文作为变量名

print(姓名)  # 输出变量的值
油哥

转义字符

姓名 年龄
油油 22

\b: 退格,把光标移动到前一列位置
\f: 换页符
\n: 换行符
\r: 回车
\t: 水平制表符
\v: 垂直制表符
\: 一个斜杠\
': 单引号
\ '': 双引号
\xhh 2位16进制数对应字符
\uhhhh: 4位16进制数表示的Unicode字符

print('hello \nworld')  # \n 换行
hello 
world
print('\101')  # 3位8进制数对应的字符
A
print('\x41')  # 2位16进制对应的字符
A

为了避免对字符串中的转义字符进行转义,可使用原始字符串(前面加上 r),表示原始字串而不被转义

path = 'C:\Windos\notepad.exe'
print(path)  # 被认为含有转义字符,被转义了
C:\Windos
otepad.exe
path = r"C:\Windos\notepad.exe"  # 原始字符串,任何字符不被转义
print(path)
C:\Windos\notepad.exe

字符串格式化

用 % 符号进行格式化

'% [-] [+] [0] [m] [.n] 格式字符' % x

即: 格式标志, 制定左对齐,,对证书加正号, 空位填0, 指定最小宽度, 精度, 类型, 格式运算符, 待转换的表达式
常用:
%s 字符串
%r 字符串(采用repr()显示)
%d 十进制整数
%.2f 保留2位浮点数
%% 一个百分号

x = 'hello world'
print('xxx %s' % x)
xxx hello world
x = 1234.778
print('the score is: %.2f' % x)
the score is: 1234.78

format( )方法格式化字符串

支持关键字参数格式化, 支持序列解包格式化字符串, 支持在数字间用 _ 分隔以提高数字可读性

1 / 3
0.3333333333333333
print('{0: .3f}'.format(1/3))
 0.333
"{0:_}, {0:_x}".format(1000000)  # 没什么意思,感觉还不如 % 直观
'1_000_000, f_4240'

格式化的字符串常量

name, age = 'chenjie', 22
x = f"My name is {name}, and i am {age} years ld."

print(x)
My name is chenjie, and i am 22 years ld.

字符常用串操作

字符串对象不可变,涉及字符串修改返回后的都是新字符串,并不对原字符串做任何修改,无一例外

find(), rfine(), index(), rinex(), count() 查找统计

s = "apple, peach, banana, peach, pear"
s.find('peach')  # 返回第一次出现的位置
7

Docstring:
S.find(sub[, start[, end]]) -> int

Return the lowest index in S where substring sub is found,
such that sub is contained within S[start:end]. Optional
arguments start and end are interpreted as in slice notation.

Return -1 on failure.

s.find('peach', 8)  # 从index 7 开始往后找
22
s.find('peach', 8, 20)  # 指定从8 - 20 范围内找
-1
s.rfind('p')  # 从右往左找,但索引值仍然是左起
29
s.index('p')
1
s.rindex('p')
29
s.index('xxx')  # find 与 index 的区别在于 find 没找到返回-1, insex 没找到会报错
---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-62-636e77087d3c> in <module>
----> 1 s.index('xxx')  # find 与 index 的区别在于 find 没找到返回-1, insex 没找到会报错


ValueError: substring not found
s.count('p')  # 统计字符出现的次数,没有则返回0
5
s.count('peach')  #词频统计?? 不知和字典谁更好写呢,待测量
2
s.count('xxx')  # 不存在返回0
0

split(), rsplit(), partition(), rpatition() 分隔

s = "apple, peach, banana, peach, pear"
s.split(',')  # 使用逗号分隔(默认为 空格),返回列表形式
['apple', ' peach', ' banana', ' peach', ' pear']

Docstring:
S.split(sep=None, maxsplit=-1) -> list of strings

Return a list of the words in S, using sep as the
delimiter string. If maxsplit is given, at most maxsplit
splits are done. If sep is not specified or is None, any
whitespace string is a separator and empty strings are
removed from the result.

s = '2018-11-02'
s.split('-')
['2018', '11', '02']
list(map(int, s.split('-')))  # 将分隔结果转换为整数
[2018, 11, 2]
s = '\n\nhello\t\tworldn\n\n My name\t is \t chenjie'
s.split()  # 不指定则任意空白符分割(空格,换行,制表符)
['hello', 'worldn', 'My', 'name', 'is', 'chenjie']
s.split(maxsplit=3)  # 指定最大分割次数
['hello', 'worldn', 'My', 'name\t is \t chenjie']
s = "apple, peach, banana, peach, pear"
s.partition(',')  # 将字符串分为3个部分, 返回元组
('apple', ',', ' peach, banana, peach, pear')

Docstring:
S.partition(sep) -> (head, sep, tail)

Search for the separator sep in S, and return the part before it,
the separator itself, and the part after it. If the separator is not
found, return S and two empty strings.

s.partition('banana')
('apple, peach, ', 'banana', ', peach, pear')
s.rpartition('peach')
('apple, peach, banana, ', 'peach', ', pear')
s.partition('xxx')  # 没有找到则返回原字符串,后面添2逗号(默认)
('apple, peach, banana, peach, pear', '', '')

join() 连接

Docstring:
S.join(iterable) -> str

Return a string which is the concatenation of the strings in the
iterable. The separator between elements is S.

li = ['apple', 'peach', 'banana', 'peach', 'pear']  # 形参为可迭代对象
sep = ','  # 指定逗号为连接符

sep.join(li)  # 语法: 连接符.join(可迭代对象),  即将可迭代对象,有(分隔符)连接成一个字符串
'apple,peach,banana,peach,pear'
':'.join(li) # 用 : 来连接 可迭代里面的元素,整体作为一个字符串返回
'apple:peach:banana:peach:pear'
''.join(li)  # 使用空字符来连接元素
'applepeachbananapeachpear'
''.join([1,2,3,4,5,'cj'])  # 可迭代对象里面的元素,需要也是 isinstance(element, str)
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-92-4d08bca0998d> in <module>
----> 1 ''.join([1,2,3,4,5,'cj'])  # 可迭代对象里面的元素,需要也是 isinstance(element, str)


TypeError: sequence item 0: expected str instance, int found
''.join(str([1,2,3,4, 'cj']))  # 确保 可迭代对象是str
"[1, 2, 3, 4, 'cj']"

split() 和join()组合,可以删掉字符串多余的空白字符,连续多个空白字符,只保留一个

x = 'aaa bb cc        dd e   ff  g'

''.join(x.split())  # 删除多余空白符,这个有点厉害
'aaabbccddeffg'

lower(), upper(), capitalize(), title(), swapcase() 大小写, 首字母

s = 'What is Your Name?'
s.lower()  # 返回小写字母
'what is your name?'
s.upper()  # 返回大写字母
'WHAT IS YOUR NAME?'
s.capitalize()  # 首字母大写
'What is your name?'
s.title()  # 每个单词首字母大写
'What Is Your Name?'
s.swapcase()  # 大小写转换
'wHAT IS yOUR nAME?'

raplace(), marketrans(), translate() 单次, 多次 查找替换

s = "中国, 中国"

s.replace('中国', '中华人民共和国')  
'中华人民共和国, 中华人民共和国'
print('abcdabc'.replace('abc', 'ABC'))  # 一键替换,很厉害
ABCdABC
a1 = 'aaa'.replace('x', 'xxx')  # 没有找到,old, 则返回原字符串,注意,此时没有返回 新对象哦
print(id(a1))
114211397336
a2 =  'aaa'
print(id(a2))
114211397336

字符串对象的maketrans() 方法用来生成字符映射表, 而translate() 方法根据映射表实现字符串替换

# 创建映射表, 将字符 "abcdef123"  对应地转换为"uvwxyz@#$"
table = ''.maketrans('abcdef123', 'uvwxyz@#$')  # 一 一对应转换

s = 'Python is a great programming language. I like it.'

# 按映射表进行替换, 实现了加密的效果
s.translate(table)
'Python is u gryut progrumming lunguugy. I liky it.'

Signature: s.maketrans(x, y=None, z=None, /)
Docstring:
Return a translation table usable for str.translate().

If there is only one argument, it must be a dictionary mapping Unicode
ordinals (integers) or characters to Unicode ordinals, strings or None.
Character keys will be then converted to ordinals.

If there are two arguments, they must be strings of equal length, and
in the resulting dictionary, each character in x will be mapped to the
character at the same position in y. If there is a third argument, it
must be a string, whose characters will be mapped to None in the result.

Docstring:
S.translate(table) -> str

Return a copy of the string S in which each character has been mapped
through the given translation table. The table must implement
lookup/indexing via getitem, for instance a dictionary or list,
mapping Unicode ordinals to Unicode ordinals, strings, or None. If
this operation raises LookupError, the character is left untouched.
Characters mapped to None are deleted.

案例: 用字符的maketrans() 和 translate() 实现凯撒加密算法

string.ascii_letters
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
import string

def kaisa(s, k):
    """把字符串 s 用密钥 k 凯撒加密,即将字符从索引k截断,后面的放前面"""
    lower = string.ascii_lowercase  # 小写字母
    upper = string.ascii_uppercase  # 大写字母
    
    before = string.ascii_letters # 'abcd...zABC...Z'
    after = lower[k:] + lower[: k] + upper[k: ] + upper[: k]
    
    table = s.maketrans(before, after)  # 创建映射表
    
    return s.translate(table)  # 将映射表作为形参,实现字符串的,替换,按照映射关系

s = 'Python is a grate programming language, I like it.'

print(kaisa(s, 2))

s1 = " If the implementation is easy to explain, it may be a good idea."
print(kaisa(s, 3))

Ravjqp ku c itcvg rtqitcookpi ncpiwcig, K nkmg kv.
Sbwkrq lv d judwh surjudpplqj odqjxdjh, L olnh lw.

strip(), rstrip(), lstrip() 删除空白(或指定)字符, 理解"两侧, 左侧, 右侧的区别"

s1 = "  abc  "
print(id(s1))

s2 = s1.strip()  # 生成了新的字符串, 删除空白符
print(id(s2))
print(s2)
55024608176
55024554984
abc
'\n\nhello word \n\n   '.strip()  # 删除空白符, 两侧
'hello word'
"abaaaaassddf".strip('abs')  #  删除指定字符串  只有有'abs'都要删除, 理解"两侧"
'ddf'
"aaaaaaddfaaa".rstrip('a')  # 删除字符串右端指定字符, 遇到阻碍就不删了, 具有"惰性特点"
'aaaaaaddf'
"aaaaaaddfaaa".lstrip('fa')  # 删除字符串左端指定字符, 遇到阻碍就不删了,具有"惰性特点"
'ddfaaa'
"aabbccddeeefffgg".strip('bf')  # b, f,都不在字符串的两侧,所以不会删除任何东西, 地址也不会变化
'aabbccddeeefffgg'

startswith(), endswith() 指定字符串开头, 结尾

s = "Beatiful is better than ugly."
s.startswith('Be')
True
s.startswith('Be', 6)  # 指定检测范围的起始位置
False
s.endswith('ly.')
True
s.endswith('ly', -1, 10)  # 指定检测的开始/结束范围
False

列出指定文件夹下所有扩展名为bmp, jpg, gif的图片

import os

[filename for filename in os.listdir(r'D:\\') if filename.endswith(('.bmp', '.jpg', '.gif'))]
[]

isdigit(), isalpha(), isalnum(), isdecimal(), isnumeric(), isspace(), isupper(), islower() 数字,字符,大小写等

'666.666'.isdigit()  # 是否为数字 ??
False
'666.666'.isdecimal()  # 是否为十进制
False
'666.666'.isnumeric()  # why????
False
'1234'.isdigit()  # 全为数字?
True
'acddss'.isalpha()  # 全为字母?
True
'abcd123'.isalnum() # 仅为数字or字母
True
'abcd123@@'.isalnum()
False
'九'.isnumeric()  # 支持汉字数字
True
'IV'.isnumeric()  # 支持罗马数字
False

center(), ljust(), rjust, zfill() 字符排版

'Hello world'.center(20)  # 居中对齐,默认以空格进行填充
'    Hello world     '
'Hello, Python'.center(20, '*')  # 指定字符进行填充,(居中对齐)
'***Hello, Python****'
'Hello world'.ljust(20, '*')  # 左对齐
'Hello world*********'
'Hello world'.rjust(20)  # 右对齐
'         Hello world'
'cj'.zfill(5)  # 左侧填0补位
'000cj'
'cj'.zfill(1)  # 长度小于字符本身,返回原字符串
'cj'
'UFO'.zfill(20)
'00000000000000000UFO'

字符串对象支持的运算符

+, * , join

运算符 + 和 join() 方法的速度差异

import timeit

# 使用列表推导式生成10000个字符串
str_list = ['This is a long string that not keep in memory' for _ in range(10000)]  # 感觉很大空间呀要

def use_join():
    """使用join连接"""
    return ''.join(str_list)

def use_plus():
    result = ''
    for s in str_list:
        result = result + s
    return result

if __name__ == '__main__':
    
    # 重复执行次数
    times = 1000

    # 创建计时器对象
    join_time = timeit.Timer('use_join', 'from __main__ import use_join')  
    plus_time = timeit.Timer('use_plus', 'from __main__ import use_plus')

    print("Time for join: ", join_time.timeit(number=times))
    print("Time for plus: ", plus_time.timeit(number=times))

Time for join:  1.866125984406608e-05
Time for plus:  3.1257610316970386e-05
'abcd' * 3
'abcdabcdabcd'
'ab' in 'abcda'
True
'ax' in 'abcx'  # 将左边作为一个整体
False
'cj' not in 'xbdssd'
True

in + replce() 实现用户输入敏感词屏蔽

words = ('赌博', '非法', '暴力')

text = input('请输入: ')
for word in words:  # 是遍历 敏感词汇表哦
    if word in text:
        print("非法")
        break
else:
    print("正常")
请输入: 哈哈, 你很暴力哦
非法

将敏感词替换为3个***

words = ('赌博', '非法', '暴力')

text = input('请输入: ')
for word in words:  # 是遍历 敏感词汇表哦
    if word in text:
        text = text.replace(word, "***")
print(text)
请输入: 小明喜欢赌博,和有非法行为
小明喜欢***,和有***行为
words = ('赌博', '非法', '暴力')

text = '这句话里有非法内容'

import re
re.sub('|'.join(words), '***', text)
'这句话里有***内容'

内置函数应用于字符串

len('hello world')
11
max('hello word')  # 最大/最小字符
'w'
x = 'hello world'

list(zip(x, x))
[('h', 'h'),
 ('e', 'e'),
 ('l', 'l'),
 ('l', 'l'),
 ('o', 'o'),
 (' ', ' '),
 ('w', 'w'),
 ('o', 'o'),
 ('r', 'r'),
 ('l', 'l'),
 ('d', 'd')]
sorted(x)  # 默认升序
[' ', 'd', 'e', 'h', 'l', 'l', 'l', 'o', 'o', 'r', 'w']
list(enumerate(x))
[(0, 'h'),
 (1, 'e'),
 (2, 'l'),
 (3, 'l'),
 (4, 'o'),
 (5, ' '),
 (6, 'w'),
 (7, 'o'),
 (8, 'r'),
 (9, 'l'),
 (10, 'd')]
list(map(lambda i, j: i + j, x, x))  # 结合匿名函数/高阶函数/解包
['hh', 'ee', 'll', 'll', 'oo', '  ', 'ww', 'oo', 'rr', 'll', 'dd']
eval('1 + 1')  # 对字符串里的元素求值,并返回该值
2

字符串切片

s = 'hello word'
s[4:]
'o word'

字符串常量

import string
import random

# 将字母, 数字, 符号,拼接,然后生成随机密码
s = string.digits + string.ascii_letters + string.punctuation
# print(s)
def generate_random(n):
    """返回长度为n的随机字符"""
    return ''.join((random.choice(s) for _ in range(n)))
generate_random(6)  # 生成 6 位随机字符
']J:kHg'
generate_random(15)  # 生成 15位随机字符
']<H:4TJG(Yz%;qY'

中英文分词

jieba库

import jieba

s = "分词的准确度直接是影响了文本挖掘算法的最终呈现效果哦"

#  使用默认词库进行分词
jieba.cut(s)
<generator object Tokenizer.cut at 0x00000078379CDE60>
# jieba.cut??
list(_)  # 序列化
Building prefix dict from the default dictionary ...
Dumping model to file cache C:\Users\chenjie\AppData\Local\Temp\jieba.cache
Loading model cost 1.241 seconds.
Prefix dict has been built succesfully.





['分词',
 '的',
 '准确度',
 '直接',
 '是',
 '影响',
 '了',
 '文本',
 '挖掘',
 '算法',
 '的',
 '最终',
 '呈现',
 '效果',
 '哦']
list(jieba.cut('纸杯'))  # 词库已有的词
['纸杯']
list(jieba.cut('花纸杯'))  # 词库没有的词, 按照已有词库进行分词
['花', '纸杯']
jieba.add_word('花纸杯')  # 给默认词库增加新词
list(jieba.cut('花纸杯'))  # 测试新词是否可以使用了
['花纸杯']

制作词云图

wordcloud 库

import wordcloud
import matplotlib

def show(s):
    """生成词云图案"""
    wc = wordcloud.WordCloud(width=50, height=400, background_color='white')  # 创建词云对象
    t = wc.generate(s)  # 生成词云
    t.to_image().show()  # 绘制并显示词云
    
show("hello world 陈杰 陈杰 陈杰 陈杰 陈杰 python python python ")
    



精彩案例赏析

检查并判断字符串的安全强度

需求:

  • 不是字符串或字符串长度小于6,则认为不适合作为密码
  • 判断依据: 数字, 小写字母, 大写字母, 标点符号
  • 规则:
    • 满足其中1个, weak
    • 满足其中2个, below_middle
    • 满足其中3个, middle
    • 全满足, strong
import string

def check(passwd):
    """检查并判断字符串的安全强度"""
    # 必须是字符串且长度大于6
    if not isinstance(passwd, str) or len(passwd) < 6:
        return 'Not suitable for password.'
    
    d = {1:'weak', 2:'below_middle', 3:'middle', 4:'strong'}  # 条件数和等级的映射关系
    
    r = [False] * 4  # 记录是否含有数字,小写字母, 大写字母, 符号
    
    for s in passwd:
        if s in string.digits:  # 数字
            r[0] = True
        
        elif s in string.ascii_lowercase:  # 小写字母
            r[1] = True
        elif s in string.ascii_uppercase:  # 大写字母
            r[2] = True

        elif s in string.punctuation:  # 标点符号
              r[3] = True
                
    return d.get(r.count(True), 'error')

check('11111111Ab??')
'strong'
# 核心

import string

a_set = set()
grade = ('Weak', 'Below_middle', 'Middle', 'Strong')

passwd = 'xjfksjfsf134r.eew9'
for s in passwd:
    if s in string.digits:  # 数字
        a_set.add(1)
        
    elif s in string.ascii_lowercase:  # 小写字母
        a_set.add(2)
    elif s in string.ascii_uppercase:  # 大写字母
        a_set.add(3)
        
    elif s in string.punctuation:  # 标点符号
        a_set.add(4)
        
print(grade[len(a_set) -1] )
    
Middle
# 封装

def passwd_grade(s):
    "检查并判断密码的安全等级"\
    
    # 先校验字符和字符的长度要求
    if not isinstance(s, str) or len(s) < 6:
        return 'Not suitable for password.'

    import string

    a_set = set()  # 利用集合的自动去重
    grade = ['Weak', 'Below_middle', 'Middle', 'Strong']

    for s in s:
        if s in string.digits:  # 数字
            a_set.add(1)

        elif s in string.ascii_lowercase:  # 小写字母
            a_set.add(2)
            
        elif s in string.ascii_uppercase:  # 大写字母
            a_set.add(3)

        elif s in string.punctuation:  # 标点符号
            a_set.add(4)
#     print(a_set)
    return grade[len(a_set) -1] 

passwd_grade('888')
'Not suitable for password.'
passwd_grade('111111')
'Weak'
passwd_grade('111111111and')
'Below_middle'
passwd_grade('323,?Ac')
'Strong'

编写程序,生成大量随机信息

  • random 模块生成随机数据, 这在需要大量数据测试或演示软件功能时,非常有用, 不仅能真实展示软件的功能或算法, 还能避免泄露真实数据引起不必要的争议.

需求:

  • 生成n个人的随机信息,生成文件存储,字段包括: 姓名, 性别, 年龄, 手机号, 邮箱, 地址, 每一行代表一条数据

我的思考过程

1. 理清总体思路,分治法, 并写出基本框架(40%)

2. 写出关键的数据交互部分,即主程序(20%)

3. 实现各模块细节(20%)

4. 调试(10%)

5.重构和测试(10%)

a 分治思路

import random
import string

def get_name():
    pass

def get_sex():
    pass

def get_age():
    pass

def get_iphone():
    pass

def get_email():
    pass

def get_adress():
    pass

def random_data_to_file(file_name, n):
    """数据存入文件,传入文件名file_name和所需数据条数n"""
    pass

def output(filename, n):
    """数据显示"""
    pass  

def main():
    "主程序"
    random_data_to_file()  # 文件名, 条数
    output()  # 输出查看
    

b 主数据交互(觉得程序比较关键的地方),

  • 此处我觉得是输出,从文件中读取数据,每一行输出一条数据(姓名,性别, 年龄, 邮箱....)
  • 代码容易但此处要抽象出文件的结构,取指导前面的子模块
import random
import string

def get_name():
    pass

def get_sex():
    pass

def get_age():
    pass

def get_iphone():
    pass

def get_email():
    pass

def get_adress():
    pass

def random_data_to_file(file_name, n):
    """数据存入文件,传入文件名file_name和所需数据条数n"""
    pass

def output(file_name):
    """数据显示"""
    with open(file_name, 'r') as f:
        # 必须按行读,数据应为: chenjie, 22, cjsd@163.com, (逗号分隔)
        while True:
            line = f.readline().split(',')  # 此处则可看到全貌,之前的逻辑
            if line:
                print(line)
            else:
                break
def main():
    "主程序"
    random_data_to_file()  # 文件名, 条数
    output()  # 输出查看
    

b.1 输出搞定了,即顺带把写文件也搞定了

import random
import string

def get_name():
    pass

def get_sex():
    pass

def get_age():
    pass

def get_phone():
    pass

def get_email():
    pass

def get_adress():
    pass

def random_data_to_file(file_name, n):
    """数据存入文件,传入文件名file_name和所需数据条数n"""
    with open(file_name, 'w') as f:
        for _ in range(n):
            # 生成一条数据, join() 拼接一下
            name = get_name()
            sex = get_sex()
            age = get_age()
            phone= get_phone()
            email = get_email()
            address = get_adress()
            # 用 ',' 拼接一下
            line = ','.join([name, sex, age, phone, email, address])
            # 写入文件
            f.write(line)
            
            
def output(file_name):
    """数据显示"""
    with open(file_name, 'r') as f:
        # 必须按行读,数据应为: chenjie, 22, cjsd@163.com, (逗号分隔)
        while True:
            line = f.readline().split(',')  # 此处则可看到全貌,之前的逻辑
            if line:
                print(line)
            else:
                break
def main():
    "主程序"
    random_data_to_file()  # 文件名, 条数
    output()  # 输出查看
    
# join() test
','.join(('1', 'a', 'djfk', 'df', '9'))
'1,a,djfk,df,9'

c 各细节模块实现,**挑选容易的先搞定,麻烦的细节先PASS

  • 如先实现年龄,性别这种,几行代码就搞定了
  • 名字和地址比较麻烦,涉及到中文姓名,地址, 需要找些参考资料的,先pass
import random
import string

def get_name():
    
    return random.choice(['陈杰', '老二', '老四', '阳哥', '校庆'])

def get_sex():
    return random.choice(('男', '女'))

def get_age():
    return str(random.randint(18, 100))

def get_phone():
    '''随机手机号,看起来像手机号'''
    
    part1 = '1' + str(random.choice(range(3, 9)))  #  前两位为13,14,14,...18
    
    lst = list(map(str,range(10))) # ['0', '1', '2'.......]
    random.shuffle(lst)   # 后9位: 将[0,1,2,3,4,5,6,7,8,9] 随机打乱,shuffle()是原地操作, rfturn None
    part2 = ''.join(lst)
    
    # 拼接一下
    return part1 + part2
    

def get_email():
    """\w{4,15}@\w(\.\w+)+"""
      
    def suffix():
        for _ in range(random.randint(2,8)):
            tmp = random.choice(string.ascii_letters)  # abcd.com
            return tmp + '.com'

    part1 = ''
    for _ in range(random.randint(4,15)):
        part1 += random.choice(string.ascii_letters + string.digits)  # @ 前面的字符

    part2 = '@'
    part3 = random.choice(['163.com', '139.com', '126.com', 'gmail.com', suffix()]) # 列表里面放函数,我感觉自己很厉害

    return part1 + '@' + part3



def get_adress():
    """暂时写几个城市"""
    addr = ['北京', '上海', '广州', '深圳', '其他二线城市', '三四线城市']
    
    return random.choice(addr)


def random_data_to_file(file_name, n):
    """数据存入文件,传入文件名file_name和所需数据条数n"""
    with open(file_name,'w', encoding='utf-8') as f:
        for _ in range(n):
            # 生成一条数据, join() 拼接一下
            name = get_name()
            sex = get_sex()
            age = get_age()
            phone= get_phone()
            email = get_email()
            address = get_adress()
            # 用 ',' 拼接一下
            line = ','.join([name, sex, age, phone, email, address])
            # 写入文件
            f.write(line)
            
    print('数据写入文件已完成')
            
            
def output(file_name):
    """数据显示"""
    with open(file_name, 'r') as f:
        
        for line in file_name:
            print(line)
#         # 必须按行读,数据应为: chenjie, 22, cjsd@163.com, (逗号分隔)
#         while True:
#             line = f.readline().split(',')  # 此处则可看到全貌,之前的逻辑
#             if line:
#                 print(line)
#             else:
#                 break
def main():
    "主程序"
    random_data_to_file('cards.txt',10)  # 文件名, 条数
    output('cards')  # 输出查看
    
if __name__ == '__main__':
    
    main()
    

字符串处理, 何等重要, 而 Python 又是对字符串处理, 相当友好哇.

posted @ 2020-02-19 19:55  致于数据科学家的小陈  阅读(661)  评论(0编辑  收藏  举报