python编程实例

01-Hello World

01-Hello World

python 的语法逻辑完全靠缩进,建议缩进4个空格

如果是顶级代码,必须顶格书写,哪怕只有一个空格也会语法错误

下面实例中,满足if条件要输出两行内容,这两行内容必须都缩进,而且具有相同的缩进级别。

print("hello world")

if 3 > 0:
    print("OK")
    print("yes")
    
x = 3; y = 4 #不推荐,还是应该写成两行
print(x + y)

02-print

print("hello world")   #hello world
print("hello","world") #逗号自动添加默认的分隔符    hello world
print("hello" + "world") #加号表示字符拼接    helloworld
print("hello","world",sep="***") #单词间用***分隔    hello***world
print("*" * 10) #*号重复10遍  **********
print("how are you?",end="") #默认print会打印回车,end=""表示不要回车

03-基本运算

运算符可以分为:算术运算符、比较运算符和逻辑运算符。优先级是:算术运算符>比较运算符>逻辑运算符。不过呢,没记住优先级,最好使用括号,这样不用背,也增加了代码的可读性。

print(5 / 2) #2.5
print(5 // 2) #丢弃余数,只保留商 2
print(5 % 2) #求余数 1
print(5 ** 3) #求5的3次方 125
print(5 > 3)#返回True
print(3 > 5)#返回False
print(20 > 10 >5) #python支持连续比较 True
print(20 >10 and 10 >5) #python支持连续比较,与上面相同含义 True
print(not 20 > 10) #False
print(not 10 > 20) #True

True和False是关键字,区分大小写

04-input

number = input("请输入数字:") #input用于获取键盘输入 20
print(number) # 20
print(type(number)) #input获得的数据是字符型 <class 'str'>
#print(number + 10) #报错,不能把字符和数字做运算 TypeError: must be str, not int
print(int(number) + 10) #int可将字符10转换成数字10  30
print(number + str(10)) #str可将10转换为字符串后实现字符串拼接 2010

05-输入输出基础练习

username = input("username: ") #刘备
print("welcome",username) #print各项间默认以空格作为分隔符  welcome 刘备 逗号默认中间有一个空格
print("welcome  " + username) #注意引号内最后的空格  welcome  刘备 第一个字符串中包含两个空格

06-字符串使用基础

python中,单双引号在字符串中使用,没有区别

sentence = 'tom\'s pet is a cat' #单引号中间还有单引号,可以转义
sentence2 = "tom's pet is a cat" #也可以用双引号包含单引号
sentence3 = "tom said:\"hello world!\""
sentence4 = 'tom said:"hello world!"' #单引号中间可以用双引号,可以转义

#三个连续的三引号或单引号,可以保存输入格式,允许输入多行字符串
words = """
hello
world
abcd"""
print(words)
#hello
#world
#abcd

py_str = 'python'
print(len(py_str)) #取长度 6
print(py_str[0]) #取第一个字符 p
print('python'[0]) #取第一个字符 p
print(py_str[-1]) #取最后一个字符 n
#print(py_str[6]) #错误,下表超出范围  IndexError: string index out of range
print(py_str[2:4]) #切片,起始下标包含,结束下标不包含 th
print(py_str[2:]) #从下标为2的字符渠道结尾 thon
print(py_str[:2]) #从开头取到下标为2之前的字符 py
print(py_str[:]) #取全部 python
print(py_str[::2]) #按照步长为2取值,默认为1 pto
print(py_str[1::2]) #以下标为1开始,步长为2取值 yhn
print(py_str[::-1]) #步长为负,表示从右往左取 nohtyp

print(py_str + 'is good') #简单拼接在一起 pythonis good
print(py_str * 3) #把字符串重复3遍 pythonpythonpython

print('t' in py_str) #True
print('th' in py_str) #True
print('to' in py_str) #False 子字符串必须连续
print('to' not in py_str) #True

07-列表基础

列表也是序列对象,但它是容器类型,列表中可以包含各种数据,列表可变

alist = [10,20,30,'bob','alice',[1,2,3]]
print(len(alist)) #6
print(alist[-1]) #取出最后一项 [1, 2, 3]
print(alist[-1][-1]) #因为最后一项是列表,还可以继续取下标 3
print(alist[-2][2]) #列表倒数第二项是字符串,还可以继续取下标 i
print(alist[3:5]) #['bob','alice']
print(10 in alist) #True
print('o' in alist) #False
print(100 not in alist) #True

alist[-1] = 100 #修改最后一项的值
print(alist) # [10, 20, 30, 'bob', 'alice', 100]

alist.append(200) #向列表中追加一项
print(alist) #[10, 20, 30, 'bob', 'alice', 100, 200]

08-元组基础

元组与列表基本上是一致的,只是元组不可变,列表可变

atuple = (10,20,30,'bob','alice',[1,2,3])
print(len(atuple)) #6
print(atuple[2]) #30
print(atuple[-1]) #[1, 2, 3]
print(atuple[3:5]) #('bob','alice')
print(10 in atuple) #True

atuple[-1] = 100 #错误,元组是不可变的 TypeError: 'tuple' object does not support item assignment

09-字典基础

#字典是key-value(键-值)对形式的,没有顺序,通过键取值
adict = {'name':'bob','age':23}
print(len(adict)) #2
print('bob' in adict) #False
print('name' in adict) #True
adict['email'] = 'bob@163' #字典中没有的key,则添加
print(adict) #{'name': 'bob', 'age': 23, 'email': 'bob@163'}
adict['age'] = 25 #字典中已有的key,修改对应的value
print(adict) #{'name': 'bob', 'age': 25, 'email': 'bob@163'}

10-基本判断

单个数据也可作为判断条件

任何值为0的数字、空对象都是False,任何非0数字、非空对象都是True.

if 3 > 0:
    print('yes')
    print('ok')
if 10 in [10,20,30]:
    print('ok')
if -0.0:
    print('yes') #任何值为0的数字都是False
if [1,2]:
    print('yes') #非空对象都是True
if ' ':
    print('yes') #空格字符也是字符,条件为True

11-条件表达式、三元运算符

a = 10
b = 20

if a < b:
    smaller = a
else:
    smaller = b
print(smaller) #10

s = a if a < b else b #和上面的if-else语句等价
print(s) #10

12-判断练习:用户名和密码是否正确

import getpass #导入模块

username = input('username:')
#getpass模块中,有一个方法也叫getass
password = getpass.getpass('password:')

if username == 'bob' and password == '123456':
    print('Login successful')
else:
    print('Login incorrect')

13-成绩分类

score = int(input('分数:'))

if score >=90:
    print('优秀')
elif score >=80:
    print('好')
elif score >=70:
    print('良')
elif score >=60:
    print('及格')
else:
    print('你要努力了')

14-石头剪刀布

import random

all_choices = ["石头","剪刀","布"]
computer = random.choice(all_choices)
player = input('请出拳:')

# print('Your choice:',player,"Computer's choice:",computer)
print("Your choice:%s,Computer's choice:%s" %(player,computer))
if player == "石头":
    if computer == "石头":
        print("平局")
    elif computer == "剪刀":
        print("You Win!!!")
    else:
        print("You Lose!!!")
elif player == "剪刀":
    if computer == "石头":
        print("You Lose!!!")
    elif computer == "剪刀":
        print("平局")
    else:
        print("You Win!!!")
else:
    if computer == "石头":
        print("You Win!!!")
    elif computer == "剪刀":
        print("You Lose!!!")
    else:
        print("平局")

15-改进的石头剪刀布

import random

all_choices = ["石头","剪刀","布"]
win_list = [["石头","剪刀"],["剪刀","布"],["布","石头"]]
prompt = '''(0)石头
(1)剪刀
(2)布
请选择(0/1/2)'''
computer = random.choice(all_choices)
ind = int(input(prompt))
player = all_choices[ind]

print("Your choice:%s,Computer's choice:%s" %(player,computer))
if player == computer:
    print('\033[32;1m平局\033[0m')
elif [player,computer] in win_list:
    print('\033[31;1mYou Win!!!\033[0m')
else:
    print('\033[31;1mYou Lose!!!\033[0m')

16-猜数:基础实现

import random

num = random.randint(1,10) #随机生成1-10之间的数字
answer = int(input('guess a number:')) #将用户输入的字符转换为整数
if answer > num:
    print("猜大了")
elif answer < num:
    print("猜小了")
else:
    print("猜对了")
    
print('the number:',num)

17-猜数,直到猜对

import random

num = random.randint(1,10) #随机生成1-10之间的数字
running = True

while running:
    answer = int(input('guess a number:')) #将用户输入的字符转换为整数
    if answer > num:
        print("猜大了")
    elif answer < num:
        print("猜小了")
    else:
        print("猜对了")
        running = False

18-猜数,5次机会

import random

num = random.randint(1,10) #随机生成1-10之间的数字
counter = 0

while counter < 5:
    answer = int(input('guess a number:')) #将用户输入的字符转换为整数
    if answer > num:
        print("猜大了")
    elif answer < num:
        print("猜小了")
    else:
        print("猜对了")
        break
    counter +=1
else: #循环被break就不执行了,没有break才执行
    print('the number is :',num)	

19-while循环,累加至100

因为循环次数是已知的,实际使用时,建议用for循环

sum100 = 0
counter = 1

while counter < 101:
    sum100 +=counter
    counter +=1
print(sum100) #5050

20-while-break

break是结束循环,break之后、循环体内代码不在执行

while True:
    yn = input('Continue(y/n): ')
    if yn in ['n','N']:
        break
    print('running...')

21-while-continue

计算100以内偶数之和

continue是跳过本次循环剩余部分,回到循环条件处。

sum100 = 0
counter = 0

while counter < 100:
    counter +=1
    if counter %2 ==1:
        continue
    sum100 += counter
print(sum100) #2550

22-for 循环遍历数据对象

astr = 'hello'
alist = [10,20,30]
atuple = ('bob','tom','alice')
adict = {'name':'john','age':23}

for ch in astr:
    print(ch) 

for i in alist:
    print(i)

for name in atuple:
    print(name)

for key in adict:
    print('%s:%s'%(key,adict[key]))

23-range用法及数字累加

print(range(10)) #range(0,10)
print(list(range(10))) #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(list(range(6,11))) #[6, 7, 8, 9, 10]
print(list(range(1,10,2))) #[1, 3, 5, 7, 9]
print(list(range(10,0,-1))) #[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]

sum100 =0

for i in range(1,101):
    sum100 += i
print(sum100) #5050

24-列表实现斐波那契数列

列表中先给定两个数字,后面的数字总是前两个数字之和

fib = [0,1]

for i in range(8):
    fib.append(fib[-1] + fib[-2])

print(fib)

25-九九乘法表

for i in range(1,10):
    for j in range(1,i + 1):
        print('%s*%s=%s' % (j,i,i*j),end=' ')
    print() #没有将会把结果打印到一行,换行的作用

# i = 1 ->j:[1]
# i = 2 ->j:[1,2]
# i = 3 ->j:[1,2,3]
#或者由用户指定相乘到多少
n = int(input('number:'))

for i in range(1,n + 1):
    for j in range(1, i + 1):
        print('%s*%s=%s' % (j,i,i*j),end=' ')
    print()

26-逐步实现列表解析

#10+5的结果放到列表中
[10 + 5]
#10+5这个表达式计算10次
[10 + 5 for i in range(10)] 
#10+i的i来自于循环
[10 + i for i in range(10)] 
[10 + i for i in range(1,11)]
#通过if过滤,满足if条件的才参与10+i的运算
[10 + i for i in range(1,11) if i %2 == 1]
[10 + i for i in range(1,11) if i %2]
#生成IP地址列表
['192.168.1.%s' %i for i in range(1,255)]

27-三局两胜的石头剪刀布

import random

all_choices = ["石头","剪刀","布"]
win_list = [["石头","剪刀"],["剪刀","布"],["布","石头"]]
prompt = '''(0)石头
(1)剪刀
(2)布
请选择(0/1/2):'''
cwin = 0 #电脑赢
pwin = 0 #玩家赢

while cwin < 2 and pwin <2 :
    computer = random.choice(all_choices)
    ind = int(input(prompt))
    player = all_choices[ind]

    print("Your choice:%s,Computer's choice:%s" %(player,computer))
    if player == computer:
        print('\033[32;1m平局\033[0m')
    elif [player,computer] in win_list:
        pwin += 1
        print('\033[31;1mYou Win!!!\033[0m')
    else:
        cwin += 1
        print('\033[31;1mYou Lose!!!\033[0m')

28-文件对象基础操作

#文件操作的三个步骤:打开、读写、关闭
#cp /etc/passwd/tmp
f = open('/tmp/passwd') #默认以r的方式打开纯文本文件
data = f.read() #read()把所有内容读取出来
print(data)
data = f.read() #随着读写的进行,文件指针向后移动
#因为第一个f.read()已经把文件指针移动到结尾了,所以再读就没有数据了
#所以data是空字符串
f.close()
#############################################
f = open('/tmp/passwd')
data01 = f.read(4) #读4字节
f.readline() #读到换行符\n结束
f.readlines() #把每一行数据读出来放到列表中
f.close()
##############################################
f = open('/tmp/passwd')
for line in f:
    print(line,end='')
f.close()
##############################################
f = open('图片地址','rb') #打开非文本文件要加参数b
f.read(4096)
f.close()
##############################################
f = open('/tmp/myfile','w') #'w'打开文件,如果文件不存在则创建
f.write('hello world!\n')
f.flush() #立即将缓存中的数据同步到磁盘
f.writelines(['2nd line.\n','new line.\n'])
f.close() #关闭文件的时候,数据保存到磁盘
#############################################
with open('/tmp/passwd') as f:
    print(f.readline())
##############################################
f = open('/tmp/passwd')
f.tell() #查看文件指针的位置
f.readline()
f.tell()
f.seek(0,0) #第一个数字是偏移量,第二个数字是相对位置 #相对位置0表示开头,1表示当前,2表示结尾
f.tell()
f.close()

29-拷贝文件-1

拷贝文件就是以r的方式打开源文件,以w的方式打开目标文件,将源文件数据读出后,写到目标文件。以下是【不推荐】的方式,但是可以工作。

f1 = open('/bin/ls','rb')
f2 = open('/root/ls','wb')

data = f1.read()
f2.write(data)

f1.close()
f2.close()

30-拷贝文件-2

每次读取4k,读完为止:

src_fname = '/bin/ls'  #源文件名称
dst_fname = '/root/ls' #目标文件名称

src_fobj = open(src_fname,'rb')
dst_fobj = open(dst_fname,'wb')

while True:
    data = src_fobj.read(4096)
    if not data:
        break
    dst_fobj.write(data)

src_fobj.close()
dst_fobj.close()

31-位置参数

注意:位置参数中的数字是字符形式的

import sys
print(sys.argv) #sys.argv是sys模块里的argv列表

# python3 position_args.py
# python3 position_args.py 10
# python3 position_args.py 10 bob

32-函数应用-菲波那契数列

def gen_fib(l):
    fib = [0,1]

    for i in range(l - len(fib)):
        fib.append(fib[-1] + fib[-2])
    return fib #返回列表,不返回变量fib

a = gen_fib(10)
print(a) #[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
print('-'*10) #----------
n = int(input("length:"))
print(gen_fib(n)) #不会把变量n传入,是把n代表的值赋值给形参 #length:

33-函数-拷贝文件

import sys

def copy(src_fname,dst_fname): #src_fname源文件名称,dst_fname目标文件名称
    src_fobj = open(src_fname,'rb')
    dst_fobj = open(dst_fname,'wb')

    while True:
        data = src_fobj.read(4096)
        if not data:
            break
        dst_fobj.write(data)

    src_fobj.close()
    dst_fobj.close()

copy(sys.argv[1],sys.argv[2])
#执行方式
# cp_func.py /etc/hosts /tmp/zhuji.txt

34-函数-九九乘法表

def matble(n):
    for i in range(1,n + 1):
        for j in range(1,i + 1):
            print('%s*%s=%s' % (j,i,i*j),end=' ')
        print() #没有将会把结果打印到一行,换行的作用

matble(6)
matble(9)

35-模块基础

每一个以py作为扩展名的文件都是一个模块

# 创建star.py文件
hi = 'hello world!'

def pstar(n=50):
    print('*' * n)
if __name__=='__main__':
    pstar() #**************************************************
    pstar(30) #******************************

新建call_star.py并调用star模块:

import star

print(star.hi) #hello world!
star.pstar() #**************************************************
star.pstar(20)#********************

36-生成密码/验证码

此文件名:randpass.py

思路:

1、设置一个用于随机取出字符的基础字符串,本例使用大小写字母加数字

2、循环n次,每次随机取出一个字符

3、将各个字符拼接起来,保存到变量result中

from random import choice
import string

all_chs = string.ascii_letters + string.digits #大小写字母加数字

def gen_pass(n = 8):
    result = ''

    for i in range(n):
        ch = choice(all_chs)
        result += ch
    return result

if __name__ == '__main__':
    print(gen_pass()) #随机的8位密码
    print(gen_pass(4)) #随机的4位密码
    print(gen_pass(10)) #随机的10位密码

37-序列对象方法-1

from random import randint

alist = list() #[]
print(alist)
print(list('hello')) #['h', 'e', 'l', 'l', 'o']
print(list((10,20,30))) #[10,20,30]元组转列表
astr = str()
print(astr) #''
print(str(['h', 'e', 'l', 'l', 'o'])) #将列表转换为字符串 #['h', 'e', 'l', 'l', 'o']为一个字符串
atuple = tuple() #()
print(tuple('hello')) #('h', 'e', 'l', 'l', 'o')
num_list = [randint(1,100) for i in range(10)]
print(max(num_list))
print(min(num_list))

38-序列对象方法-2

alist = [10,'john']
# list(enumerate(alist)) #[(0,10),(1,'john')]
# a,b = 0,10 #a->0  ->10

for ind in range(len(alist)):
    print('%s:%s' % (ind,alist[ind]))

for item in enumerate(alist):
    print('%s:%s' % (item[0],item[1]))

for ind,val in enumerate(alist):
    print('%s:%s' % (ind,val))

atuple = (96,97,40,75,58,34,69,29,66,90)
result01 = sorted(atuple)
print(result01) #[29, 34, 40, 58, 66, 69, 75, 90, 96, 97]
result02 = sorted('hello')
print(result02) #['e', 'h', 'l', 'l', 'o']
for i in reversed(atuple):
    print(i,end=',') #90,66,29,69,34,58,75,40,97,96,

39-字符串方法

py_str = 'hello world!'
print(py_str.capitalize()) #Hello world!第一个字母大写
print(py_str.title()) #Hello World!每个单词首字母大写
print(py_str.center(50)) #                   hello world!                   位于50字节中间,没有字符处为空格填充
print(py_str.center(50,'#')) # ###################hello world!###################
print(py_str.ljust(50,'*')) # hello world!**************************************
print(py_str.rjust(50,'*')) # **************************************hello world!
print(py_str.count('l')) #统计l出现的次数 3
print(py_str.count('lo')) #统计lo出现的次数 1
print(py_str.endswith('d!')) #是否以d!结尾? True
print(py_str.startswith('a')) #是否以a开头? False
print(py_str.islower()) #字母是否都是小写的?其他字符不考虑 True
print(py_str.isupper()) #字母是否都是大写的?其他字符不考虑 False
print('Hao123'.isdigit()) #所有字符都是数字吗? False
print('Hao123'.isalnum()) #所有字符都是字母数字吗? True
print('  hello\t    '.strip()) #去除两端空白字符,常用 hello
print('  hello\t    '.lstrip()) # hello	
print('  hello\t    '.rstrip()) #  hello
print('how are you?'.split()) # ['how', 'are', 'you?']
print('hello.tar.gz'.split('.')) #['hello', 'tar', 'gz']
print('.'.join(['hello','tar','gz'])) #hello.tar.gz
print('-'.join(['hello','tar','gz'])) #hello-tar-gz

40-字符串格式化

print("%s is %s years old" % ('bob',23)) #常用 bob is 23 years old
print("%s is %d years old" % ('bob',23)) #常用 bob is 23 years old
print("%s is %d years old" % ('bob',23.5)) # %d是整数 常用 bob is 23 years old
print("%s is %f years old" % ('bob',23.5)) # bob is 23.500000 years old
print("%s is %5.2f years old" % ('bob',23.5)) # %5.2f是宽度为5,2位小数 bob is 23.50 years old
print("97 is %c" % 97) # 97 is a
print("11 is %#o" % 11) # %#o表示有前缀的8进制 11 is 0o13
print("11 is %#x" % 11) # 11 is 0xb
print("%10s%5s" % ('name','age')) # %10s表示总宽度为10,右对齐,常用       name  age
print("%10s%5s" % ('bob',25)) #        bob   25
print("%10s%5s" % ('alice',23)) #      alice   23
print("%-10s%-5s" % ('name','age')) # %-10s表示左对齐,常用 name      age  
print("%-10s%-5s" % ('bob',25)) # bob       25  
print("%10d" % 123) #        123
print("%010d" % 123) # 0000000123

print("{} is {} years old".format('bob',25)) # bob is 25 years old
print("{1} is {0} years old".format(25,'bob')) # bob is 25 years old
print("{:<10}{:<8}".format('name','age')) # name      age  

41-shutil模块常用方法

import shutil

with open('/etc/passwd','rb') as sfobj:
    with open('/tmp/mima.txt','wb') as dfobj:
        shutil.copyfileobj(sfobj,dfobj) #拷贝文件对象

shutil.copyfile('/etc/passwd','/tmp/mima2.txt')
shutil.copy('/etc/shadow','/tmp/') # cp /etc/shadow /tmp/
shutil.copy2('/etc/shadow','/tmp/') # cp -p /etc/shadow /tmp/
shutil.move('/tmp/mima.txt','/var/tmp/') # mv /tmp/mima.txt /var/tmp/
shutil.copytree('/etc/security','/tmp/anquan') # cp -r /etc/security /tmp/anquan
shutil.rmtree('/tmp/anquan') # rm -rf /tmp/anquan
#将mima2.txt的权限设置成与etc/shadow 一样
shutil.copymode('/etc/shadow','/tmp/mima2.txt')
#将mima2.txt的元数据设置成与etc/shadow 一样
#元数据使用 stat /etc/shadow查看
shutil.copystat('/etc/shadow','/tmp/mima2.txt')
shutil.chown('/tmp/mima2.txt',user='zhangsan',group='zhangsan')

42-练习:生成文本文件

import os

def get_fname():
    while True:
        fname = input('filename:')
        if not os.path.exists(fname):
            break
        print('%s already exists.Try again' % fname)
    return fname

def get_content():
    content = []
    print('输入数据,输入end结束')
    while True:
        line = input('>')
        if line == 'end':
            break
        content.append(line)
    return content

def wfile(fname,content):
    with open(fname,'w') as fobj:
        fobj.writelines(content)

if __name__ == '__main__':
    fname = get_fname()
    content = get_content()
    content = ['%s\n' % line for line in content]
    wfile(fname,content)

43-列表方法

alist = [1,2,3,'bob','alice']
alist[0] = 10
print(alist) #[10, 2, 3, 'bob', 'alice']
alist[1:3] = [20,30]
print(alist) #[10, 20, 30, 'bob', 'alice']
alist[2:2] = [22,24,26,28]
print(alist) #[10, 20, 22, 24, 26, 28, 30, 'bob', 'alice']
alist.append(100)
print(alist) #[10, 20, 22, 24, 26, 28, 30, 'bob', 'alice', 100]
alist.remove(24) #删除第一个24
print(alist) #[10, 20, 22, 26, 28, 30, 'bob', 'alice', 100]
print(alist.index('bob')) #返回下标 6
blist = alist.copy() #相当于blist = alist[:]
print(blist) #[10, 20, 22, 26, 28, 30, 'bob', 'alice', 100]
alist.insert(1,15) #在下标为1的位置插入数字15
print(alist) #[10, 15, 20, 22, 26, 28, 30, 'bob', 'alice', 100]
alist.pop() #默认弹出最后一项
print(alist) #[10, 15, 20, 22, 26, 28, 30, 'bob', 'alice']
alist.pop(2) #弹出下标为2的一项
print(alist) #[10, 15, 22, 26, 28, 30, 'bob', 'alice']
alist.pop(alist.index('bob')) #
print(alist) #[10, 15, 22, 26, 28, 30, 'alice']
# alist.sort() #错误 TypeError: '<' not supported between instances of 'str' and 'int'
# print(alist)
alist.reverse() #列表反转
print(alist) #['alice', 30, 28, 26, 22, 15, 10]
print(alist.count('new')) #列表中new的个数 0
alist.extend('new')
print(alist) #['alice', 30, 28, 26, 22, 15, 10, 'n', 'e', 'w']
alist.extend(['hello','world','hehe'])
print(alist) #['alice', 30, 28, 26, 22, 15, 10, 'n', 'e', 'w', 'hello', 'world', 'hehe']

44-检查合法标识符

import sys
import keyword
import string

first_chs = string.ascii_letters + '-'
all_chs = first_chs + string.digits

def check_id(idt):
    if keyword.iskeyword(idt):
        return "%s is keyword" % idt

    if idt[0] not in first_chs:
        return "1st invaild"

    for ind,ch in enumerate(idt[1:]):
        if ch not in all_chs:
            return "char in position #%s invaild" % (ind + 2)

    return "%s is vaild" % idt

if __name__ == '__main__':
    print(check_id(sys.argv[0])) #python3 checkid.y abc@123

45-动画程序:@从一行#中穿过

\r是回车不换行

# @在一行#从头到尾移动
import time

length = 19
count = 0

while True:
    print('\r%s@%s' % ('#' * count,'#' * (length-count)),end='')
    try:
        time.sleep(0.3)
    except KeyboardInterrupt:
        print('\nBye-bye')
        break
    if count == length:
        count = 0
    count += 1

46-创建用户,设置随机密码

randpass模块参见《36-生成密码/验证码》(http://www.jianshu/p/b81b7ae19cb2)

import subprocess
import sys
from randpass import gen_pass

def adduser(username,password,fname):
    data = """user information:
    %s:%s
    """
    subprocess.call('useradd %s' % username,shell=True)
    subprocess.call(
        'echo %s | passwd --stain %s' % (password,username),
        shell=True
    )
    with open(fname,'a') as fobj:
        fobj.write(data % (username,password))

if __name__ == '__main__':
    username = sys.argv[1]
    password = gen_pass()
    adduser(username,password,'/etc/user.txt') #python3 adduser.y john

47-列表练习:模拟栈操作

stack = []

def push_it():
    item = input('item to push:')
    stack.append(item)
    
def pop_it():
    if stack:
        print("from stack popped %s" % stack.pop())

def view_it():
    print(stack)
    
def show_menu():
    cmds = {'0':push_it(),'1':pop_it(),'2':view_it()} #将函数存入字典
    promt = """(0)push it
(1)pop it
(2)view it
(3)exit
Please input your choice(0/1/2/3):"""
    while True:
        #input()得到字符串,用strip()去掉两端空白,再取下标为0的字符
        choice = input(promt).strip()[0]
        if choice not in '0123':
            print('Invaild input. Try again.')
            continue
        
        if choice == '3':
            break
        
        cmds[choice]()
        
if __name__ == '__main__':
    show_menu()

48-实现Linux系统中unix2dos功能

import sys

def unix2dos(fname):
    dst_fname =fname + '.txt'

    with open(fname) as src_fobj:
        with open(dst_fname,'w') as dst_fobj:
            for line in src_fobj:
                line = line.rstrip() + '\r\n'
                dst_fobj.write(line)

if __name__ == '__main__':
    unix2dos(sys.argv[1])

49-字典基础用法

adict = dict() #{}
dict(['ab','cd'])
bdict = dict([('name','bob'),('age',25)])
{}.fromkeys(['zhangsan','lisi','wangwu'],11)

for key in bdict:
    print('%s:%s' % (key,bdict[key])) #name:bob age:25

print("%(name)s:%(age)s" % bdict) #bob:25

bdict['name'] = 'tom'
bdict['email'] = 'tom@tedu'
print(bdict) #{'name': 'tom', 'age': 25, 'email': 'tom@tedu'}

del bdict['email']
print(bdict) #{'name': 'tom', 'age': 25}
bdict.pop('age')
print(bdict) #{'name': 'tom'}
bdict.clear()
print(bdict) #{}

50-字典常用方法

adict = dict([('name','bob'),('age',25)])
print(len(adict)) #2
hash(10) #判断给定的数据是不是不可变的,不可变数据才能作为key
print(adict.keys()) #dict_keys(['name', 'age'])
print(adict.values()) #dict_values(['bob', 25])
print(adict.items()) #dict_items([('name', 'bob'), ('age', 25)])

#get方法常用,重要
adict.get('name') #取出字典中name对应的value,如果没有返回None
print(adict.get('qq')) #None
print(adict.get('qq','not found')) #没有qq,返回指定内容 #not found
print(adict.get('age','not found')) #25
adict.update({'phone':'1234567899'})
print(adict) #{'name': 'bob', 'age': 25, 'phone': '1234567899'}

51-集合常用方法

#集合相当于无值的字典,所以用{}表示
myset = set('hello')
print(len(myset)) #4
for ch in myset:
    print(ch)

aset = set('abc')
bset = set('cde')
print(aset & bset) #交集 #{'c'}
print(aset.intersection(bset)) #交集 #{'c'}
print(aset | bset) #并集 #{'c', 'd', 'a', 'b', 'e'}
print(aset.union(bset)) #并集 #{'c', 'd', 'a', 'b', 'e'}
print(aset - bset) #差补 #{'b', 'a'}
print(aset.difference(bset)) #差补 #{'b', 'a'}
print(bset.difference(aset)) #差补 #{'e', 'd'}
print(aset) #{'c', 'b', 'a'}
aset.add('new') #添加
print(aset) #{'new', 'c', 'b', 'a'}
aset.update(['aaa','bbb']) #更新
print(aset) #{'aaa', 'bbb', 'c', 'new', 'b', 'a'}
aset.remove('bbb') #删除
print(aset) #'aaa', 'c', 'new', 'b', 'a'}

cset =set('abcde')
dset = set('bcd')
print(cset.issuperset(dset)) #cset是dset的超集吗? #True
print(cset.issubset(dset)) #cset是dset的子集吗? #False

52-集合实例:取出第二个文件有,第一个文件没有的行

#cp /etc/passwd .
#cp /etc/passwd mima
#vim mima ->修改,与passwd有些区别

with open('passwd') as fobj:
    aset = set(fobj)

with open('mima') as fobj:
    bset = set(fobj)

with open('diff.txt','w') as fobj:
    fobj.writelines(bset - aset)

53-字典练习:模拟注册/登录

import getpass

userdb = {}

def regirster():
    username = input('username:')
    if username in userdb:
        print('%s already exists.' % username)
    else:
        password = input('password:')
        userdb[username] = password

def login():
    username = input('username:')
    password = getpass.getpass("password:")
    if userdb.get(username) != password:
        print('login failed')
    else:
        print('login successful')

def show_menu():
    cmds = {'0':regirster,'1':login}
    prompt = '''(0)register
    (1)login
    (2)exit
    please input your choice(0/1/2):'''
    while True:
        choice = input(prompt).strip()[0]
        if choice not in '012':
            print('Invaild input,try again')
            continue
        if choice == '2':
            break
        cmds[choice]()
        
if __name__ == '__main__':
    show_menu()

54.计算千万次加法运算时间

import time

result = 0
start = time.time() #返回运算前时间戳
for i in range(10000000):
    result += i
end = time.time() #返回运算后时间戳
print(result)
print(end - start)

55-时间相关模块常用方法

import time

t = time.localtime() #返回当前时间的九元组
print(t) #time.struct_time(tm_year=2019, tm_mon=10, tm_mday=18, tm_hour=9, tm_min=8, tm_sec=21, tm_wday=4, tm_yday=291, tm_isdst=0)
print(time.gmtime()) #返回格林威治0时区当前时间的九元组 #time.struct_time(tm_year=2019, tm_mon=10, tm_mday=18, tm_hour=1, tm_min=10, tm_sec=29, tm_wday=4, tm_yday=291, tm_isdst=0)
print(time.time()) #常用,与1970-1-1 8:00之间的秒数,时间戳 #1571361029.5783381
print(time.mktime(t)) #把九元组时间转换成时间戳 #1571361029.0
time.sleep(1) #休眠1秒
print(time.asctime()) #如果有参数,是九元组形式 #Fri Oct 18 09:10:30 2019
print(time.ctime()) #返回当前时间,参数是时间戳,常用 #Fri Oct 18 09:10:30 2019
print(time.strftime("%Y-%m-%d")) #常用 #2019-10-18
print(time.strptime('2018-07-20',"%Y-%m-%d")) #返回九元组时间格式 #time.struct_time(tm_year=2018, tm_mon=7, tm_mday=20, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=4, tm_yday=201, tm_isdst=-1)
print(time.strftime('%H:%M:%S')) #09:10:30

####################################################
from datetime import datetime
from datetime import timedelta

print(datetime.today()) #返回当前时间的datetime对象 #2019-10-18 09:18:57.156086
print(datetime.now()) #同上,可以用时区做参数 #2019-10-18 09:18:57.156086
print(datetime.strptime('2018/07/20',"%Y/%m/%d")) #返回datetime对象 #2018-07-20 00:00:00
dt = datetime.today()
print(dt) #2019-10-18 09:21:36.056204
print(datetime.ctime(dt)) #Fri Oct 18 09:21:36 2019
print(datetime.strftime(dt,"%Y/%m/%d")) #2019/10/18

days = timedelta(days=90,hours=3) #常用
dt2 = dt + days
print(dt2.year) #2020
print(dt2.month) #1
print(dt2.day) #16
print(dt2.hour) #12

56-变量作用域

x = 10 #全局变量从定义开始到程序结束,一直可见可变

def foo():
    print(x)

foo() #->10

def bar():
    x = 20 #此处的x是局部变量,将全局变量遮盖住,不会影响全局变量的值
    print(x)

bar() #x ->20
print(x) #x ->10

def aaa():
    global x #在局部引用全局变量
    x = 100 #将全局变量x重新赋值为100
    print(x) 

aaa()#x ->100

print(x) #x ->100

57-os模块常用方法

import os

print(os.getcwd()) #显示当前路径 #/home/tarena/自习/2019.06.12
print(os.listdir('/home/tarena/自习')) #ls -a 必须加路径 #['.idea', '2019.06.12', '读书方法.py']
# os.mkdir('/tmp/mydemo') #mkdir /tmp/mydemo
# os.chdir('/tmp/mydemo') #cd /tmp/mydemo
# os.mknod('test.txt') #touch test.txt
# os.symlink('/etc/hosts','zhuji') #ln -s /etc/hosts zhuji
print(os.path.isdir('/etc')) #True
print(os.path.isfile('test.txt')) #判断test.txt是不是文件 #False
print(os.path.islink('zhuji')) #判断zhuji是不是软连接 #False
print(os.path.exists('/tmp')) #判断是否存在 #True
print(os.path.basename('/tmp/abc/aaa.txt')) #aaa.txt
print(os.path.dirname('/tmp/abc/aaa.txt')) #/tmp/abc
print(os.path.split('/tmp/abc/aaa.txt')) #('/tmp/abc', 'aaa.txt')
print(os.path.join('/home/tom','xyz.txt')) #/home/tom/xyz.txt
print(os.path.abspath('test.txt')) #返回当前目录test.txt的绝对路径 #/home/tarena/自习/2019.06.12/test.txt

58-pickle存储器

import pickle
"""以前的文件写入,只能写入字符串,
如果希望把任意数据对象(数字,列表等)写入文件,取出来的时候数据类型不变,就用到pickle了
"""

# shop_list = ['eggs','apple','peach']
# with open('/tmp/shop.data','wb') as fobj:
#     pickle.dump(shop_list,fobj)

with open('/tmp/shop.data','rb') as fobj:
    mylist = pickle.load(fobj)

print(mylist[0],mylist[1],mylist[2])

59-异常处理基础

try: #把有可能发生异常的语句放到try里执行
    n = int(input("number:"))
    result = 100/n
    print(result)
except ValueError:
    print("invaild number")
except ZeroDivisionError:
    print('0 not allowed')
except KeyboardInterrupt:
    print('bye-bye')
except EOFError:
    print('bye-bye')

60-异常处理完整语法

try: #把有可能发生异常的语句放到try里执行
    n = int(input("number:"))
    result = 100/n
except (ValueError,ZeroDivisionError):
    print("invaild number")
except (KeyboardInterrupt,EOFError):
    print('bye-bye')
else:
    print(result) #异常不发生时才执行else语句
finally:
    print('Done') #不管异常是否发生都必须执行的语句

#常用形式有try-except和try-finally

61-自定义异常

def set_age(name,age):
    if not 0 < age <120:
        raise ValueError('年龄超出范围') #自主决定触发什么样的异常
    print("%s is %d years old" % (name,age))

def set_age2(name,age):
    assert 0 < age <120,'年龄超出范围'  #断言异常
    print("%s is %d years old" % (name, age))

if __name__ == '__main__':
    set_age('zhangsan',20)
    set_age2('lisi',200)

62-函数调用:参数使用注意事项

def get_age(name,age):
    print("%s is %s years old" % (name,age))

get_age('bob',25) #参数按顺序传递
get_age(25,'bob') #没有语法错误,但语义不对
get_age(age=25,name='bob') #
get_age('bob',age=25)

# get_age() #错误,缺少参数
# get_age('bob',25,100) #错误,多参数
# get_age(age=25,'bob') #语法错误
# get_age(25,name='bob') #错误,参数按顺序传递,name得到多个值

63-参数个数不固定的函数

def fun1(*args): #*表示args是个元组
    print(args)

def fun2(**kwargs): #**表示kwargs是个字典
    print(kwargs)

def fun3(x,y):
    print(x * y)

def fun4(name,age):
    print("%s is %s years old" % (name, age))

if __name__ == '__main__':
    fun1() #()
    fun1(10) #(10,)
    fun1(10,'bob') #(10, 'bob')
    fun2() #{}
    fun2(name='bob',age=25) #{'name': 'bob', 'age': 25}
    fun3(*[10,5]) #调用的时候,*表示拆开后面的数据类型 #50
    fun4(**{'name':'bob','age':25}) # bob is 25 years old

64-偏函数基础应用

偏函数可以理解为,将现有函数的某些参数固定下来,构成一个新的函数。新函数调用就不用写那么多参数了

from functools import partial

def foo(a,b,c,d,f):
    return a + b + c + d + f

if __name__ == '__main__':
    print(foo(10,20,30,40,5)) #105
    print(foo(10,20,30,40,25)) #125
    add = partial(foo,a =10,b = 20,c = 30,d = 40)
    print(add(f = 5)) #相当于foo(10,20,30,40,5) #105
    print(add(f=8)) #相当于foo(10,20,30,40,5) #108

65-偏函数应用:简单的图形窗口

import tkinter
from functools import partial

root = tkinter.Tk()
lb = tkinter.Label(text="Hello world!")
b1 = tkinter.Button(root,fg = 'white',bg = 'blue',text='Button 1') #不使用偏函数生成按钮
MyBtn = partial(tkinter.Button,root,fg = 'white',bg = 'blue') #使用偏函数定义MyBtn
b2 = MyBtn(text = 'Button 2')
b3 = MyBtn(text = quit,command = root.quit)
lb.pack()
b1.pack()
b2.pack()
b3.pack()
root.mainloop()

66-生成器基础

生成器也是函数,只是常规函数通过return返回一个值,而生成器可以通过yield返回很多中间结果

def mygen():
    yield 'hello'
    a = 10 + 20
    yield a
    yield [1,2,3]

if __name__ == '__main__':
    m = mygen()
    for i in m:
        print(i)

    for i in m:
        print(i) #无值,因为生成器只能用一次

67-生成器实例:每次取出文件的10行内容

def blocks(fobj):
    block = []
    counter = 0
    for line in fobj:
        block.append(line)
        counter += 1
        if counter == 10:
            yield block #返回中间结果,下次取值,从这里继续向下执行
            block = []
            counter = 0
    if block: #文件不够10行的部分
        yield block

if __name__ == '__main__':
    fobj = open('/tmp/passwd') # cp /tmp/passwd /tmp
    for lines in blocks(fobj):
        print(lines)
        print()
    fobj.close()

68-匿名函数和filter

from random import randint

def fun1(x):
    return x % 2

if __name__ == '__main__':
    alist = [randint(1,100) for i in range(10)]
    print(alist)
    # filter要求第一个参数是函数,该函数必须返回True或False
    # 执行时把alist的每一项作为fun1的参数,返回真留下,否则过滤掉
    # filter函数的参数又是函数,称作高阶函数
    result = filter(fun1,alist) #不使用匿名函数
    print(list(result))
    result2 = filter(lambda x:x % 2,alist)
    print(list(result2))

69-匿名函数和map

from random import randint

def fun(x):
    return x * 2 + 1

if __name__ == '__main__':
    alist = [randint(1,100) for i in range(10)]
    print(alist)
    # map将第二个参数中的每一项交给fun函数进行加工,保留加工后的结果
    result = map(fun,alist) #使用常规函数作为参数
    print(list(result))
    result2 = map(lambda x:x * 2 + 1,alist) #使用匿名函数作为参数
    print(list(result2))

70-函数练习:数字游戏

随机生成100以内的两个数字,实现随机的加减法。如果是减法,结果不能是负数。算错三次,给出正确答案。

from random import randint,choice

def add(x,y):
    return x + y

def sub(x,y):
    return x - y

def exam():
    cmds = {'+':add,'-':sub}
    nums = [randint(1,100) for i in range(2)]
    nums.sort(reverse=True) #列表降序排列
    op = choice('+-')
    result = cmds[op](*nums)
    prompt = "%s %s %s = " % (nums[0],op,nums[1])
    tries = 0
    
    while tries < 3:
        try:
            answer = int(input(prompt))
        except: #简单粗暴的捕获所有异常
            continue
        
        if answer == result:
            print('Very good!')
            break
        else:
            print('Wrong answer')
            tries += 1
    else: #此处是while的else,全算错才给答案,算对了就不用给出答案了
        print('%s%s' % (prompt,result))

if __name__ == '__main__':
    while True:
        exam()
        try:
            yn = input("(Continue(y/n)?").strip()[0]
        except IndexError:
            continue
        except (KeyboardInterrupt,EOFError):
            print()
            yn = 'n'
        
        if yn in 'nN':
            break

71-数字游戏进阶

与前面例子相同,只是加减法函数更换为匿名函数

from random import randint,choice


def exam():
    cmds = {'+':lambda x,y:x + y,'-':lambda x,y:x - y}
    nums = [randint(1,100) for i in range(2)]
    nums.sort(reverse=True) #列表降序排列
    op = choice('+-')
    result = cmds[op](*nums)
    prompt = "%s %s %s = " % (nums[0],op,nums[1])
    tries = 0

    while tries < 3:
        try:
            answer = int(input(prompt))
        except: #简单粗暴的捕获所有异常
            continue

        if answer == result:
            print('Very good!')
            break
        else:
            print('Wrong answer')
            tries += 1
    else: #此处是while的else,全算错才给答案,算对了就不用给出答案了
        print('%s%s' % (prompt,result))

if __name__ == '__main__':
    while True:
        exam()
        try:
            yn = input("(Continue(y/n)?").strip()[0]
        except IndexError:
            continue
        except (KeyboardInterrupt,EOFError):
            print()
            yn = 'n'

        if yn in 'nN':
            break

72-递归函数计算阶乘

递归函数就是在函数内部调用自己

def fun(n): #5
    if n == 1:
        return n
    return n * fun(n - 1)
        #5 * fun(4)
        # 5 * 4 fun(3)
        # 5 * 4 *3fun(2)
        # 5 * 4 *3 * 2fun(1)
        # 5 * 4 *3 * 2 * 1

if __name__ == '__main__':
    print(fun(5))
    print(fun(6))

73-函数递归练习:逐级列出目录

# listdir.py

import os
import sys

def list_files(path):
    if os.path.isdir(path):
        print(path + ':')
        content = os.listdir(path)
        print(content)
        for fname in content:
            fname = os.path.join(path,fname)
            list_files(fname)
            
if __name__ == '__main__':
    list_files(sys.argv[1])  #python3 listdir.py /etc

74-函数递归练习:快速排序

思路:1、假设列表中的第一个数是中间值,逼他小的数字放到smaller列表中,比它大的数字放到larger列表中,再将这三项拼接起来

2、因为smaller和larger仍然是无序列表,需要使用相同的方法继续分割。

3、如果列表长度是0或1,那么就没有必要再排序了。

from random import randint

def quick_sort(num_list):
    if len(num_list) < 2:
        return num_list
    middle = num_list[0]
    smaller = []
    larger = []
    for i in num_list[1:]:
        if i < middle:
            smaller.append(i)
        else:
            larger.append(i)
    return quick_sort(smaller) + [middle] + quick_sort(larger)

if __name__ == '__main__':
    alist = [randint(1,100) for i in range(10)]
    print(alist) #[33, 2, 30, 91, 45, 61, 22, 26, 71, 47]
    print(quick_sort(alist)) #[2, 22, 26, 30, 33, 45, 47, 61, 71, 91]

75-闭包的用法

下面的代码用到了[《65-偏函数应用:简单的图形窗口》]图形窗口上的按钮有个command选项,其实它就是一个函数。如下:

import tkinter
from functools import partial

root = tkinter.Tk()
lb = tkinter.Label(text="Hello world!")
b1 = tkinter.Button(root,fg = 'white',bg = 'blue',text='Button 1') #不使用偏函数生成按钮
MyBtn = partial(tkinter.Button,root,fg = 'white',bg = 'blue') #使用偏函数定义MyBtn
b2 = MyBtn(text = 'Button 2')
b3 = MyBtn(text = quit,command = root.quit)
lb.pack()
b1.pack()
b2.pack()
b3.pack()
root.mainloop()

按下Button 1和Button 2就会执行hello和welcome两个函数。这两个函数非常类似,如果有10个按钮,并且都是类似的呢?换成内部函数、闭包的语法如下:

import tkinter
from functools import partial

def hello(word):
    def welcome():
        lb.config(text="Hello %s!" % word)
    return welcome #hello函数的返回值还是函数

root = tkinter.Tk()
lb = tkinter.Label(text="Hello world!",font="Times 26")
MyBtn = partial(tkinter.Button,root,fg = 'white',bg = 'blue') #使用偏函数定义MyBtn
b1 = MyBtn(text = 'Button 1',command=hello('China'))
b2 = MyBtn(text = 'Button 2',command=hello('world'))
b3 = MyBtn(text = quit,command = root.quit)
lb.pack()
b1.pack()
b2.pack()
b3.pack()
root.mainloop()

76-装饰器基础

def color(func):
    def red():
        return '\033[31;1m%s\033[0m' % func()
    return red

def hello():
    return 'Hello world!'

@color
def welcome():
    return 'Hello China!'

if __name__ == '__main__':
    hello = color(hello) #此种写法可以换成为welcome加上@color的写法
    print(hello())
    print(welcome()) #welcome因为有装饰器,所以调用时不是调用welcome函数,
    # 而是相当于color(welcome)()
    #color(welcome)返回red,color(welcome)()等价于red()

77-带有参数的装饰器

def color(func):
    def red(*args):
        return '\033[31;1m%s\033[0m' % func(*args)
    return red

@color
def hello(word):
    return 'Hello %s!' % word

@color
def welcome():
    return 'How are you?'

if __name__ == '__main__':
    print(hello('China'))
    print(welcome())

78-装饰器,返回不同颜色的字体

def colors(c):
    def set_color(func):
        def red(*word):
            return '\033[31;1m%s\033[0m' % func(*word)
        def green(*word):
            return '\033[32;1m%s\033[0m' % func(*word)
        adict = {'red':red,'green':green}
        return adict[c]
    return set_color

@colors('red')
def hello():
    return 'Hello world!'

@colors('green')
def welcome(word):
    return 'Hoello %s' % word

if __name__ == '__main__':
    print(hello()) 
    print(welcome('China')) 

79-综合练习:记账小程序

1、记账时手头有一万块钱
2、可以记录花的钱、存的钱,以及收支明细

import pickle
import os
import time

def cost(wallet,record): #记录花钱的函数
    amount = int(input('amount:'))
    comment = input('comment:')
    date = time.strftime('%Y-%m-%d')
    with open(wallet,'rb') as fobj:
        balance = pickle.load(fobj) - amount
    with open(wallet,'wb') as fobj:
        pickle.dump(balance,fobj)
    with open(record, 'a') as fobj:
        fobj.write('%-12s%-8s%-8s%-10s%-20s\n' % (date,amount,'',balance,comment))
        
def save(wallet,record): #记录存钱的函数
    amount = int(input('amount:'))
    comment = input('comment:')
    date = time.strftime('%Y-%m-%d')
    with open(wallet, 'rb') as fobj:
        balance = pickle.load(fobj) + amount
    with open(wallet, 'wb') as fobj:
        pickle.dump(balance, fobj)
    with open(record, 'a') as fobj:
        fobj.write('%-12s%-8s%-8s%-10s%-20s\n' % (date, '', amount, balance, comment))

def query(wallet,record): #查询收支明细的函数
    print('%-12s%-8s%-8s%-10s%-20s\n' % ('date', 'cost', 'save', 'balance', 'comment'))
    with open(record) as fobj:
        for line in fobj:
            print(line,end='')
    with open(wallet,'rb') as fobj:
        balance = pickle.load(fobj)
        print("Latest Balance:%d" % balance)

def show_menu():
    cmds = {'0':cost,'1':save,'2':query}
    prompt ="""(0)cost
    (1)save
    (2)query
    (3)exit
    please input your choice(0/1/2/3):"""
    wallet = 'wallet data'
    record = 'record.txt'
    if not os.path.exists(wallet):
        with open(wallet, 'wb') as fobj:
            pickle.dump(10000, fobj)
            
    while True:
        try:
            choice = input(prompt).strip()[0]
        except IndexError:
            continue
        except (KeyboardInterrupt,EOFError):
            print()
            choice = '3'
        
        if choice not in '0123':
            print('Invaild input.try again')
            continue
        
        if choice == '3':
            break
        cmds[choice](wallet,record)

if __name__ == '__main__':
    show_menu()

80-hashlib模块之计算md5值

#check_md5.py

import hashlib
import sys

def check_md5(fname):
    m = hashlib.md5()
    
    with open(fname,'rb') as fobj:
        while True:
            data = fobj.read(4096)
            if not data:
                break
            m.update(data)
        return m.hexdigest()

if __name__ == '__main__':
    print(check_md5(sys.argv[1])) #python3 check-md5.py /etc/passwd

81-tarfile模块的基础应用

import tarfile

#压缩文件的方法
tar = tarfile.open('/tmp/demo.tar.gz','w:gz') #gzip压缩
tar.add('/etc/hosts')
tar.add('/etc/security')
tar.close()
#tar tvzf /tmp/demo.tar.gz
#解压文件的方法
tar = tarfile.open('/tmp/demo.tar.gz','r:gz')
tar.extractall() #解压所有文件到当前目录
tar.close()

82-OOP基础

为玩具厂创建一个玩具熊类。玩具熊有名字、尺寸、颜色这些数据属性;还有唱歌、说话的行为。

class BearToy:
    def __init__(self,nm,color,size):
        """__init__在实例化时自动执行,实例本身自动作为第一个参数传递给self,
        self只是习惯使用的名字,不是必须使用
        :param nm: 名字
        :param color:颜色
        :param size: 尺寸
        """
        self.name = nm
        self.color = color #绑定属性到实例
        self.size = size

    def sing(self):
        print('lalala...')

    def speak(self):
        print('My name is %s' % self.name)
        
if __name__ == '__main__':
    tidy = BearToy('Tidy','White','Large') #调用__init__
    print(tidy.color) #White
    print(tidy.size) #Large
    tidy.sing() #lalala...
    tidy.speak() #My name is Tidy

83-OOP之组合

如果两个类有本质不同,其中一个类的对象是另一个类对象的组件时,使用组和是最佳方案。

玩具熊还有生产厂商的信息,生产厂商的信息可以作为玩具熊的一个属性。

class Vendor:
    def __init__(self,phone,email):
        self.phone = phone
        self.email = email

    def call(self):
        print('calling %s' % self.phone)

class BearToy:
    def __init__(self,color,size,phone,email):
        self.color = color #绑定属性到实例
        self.size = size
        self.vendor = Vendor(phone,email)

if __name__ == '__main__':
    bigbear = BearToy('Brown','Middle','400-111-8989','sales@tedu')
    print(bigbear.color) #Brown
    bigbear.vendor.call() #calling 400-111-8989

84-OOP之继承

如果两个类有很多相同之处,使用继承更为合理。

新玩具熊增加了一个跑的行为,其他与原来玩具熊一致。

class BearToy:
    def __init__(self,nm,color,size):
        self.name = nm
        self.color = color #绑定属性到实例
        self.size = size

    def sing(self):
        print('lalala...')

    def speak(self):
        print('My name is %s' % self.name)

class NewBear(BearToy):
    def run(self):
        print('running...')

if __name__ == '__main__':
    b1 = NewBear('Venie','Beown','Small')
    b1.sing()
    b1.run()

85-OOP之子类调用父类方法

如果子类和父类具有同名的方法,那么父类方法将被遮盖住.

可以在子类中明确指明调用的是父类方法,而不是子类的同名方法.

class BearToy:
    def __init__(self,nm,color,size):
        self.name = nm
        self.color = color #绑定属性到实例
        self.size = size

    def sing(self):
        print('lalala...')

    def speak(self):
        print('My name is %s' % self.name)

class NewBear(BearToy):
    def __init__(self,nm,color,size,date):
        # BearToy.__init__(self,nm,color,size) #以下写法完全一样,更推荐下面写法
        super(NewBear,self).__init__(nm,color,size) 
        self.date = date #新品玩具熊增加玩具熊的生产日期
    
    def run(self):
        print('running...')
        
if __name__ == '__main__':
    b1 = NewBear('Venie','Beown','Small','2018-07-20')
    b1.sing()
    b1.run()

86-OOP之必须掌握的magic

class Book:
    def __init__(self,title,author,pages):
        self.title = title
        self.author = author
        self.pages = pages
        
    def __str__(self):
        return '《%s》' % self.title
    
    def __call__(self):
        print('《%s》is written by %s' % (self.title,self.author))

if __name__ == '__main__':
    py_book = Book('Core Python','Wesley',800) #调用__init__()方法
    print(py_book) #调用__str__()方法
    py_book() #调用__call__()方法

87-OOP之多重继承

类的父类(基类)可以有多个,子类可以调用所有父类的方法

如果用重名方法,生效的顺序是自下而上,自左而右。当然最好不要出现重名方法。

class A:
    def foo(self):
        print('in A foo')
    def hello(self):
        print('A hello')

class B:
    def bar(self):
        print('in B foo')
    def hello(self):
        print('B hello')

class C(B,A):
    pass
    # def hello(self):
    #     print('C hello')

if __name__ == '__main__':
    c = C() #空
    c.foo() #in A foo
    c.bar() #in B foo
    c.hello() #B hello

88-OOP之类方法和静态方法

通过Date创建实例,也可以通过Date.create创建实例

class Date:
    def __init__(self,year,month,date):
        self.year = year
        self.month = month
        self.date =date

    @classmethod #类方法,不用创建实例即可调用
    def create(cls,dstr): #cls表示类本身,class的缩写
        y,m,d =map(int,dstr.split('-')) #map(int,['2000','5','4'])
        dt = cls(y,m,d) #即Date(y,m,d)
        return dt
    @staticmethod #静态方法,写在类的外面,可以独立成为一个函数,“愣”把它放在类中了
    def is_date_vaild(dstr):
        y,m,d = map(int,dstr.split('-'))
        return 1 <= d <= 31 and 1 <=m <= 12 and y< 4000

if __name__ == '__main__':
    bith_date = Date(1995,12,3)
    print(Date.is_date_vaild('2000-5-4')) #True
    day = Date.create('2000-5-4')
    print(day) #<__main__.Date object at 0x7fb1fbc5cd68>

89-综合练习:备份程序

1、既要可以实现完全备份,又要实现增量备份

2、完全备份时,将目录打个tar包,计算每个文件的md5值

3、增量备份时,备份有变化的文件和新增加的文件,更新md5值

import time
import os
import tarfile
import hashlib
import pickle

def check_md5(fname):
    m = hashlib.md5()
    with open(fname,'rb') as fobj:
        while True:
            data = fobj.read(4096)
            if not data:
                break
            m.update(data)
    return m.hexdigest()

def full_backup(src_dir,dst_dir,md5file):
    fname = os.path.basename(src_dir.rstrip('/'))
    fname = '%s_full_%s.tar.gz' % (fname,time.strftime('%Y%m%d'))
    fname = os.path.join(dst_dir,fname)
    md5dict = {}
    
    tar = tarfile.open(fname,'w:gz')
    tar.add(src_dir)
    tar.close()
    
    for path,folders, files in os.walk(src_dir):
        for each_file in files:
            key = os.path.join(path,each_file)
            md5dict[key] = check_md5(key)
    with open(md5file,'wb') as fobj:
        pickle.dump(md5dict,fobj)

def incr_backup(src_dir,dst_dir,md5file):
    fname = os.path.basename(src_dir.rstrip('/'))
    fname = '%s_incr_%s.tar.gz' % (fname, time.strftime('%Y%m%d'))
    fname = os.path.join(dst_dir, fname)
    md5dict = {}
    
    with open(md5file,'rb') as fobj:
        oldmd5 = pickle.load(fobj)
    
    for path,folders,files in os.walk(src_dir):
        for each_file in files:
            key = os.path.join(path,each_file)
            md5dict[key] = check_md5(key)
    
    with open(md5file,'wb') as fobj:
        pickle.dump(md5dict,fobj)

    tar = tarfile.open(fname, 'w:gz')
    for key in md5dict:
        if oldmd5.get(key) != md5dict[key]:
            tar.add(key)
    tar.close()
    
if __name__ == '__main__':
    # mkdir /tmp/demo; cp -r /etc/security /tmp/demo
    src_dir = '/tmp/demo/security'
    dst_dir = '/var/tmp/backup' #mkdir /var/tmp/backup
    md5file = '/var/tmp/backup/md5.data'
    if time.strftime('%a') == 'Mon':
        full_backup(src_dir,dst_dir,md5file)
    else:
        incr_backup(src_dir,dst_dir,md5file)

90-OOP练习:实现unix2dos和dos2unix功能

windows文本行结束标志是\r\n,非windows是\n.

import os

class Convert:
    def __init__(self,fname):
        self.fname = fname
    
    def to_linux(self):
        dst_fname = os.path.splitext(self.fname)[0] + '.linux'
        with open(self.fname,'r') as src_fobj:   
            with open(dst_fname,'w') as dst_fobj:
                for line in src_fobj:
                    line = line.rstrip() + '\n'
                    dst_fobj.write(line)
    
    def to_windows(self):
        dst_fname = os.path.splitext(self.fname)[0] + '.windows'
        with open(self.fname,'r') as src_fobj:   
            with open(dst_fname,'w') as dst_fobj:
                for line in src_fobj:
                    line = line.rstrip() + '\r\n'
                    dst_fobj.write(line)

if __name__ == '__main__':
    c = Convert('/tmp/passwd') # cp /etc/passwd /tmp
    c.to_linux()
    c.to_windows()

91-re模块基础语法

import re

m = re.match('f..','food') #匹配到返回对象
print(re.match('f..','seafood')) #匹配不到返回None
m.group() #返回匹配的值
m = re.search('f..','seafood')
m.group()
re.findall('f..','seafood is food') #返回所有匹配项组成的列表

result = re.finditer('f..','seafood is food') #返回匹配对象组成的迭代器
for m in result: #迭代器中逐个取出匹配对象
    print(m.group())

re.sub('f..','abc','fish is food')
re.split('\.|-','hello-world.tar.gz') #用.和-做切割符号

patt = re.compile('f..') #先把要匹配的模式编译,提升效率
m = patt.search('seafood') #指定在哪个字符串中匹配
m.group()

92-re练习:匹配文件中指定模式

import re

def count_patt(fname,patt):
    cpatt = re.compile(patt)
    result = {}
    
    with open(fname) as fobj:
        for line in fobj:
            m = cpatt.search(line) #如果匹配不到,返回None
            if m:
                key = m.group()
                result[key] = result.get(key,0) + 1
    return result

if __name__ == '__main__':
    fname = 'access_log' #apache日志文件
    ip = '^(\d+\.){3}\d+' #日志开头的ip地址
    print(count_patt(fname,ip))
    br = 'Firefox|MSIE|Chrome' #日志中客户端浏览器
    print(count_patt(fname,br))

93-re练习:模式匹配进阶写法

import re
from collections import Counter #Counter对象是有序的,字典无序

class Countpatt:
    def __init__(self,fname):
        self.fname = fname

    def count_patt(self,patt):
        cpatt = re.compile(patt)
        result = Counter()

        with open(self.fname) as fobj:
            for line in fobj:
                m = cpatt.search(line) #如果匹配不到,返回None
                if m:
                    result.update([m.group()])
        return result

if __name__ == '__main__':
    c = Countpatt('access_log')
    ip = '^(\d+\.){3}\d+'
    br = 'Firefox|MSIE|Chrome'
    a = c.count_patt(ip)
    print(a)
    print(a.most_common(3)) #访问量最大的前三名
    print(c.count_patt(br))

94-socket基础:TCP服务器流程

服务器启动后,测试可以使用:talent 127.0.0.1 12345

import socket

host = '' #表示本机所有地址0.0.0.0
port = 12345 #应该大于1024
addr = (host,port)
s = socket.socket() #默认值就是基于TCP的网络套接字
#设置选项,程序结束之后可以立即再运行,否则要等60秒
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
s.bind(addr) #绑定地址到套接字
s.listen(1) #启动侦听进程
cli_sock,cli_addr = s.accept() #等待客户端链接
print('Client connect from:',cli_addr)
print(cli_sock.recv(2014)) #一次最多读1024字节数据
cli_sock.send(b'I 4 C U\r\n') #发送的数据要求是byte类型
cli_sock.close()
s.close()

95-可重用的TCP服务器

在[94-socket基础:TCP服务器流程]中,TCP服务器只能一个客户端连接,客户端也只能发送一条消息。本例允许客户端发送多条消息,输入end结束。客户端退出后,服务器程序不在退出,可以为下一个客户端提供服务:

import socket

host = '' #表示本机所有地址0.0.0.0
port = 12345 #应该大于1024
addr = (host,port)
s = socket.socket() #默认值就是基于TCP的网络套接字
#设置选项,程序结束之后可以立即再运行,否则要等60秒
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
s.bind(addr) #绑定地址到套接字
s.listen(1) #启动侦听进程
while True:
    cli_sock,cli_addr = s.accept() #等待客户端链接
    print('Client connect from:',cli_addr)
    while True:
        data = cli_sock.recv(2014)
        if data.strip() == b'end':
            break
        print(data.decode('utf8')) #byte类型转换为stringleix
        data = input('> ') + '\r\n' #获得的是string类型
        cli_sock.send(data.encode('utf8')) #转成bytes类型发送
    cli_sock.close()
s.close()

96-简单而完整的TCP服务器

客户端可以通过 talent 127.0.0.1 12345访问

没发送一段文字,将会收到加上当前时间的文字

import socket
from time import strftime

class TcpTimeServer:
    def __init__(self,host='',port=12345):
        self.addr = (host,port)
        self.serv = socket.socket()
        self.serv.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
        self.serv.bind(self.addr)
        self.serv.listen(1)
    
    def chat(self,c_sock):
        while True:
            data = c_sock.recv(1024)
            if data.strip() == b'quit':
                break
            data = '[%s] %s' % (strftime('%H:%M:%S'),data.decode('utf8'))
            c_sock.send(data.encode('utf8'))
        c_sock.close()
    
    def mainloop(self):
        while True:
            cli_sock,cli_addr = self.serv.accept()
            self.chat(cli_sock)
        
        self.serv.close()

if __name__ == '__main__':
    s = TcpTimeServer()
    s.mainloop()

97-简单的TCP客户端

客户端链接服务器的12345端口,在单独的一行输入end结束客户端程序

import socket

host = '192.168.4.254' #服务器IP地址
port = 12345 #服务器端口
addr = (host,port)

c = socket.socket()
c.connect(addr)
while True:
    data = input('> ') + '\r\n'
    c.send(data.encode('utf8')) #服务器收到end结束,所以要先发送再判断
    if data.strip() == 'end':
        break
    data = c.recv(1024)
    print(data.decode('utf8'))
c.close()

98-简单的UDP服务器流程

UDP是面向非连接的,不用listen、不用accept

UDP不区分客户端,就算是同一个客户端发来的多个数据包,UDP服务器也不区分,与处理多个客户的发来的数据包等同对待。

import socket
from time import strftime

host = '' 
port = 12345 
addr = (host,port)
s = socket.socket(type=socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
s.bind(addr)
while True:
    data ,cli_addr = s.recvfrom(1024)
    clock = strftime('%H:%M:%S')
    data = '[%s] %s' % (clock,data)
    s.sendto(data.encode('utf8'),cli_addr)
    
s.close()

99-简单的UDP客户端流程

UDP客户端非常简单,只要发送到服务器地址就可以了。

import socket

host = '192.168.4.254' #服务器IP地址
port = 12345 #服务器端口
addr = (host,port)

c = socket.socket(type=socket.SOCK_DGRAM)

while True:
    data = input('> ') 
    c.send(data.encode('utf8')) #服务器收到end结束,所以要先发送再判断
    if data.strip() == 'quit':
        break
    c.sendto(data.encode('utf8'),addr)
    print(c.recvfrom(1024)[0].decode('utf8'))
    #print(c.recvfrom(1024))
c.close()

100-百鸡百钱问题

我国古代数学家张丘建在《算经》一书中提出的数学问题:鸡翁一值钱五,鸡母一值钱三,鸡雏三值钱一。百钱买百鸡,问鸡翁、鸡母、鸡雏各多少?

思路:

1、答案不只一个

2、如果全是公鸡i,最多100/5只

3、如果全是母鸡j,最多100/3只

4、如果全是小鸡k,100块钱,可以买300只;但,所有鸡最多100只

5、鸡的数目i+j+k=100

6、鸡的价钱i * 5 + j * 3 + k / 3 ==100

for i in range(100//5 + 1): #//表示只留商,不要小数,舍弃余数
    for j in range(100//3 + 1):
        for k in range(100):
            if i + j + k ==100 and i * 5 + j * 3 + k / 3 ==100:
                print('公鸡:%s,母鸡:%s,小鸡:%s' % (i,j,k))
# 公鸡:0,母鸡:25,小鸡:75
# 公鸡:4,母鸡:18,小鸡:78
# 公鸡:8,母鸡:11,小鸡:81
# 公鸡:12,母鸡:4,小鸡:84

101-多进程基础

fork()后会出现子进程,父子进程都打印Hello World!,所以会有两行相同的内容输出

import os

print('starting...')
os.fork() #生成子进程,后续代码同时在父子进程中执行
print('Hello World!')
#可以根据fork()返回值判断是父进程,还是子进程
import os

print('starting...')
pid = os.fork() #返回值是个数字,对于父进程,返回值是子进程PID,子进程是0
if pid:
    print('In parent') #父进程执行的代码
else:
    print('In child') #子进程执行的代码
print('Done') #父子进程都会执行的代码
#多进程编程时,要明确父子进程的工作。如:父进程只用于fork子进程;子进程做具体的工作。
# 如果在循环体中,做完后要退出,否则子进程还会在产生子进程,孙进程...子子孙孙无穷匮也,系统奔溃。
import os

for i in range(5):
    pid = os.fork() #父进程的工作是生成子进程
    if not pid: #如果是子进程,工作完后,结束,不要进入循环
        print('hello')
        exit() #注释这一行执行,查看结果,分析原因

102-多进程的ping

没有多进程,ping一个网段IP地址往往要花费几十分钟;使用多进程,几分钟解决

import subprocess
import os

def ping(host):
    rc = subprocess.call(
        'ping -c2 %s &> /dev/null' % host,
        shell=True
    )
    if rc:
        print('%s:down' % host)
    else:
        print('%s:up' % host)

if __name__ == '__main__':
    ips = ('192.168.1.%s' % i for i in range(1,255))
    for ip in ips:
        pid = os.fork()
        if not pid:
            ping(ip)
            exit()

103-多进程效率

没有多进程,即使CPU有多个核心,程序只是运行在一个核心上,无法利用多进程提升效率。5000万次加法,如果需要2.5秒,调用两次共花费5秒。

import time

def calc():
    result = 0
    for i in range(1,50000001):
        result += 1
        print(result)

if __name__ == '__main__':
    start = time.time()
    calc()
    calc()
    end = time.time()
    print(end - start)
    
#通过多进程,程序运行在多个核心上,同样的调用两次5000万次加法运算,时间仅为一半

import time
import os

def calc():
    result = 0
    for i in range(1,50000001):
        result += 1
        print(result)

if __name__ == '__main__':
    start = time.time()
    for i in range(2):
        pid = os.fork()
        if not pid:
            calc()
            exit()
    os.waitpid(-1,0) #挂起父进程,直到子进程结束才继续执行
    os.waitpid(-1,0) #每个waitpid只能处理一个僵尸进程,两个子进程需要调用两次
    end = time.time()
    print(end - start)

104-僵尸进程

多进程编程要注意僵尸进程。子进程没有可执行代码后将变成僵尸进程,如果父进程一直运行,有没有处理僵尸进程的代码,僵尸进程也将一直存在,消耗资源。僵尸进程无法通过kill命令杀掉。

import os
import time

pid = os.fork()
if pid:
    print('In parent.sleeping...')
    time.sleep(60)
    print('Parent done.')
else:
    print('In child.sleeping...')
    time.sleep(10)
    print('Child done') #10秒后,子进程变成了僵尸进程

# watch -n1 ps a 当子进程成为僵尸进程时,显示为z
# kill试图杀死僵尸进程、父进程,查看结果

105–解决僵尸进程问题

os.waitpid()的第二个参数,0表示挂起父进程,1表示不挂起父进程.

import os
import time

pid = os.fork()
if pid:
    print('In parent.sleeping...')
    print(os.waitpid(-1,1)) #无僵尸进程可以处理,返回0
    time.sleep(20)
    print(os.waitpid(-1, 1)) #处理僵尸进程,返回子进程pid
    time.sleep(60)
    print('Parent done.')
else:
    print('In child.sleeping...')
    time.sleep(10)
    print('Child done') #10秒后,子进程变成了僵尸进程

# watch -n1 ps a 当子进程成为僵尸进程时,显示为z
# kill试图杀死僵尸进程、父进程,查看结果

106-基于多进程的时间消息服务器

1、支持多客户端同时访问

2、客户端向服务器

3、每个客户端断开后产生僵尸进程,新客户端连接时销毁所有的僵尸进程

import socket
import os
from time import strftime

class TcpTimeServer:
    def __init__(self,host='',port=12345):
        self.addr = (host,port)
        self.serv = socket.socket()
        self.serv.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
        self.serv.bind(self.addr)
        self.serv.listen(1)
    
    def chat(self,c_sock):
        while True:
            data = c_sock.recv(1024)
            if data.strip() == b'quit':
                break
            data = '[%s] %s' % (strftime('%H:%M:%S'),data.decode('utf8'))
            c_sock.send(data.encode('utf8'))
        c_sock.close()
    
    def mainloop(self):
        while True:
            cli_sock,cli_addr = self.serv.accept()
            pid = os.fork()
            if pid:
                cli_sock.close()
                while True:
                    result = os.waitpid(-1,1)[0] #waitpid会优先处理僵尸进程
                    if result == 0:
                        break
            else:
                self.serv.close()
                self.chat(cli_sock)
                exit()
        self.serv.close()

if __name__ == '__main__':
    s = TcpTimeServer()
    s.mainloop()

107-基于多线程的ping

多线程与多进程类似,但是每个线程没有自己的资源空间,它们共用进程的资源

多线程没有僵尸进程的问题

import subprocess
import threading

def ping(host):
    rc = subprocess.call(
        'ping -c2 %s &> /dev/null' % host,
        shell=True
    )
    if rc:
        print('%s:down' % host)
    else:
        print('%s:up' % host)

if __name__ == '__main__':
    ips = ['172.40.58.%s' % i for i in range(1,255)]
    for ip in ips:
        #创建线程,ping是上面定义的函数,args是传给ping函数的参数
        t = threading.Thread(target=ping,args=(ip,))
        t.start() #执行ping(ip)

108-多线程的效率

python的多线程有一个GIL(全局解释器锁),使得多个线程,某一时刻只有一个线程发送给CPU处理。所以多线程不适用计算密集型应用。更适合IO密集型应用。以下两次计算5000万次加法运算和不用多线程相比,没有效率的提升。因为CPU有上下文切换,甚至可能多线程更慢。

import time
import threading

def calc():
    result = 0
    for i in range(1,5000001):
        result += 1
        print(result)

if __name__ == '__main__':
    start = time.time()
    t1 = threading.Thread(target=calc)
    t1.start()
    t2 = threading.Thread(target=calc)
    t2.start()
    t1.join() #挂起主进程,当t1执行完后才继续向下执行
    t2.join()
    end = time.time()
    print(end - start)

109-基于多线程的时间消息队列

与[106-基于多进程的时间消息服务器]类似,只是换成了多线程

import socket
import threading
from time import strftime


class TcpTimeServer:
    def __init__(self, host='', port=12345):
        self.addr = (host, port)
        self.serv = socket.socket()
        self.serv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.serv.bind(self.addr)
        self.serv.listen(1)

    def chat(self, c_sock):
        while True:
            data = c_sock.recv(1024)
            if data.strip() == b'quit':
                break
            data = '[%s] %s' % (strftime('%H:%M:%S'), data.decode('utf8'))
            c_sock.send(data.encode('utf8'))
        c_sock.close()

    def mainloop(self):
        while True:
            cli_sock, cli_addr = self.serv.accept()
            t = threading.Thread(target=self.chat,args=(cli_sock,))
            t.start()
        self.serv.close()
           
if __name__ == '__main__':
    s = TcpTimeServer()
    s.mainloop()

110-并行批量管理远程服务器

脚本名为remote_comm.py,执行方式如下:

python3 remote_comm.py  #服务器IP地址文件  "在远程服务器上要执行的命令"

如:

python3 remote_comm.py serverips.txt  "useradd zhangsan"

远程服务器密码以及交互方式获得。

import sys
import getpass
import paramiko
import threading
import os

def remote_comm(host,pwd,command):
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy)
    ssh.connect(hostname=host,username='root',password=pwd)
    stdin,stdout,stderr = ssh.exer_command(command)
    out = stdout.read()
    error = stderr.read()
    if out:
        print('[%s] OUT:\n%s' % (host,out.decode('utf8')))
    if error:
        print('[%s] ERROR:\n%s' % (host,error.decode('utf8')))
    ssh.close()

if __name__ == '__main__':
    if len(sys.argv) != 3:
        print('Usage:%s ipaddr_file "command"' % sys.argv[0])
        exit(1)
    if not os.path.isfile(sys.argv[1]):
        print('No such file:',sys.argv[1])
        exit(2)
    fname = sys.argv[1]
    command = sys.argv[2]
    pwd = getpass.getpass()
    with open(fname) as fobj:
        ips = [line.strip() for line in fobj]
    
    for ip in ips:
        t = threading.Thread(target=remote_comm,args=(ip,pwd,command))
        t.start()

111-配置IP地址

RHEL7主机有四块网卡,名为eth0/eth1/eth2/eth3.为四块网卡配置ip地址

#!/usr/bin/env python

import sys
import re

def configip(fname,ip_addr,if_ind):
    content = """TYPE=Etherent
    BOOTPROTO=none
    NAME=eth%s
    DEVICE=eth%s
    ONBOOT=yes
    IPADDR=%s
    PREFIX=24
    """ % (if_ind,if_ind,ip_addr)
    with open(fname,'w') as fobj:
        fobj.write(content)

def check_ip(ip_addr): #判断IP地址是不是x.x.x.x格式
    m = re.match(r'(\d{1,3}\.){3}\d{1,3}$',ip_addr)
    if not m:
        return False
    return True

def show_menu():
    prompt = """Configure IP Address:
    (0)eth0
    (1)eth1
    (2)eth2
    (3)eth3
    Your choice(0/1/2/3):"""
    try:
        if_ind = raw_input(prompt).strip()[0]
    except:
        print('Invaild input')
        sys.exit(1)
    
    if if_ind not in '0123':
        print('Wrong Selection.Use 0/1/2/3')
        sys.exit(2)
    
    fname = '/etc/sysconfig/network-scripts/ifcfg-eth%s' if_ind
    ip_addr = raw_input('ip address:').strip()
    result = check_ip(ip_addr)
    if not result:
        print('Invaild ip address')
        sys.exit(3)
    configip(fname,ip_addr,if_ind)
    print('\033[32;1mConfigure iP address done.Please execute "systemct1 restart NetworkManager"\033[0m')
    
if __name__ == '__main__':
    show_menu()

112-模拟字符串lstrip用法

思路:

1、取出字符串长度

2、通过range和字符串长度得到字符串下标

3、找到非空字符串下标,剩余部分取出切片

4、如果字符串没有非空字符,返回空串

whitesps = ' \r\n\v\f\t'

def rmlsps(astr):
    for i in range(len(astr)):
        if astr[i] not in whitesps:
            return astr[i:]
    else: #所有字符均为空,循环正常结束,返回空串
        return ''

if __name__ == '__main__':
    print(rmlsps(' \thello '))

113-模拟字符串rstrip用法

whitesps = ' \r\n\v\f\t'

def rmrsps(astr):
    for i in range(-1,len(astr),-1): #自右向左,下标为负
        if astr[i] not in whitesps:
            return astr[:i + 1] #结束下标对应的字符不包含,所以加1
    else: #所有字符均为空,循环正常结束,返回空串
        return ''

if __name__ == '__main__':
    print(rmrsps(''))
    print(rmrsps(' \thello '))

114-可变不可变对象的效率

python是一种解释型语言,执行效率要比C这样的编译型语言差得多,但是也应该注意它的效率。python的各种数据类型,按更新模型可以分为可变类型(如列表、字典)和不可变类型(如数字、字符串和元组)。多使用可变类型,它的执行效率比不可变类型要高。在[36-生成密码/验证码]中,将结果保存到一个名为result的变量中。result是字符串,字符串不可变,所以python工作时,首先要申请一段内存储result的初值(空串),随机取得一个字符后(如’a’),result += 'a’实际上是要重新申请一个新的内存,把新字符串存储进去。如此往复,有几次循环,就要重新分配几次内存。如果变量result使用列表,只需要为其分配一次内存即可,因为列表是可变的.代码可以更改为以下样式:

from random import choice
import string

all_chs = string.ascii_letters + string.digits #大小写字母加数字

def gen_pass(n = 8):
    result = []

    for i in range(n):
        ch = choice(all_chs)
        result.append(ch)
    return ''.join(result)

if __name__ == '__main__':
    print(gen_pass()) #随机的8位密码
    print(gen_pass(4)) #随机的4位密码
    print(gen_pass(10)) #随机的10位密码

115-比较文件的差异

比较两个文件的差异,可以直接使用vim

# vim -d /etc/passwd /etc/passwd-

python标准库提供了一个difflib,可以进行文件的比较,并且可以生成网页的形式。

import difflib
import webbrowser
import sys
import string
import os
from random import choice

def rand_chs(n=8): #默认生成8个随机字符
    all_chs = string.ascii_letters + string.digits
    result = [choice(all_chs) for i in range(n)]
    return ''.join(result)

#函数接收两个相似的文件名,返回HTML形式的字符串
def make_diff(lfile,rfile):
    d = difflib.HtmlDiff()
    #将两个文件分别读到列表中
    with open(lfile) as fobj:
        ldata = fobj.readlines()
    with open(rfile) as fobj:
       rdata = fobj.readlines()
    return d.make_file(ldata,rdata) #返回HTML格式内容

if __name__ == '__main__':
    try:
        lfile = sys.argv[1]
        rfile = sys.argv[2]
    except IndexError:
        print('Usage:%s file1 file2' % sys.argv[0])
        sys.exit(1)
    if not os.path.isfile(lfile):
        print('No such file:',lfile)
        sys.exit(2)
    if not os.path.isfile(rfile):
        print('No such file:',rfile)
        sys.exit(3)
    data = make_diff(lfile,rfile)
    #以下只是说明内容增加中文显示,非必须项
    data = data.replace(';Added',';Added(增加) ')
    data = data.replace('>Changed', '>Changed(改变) ')
    data = data.replace('>Deleted', '>Deleted(被删除) ')
    data = data.replace('(f)irst change', '(f)irst change(第一处变更) ')
    data = data.replace('(n)ext change', '(n)ext change(下一处变更) ')
    data = data.replace('(t)op', ';(t)op(回到顶部) ')
    html_file = '/tmp/%s.html' % rand_chs() #用随机字符生成文件名
    with open(html_file,'w') as fobj:
        fobj.write(data)
    webbrowser.open_new_tab('file:///%s' % html_file) #使用浏览器打开文件 

116-插入排序

插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据,算法适用于少量数据的排序;首先将第一个作为已经排好序的,然后每次从后的取出插入到前面并排序;

  • 时间复杂度:O(n²)
  • 空间复杂度:O(1)
  • 稳定性:稳定
def insert_sort(ilist):
    for i in range(len(ilist)):
        for j in range(i):
            if ilist[i] < ilist[j]:
                ilist.insert(j, ilist.pop(i))
                break
    return ilist
 
ilist = insert_sort([4,5,6,7,3,2,6,9,8])
print ilist

117-希尔排序

希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止

  • 时间复杂度:O(n)
  • 空间复杂度:O(n√n)
  • 稳定性:不稳定
def shell_sort(slist):
    gap = len(slist)
    while gap > 1:
        gap = gap // 2
        for i in range(gap, len(slist)):
            for j in range(i % gap, i, gap):
                if slist[i] < slist[j]:
                    slist[i], slist[j] = slist[j], slist[i]
    return slist
 
slist = shell_sort([4,5,6,7,3,2,6,9,8])
print slist

118-冒泡排序

它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成

  • 时间复杂度:O(n²)
  • 空间复杂度:O(1)
  • 稳定性:稳定
list01 = [1,89,546,54,2,58,98]

def sortport():
    for i in range(len(list01)-1):
        for j in range(len(list01)-1-i):
            if list01[j] > list01[j+1]:
                list01[j],list01[j+1] = list01[j+1],list01[j]
    return list01

l = sortport()
print(l)

119-快速排序:

通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列

  • 时间复杂度:O(nlog₂n)
  • 空间复杂度:O(nlog₂n)
  • 稳定性:不稳定
def quick_sort(qlist):
    if qlist == []:
        return []
    else:
        qfirst = qlist[0]
        qless = quick_sort([l for l in qlist[1:] if l < qfirst])
        qmore = quick_sort([m for m in qlist[1:] if m >= qfirst])
        return qless + [qfirst] + qmore
 
qlist = quick_sort([4,5,6,7,3,2,6,9,8])
print qlist

120-选择排序:

第1趟,在待排序记录r1 ~ r[n]中选出最小的记录,将它与r1交换;第2趟,在待排序记录r2 ~ r[n]中选出最小的记录,将它与r2交换;以此类推,第i趟在待排序记录r[i] ~ r[n]中选出最小的记录,将它与r[i]交换,使有序序列不断增长直到全部排序完毕

  • 时间复杂度:O(n²)
  • 空间复杂度:O(1)
  • 稳定性:不稳定
def select_sort(slist):
    for i in range(len(slist)):
        x = i
        for j in range(i, len(slist)):
            if slist[j] < slist[x]:
                x = j
        slist[i], slist[x] = slist[x], slist[i]
    return slist
 
slist = select_sort([4,5,6,7,3,2,6,9,8])
print slist

121-计算x的n次方的方法

def power(x,n):
    s = 1
    while n > 0:
        n = n - 1
        s = s * x
    return s

122-计算aa + bb + c*c + ……

def clas(*numbers):
    sum = 0
    for n in numbers:
        sum = sum + n * n
    return sum

123-计算阶乘 n!

#第一种方法
def fac(n):
    num = int(input("请输入一个数字:"))
    factorial = 1
    
    #查看数字是负数,0或正数
    if num < 0:
        print("抱歉,负数没有阶乘")
    elif num == 0:
        print("0的阶乘为1")
    else:
        for i in range(1,num + 1):
            factorial = factorial * i
        print("%d 的阶乘为%d" %(num,factorial))
       
#第二种方法
def factorial(n):
    result = 1
    for i in range(1,n):
        result *= i
    return result
#第三种方法
def fact(n):
    if n == 1:
        return 1
    return n * fact(n - 1)

124-列出当前目录下的所有文件和目录名

[d for d in os.listdir('.')]

125-把一个list中所有的字符串变成小写:

l = ['Hello','World','IBM','Apple']
a = [s.lower() for s in l]
print(a)

126-有一本100页的书,可以一天看一页,也可以一天看两页,总共有多少种看法?

def read_book(n):
    if n == 1:
        return 1
    elif n == 2:
        return 2
    else:
        return read_book(n-1) + read_book(n-2)

a = read_book(10)
print(a)

127-输出某个路径下的所有文件和文件夹的路径

import os

def print_dir():
    filepath = input("请输入一个路径:")
    if filepath == "":
        print("请输入正确路径")
    else:
        for i in os.listdir(filepath):   #获取目录中的文件及子目录列表
            print(os.path.join(filepath,i)) #把路径组合起来

print(print_dir())

128-输出某个路径及其子目录下的所有文件路径

import os

def show_dir(filepath):
    for i in os.listdir(filepath):
        path = (os.path.join(filepath,i))
        print(path)
        if os.path.isdir(path):   #isdir()判断是否是目录
            show_dir(path)        #如果是目录,使用递归方法

filepath = "C:\Program File\Internet Explorer"
show_dir(filepath)

129-输出某个路径及其子目录下所有以.html为后缀的文件

import os

def print_dir(filepath):
    for i in os.listdir(filepath):
        path = os.path.join(filepath,i)
        if os.path.isdir(path):
            print_dir(path)
        if path.endswith(".html"):
            print(path)

filepath = "E:\PycharmProjects"
print_dir(filepath)

130-把原字典的键值对颠倒并生产新的字典

dict01 = {"A":"a","B":"b","C":"c"}
dict02 = {y:x for x,y in dict01.items()}
print(dict02)

#{'a': 'A', 'b': 'B', 'c': 'C'}

131-打印九九乘法表

for i in range(1,10):
    for j in range(1,i+1):
        #print('{}x{}={}\t'.format(j,i,i*j),end='')   #两种都可以
        print('%dx%d=%d\t'%(i,j,i*j),end='')
    print()

132-替换列表中所有的3为3a

num = ["harden","lampard",3,34,45,56,76,78,3,3,3]
print(num.count(3))
print(num.index(3))
for i in range(num.count(3)):  #获取3出现的次数
    ele_index = num.index(3)   #获取首次出现3的坐标
    num[ele_index] = "3a"      #修改3为3a
print(num)

133-打印每个名字

l = ["James","Meng","Xin"]
for i in range(len(l)):
    print("Hello ,%s"%l[i])

134-合并去重

list01 = [2,3,8,4,9,5,6]
list02 = [5,6,10,17,11,2]
list03 = list01 + list02
print(list03)
print(set(list03))
print(list(set(list03)))

135-随机生成验证码的两种方式

#第一种方法
import random

list01 = []
for i in range(65,91):
    list01.append(chr(i)) #通过for循环遍历assi追加到空列表中
for j in range(97,123):
    list01.append(chr(j))
for k in range(48,58):
    list01.append(chr(k))

ma = random.sample(list01,6)
print(ma)                       #获取到的为列表
ma = ''.join(ma)           #将列表转化为字符串
print(ma)

#第二种方法
import random,string

str01 = "0123456789"
str02 = string.ascii_letters   #string.ascii_letters 包含所有字母(大写或小写)的字符串
str03 = str01 + str02
ma1 = random.sample(str03,6)
ma2 = ''.join(ma1)
print(ma2)

136-猜数字游戏

import random

i = 1
a = random.randint(0,100)
b = int(input("请输入0-100中的一个数字\n然后查看是否与电脑一样:"))
while a != b:
    if a > b:
        print("你第%d输入的数字小于电脑随机数"%i)
        b = int(input("请再次输入数字:"))
    else:
        print("你第%d输入的数字大于电脑随机数"%i)
        b = int(input("请再次输入数字:"))
    i += 1
else:
    print("恭喜你,你第%d输入的数字与电脑随机数%d一样"%(i,b))

137-计算平方根

num = float(input("请输入一个数字:"))
num_sqrt = num ** 0.5
print('%0.2f 的平方根为 %0.2f'%(num,num_sqrt))

138-判断字符串是否只由数字组成

#第一种方法
def is_number(s):
    try:
        float(s)
        return True
    except ValueError:
        pass
    try:
        import unicodedata
        unicodedata.numeric(s)
        return True
    except (TypeError,ValueError):
        pass

    return False

c = is_number("455")
print(c)
#第二种方法
print("chri".isdigit())  # 检测字符串是否只由字符串组成
print("000".isnumber())  # 检测字符串是否只由字符串组成,这种方法只针对unicode对象

139-判断奇偶数

#第一种方法
num = int(input("输入一个数字: "))
if (num % 2) == 0:
   print("{0} 是偶数".format(num))
else:
   print("{0} 是奇数".format(num))
#第二种方法
while True:
    try:
        num = int(input('输入一个整数:'))    #判断输入是否为整数
    except ValueError:                      #不是纯数字需要重新输入
        print("输入的不是整数!")
        continue
    if num % 2 == 0:
        print('偶数')
    else:
        print('奇数')
    break

140-判断闰年

#第一种方法
year = int(input("输入一个年份: "))
if (year % 4) == 0:
   if (year % 100) == 0:
       if (year % 400) == 0:
           print("{0} 是闰年".format(year))   # 整百年能被400整除的是闰年
       else:
           print("{0} 不是闰年".format(year))
   else:
       print("{0} 是闰年".format(year))       # 非整百年能被4整除的为闰年
else:
   print("{0} 不是闰年".format(year))
   
#第二种方法
year = int(input("请输入一个年份:"))
if (year % 4) == 0 and (year % 100) != 0 or (year % 400) == 0:
    print("{0}是闰年".format(year))
else:
    print("{0}不是闰年".format(year))
    
#第三种方法
import calendar

year = int(input("请输入年份:"))
check_year=calendar.isleap(year)
if check_year == True:
    print ("%d是闰年"% year)
else:
    print ("%d是平年"% year)

141-获取最大值

#第一种方法
N = int(input('输入需要对比大小数字的个数:'))
print("请输入需要对比的数字:")
num = []
for i in range(1,N+1):
    temp = int(input('输入第 %d 个数字:' % i))
    num.append (temp)

print('您输入的数字为:',num)
print('最大值为:',max(num))

#第二种方法
N = int(input('输入需要对比大小数字的个数:\n'))

num = [ int(input('请输入第 %d 个对比数字: \n'%i))for i in range(1,N+1)]

print('您输入的数字为:',num)
print('最大值为: ',max(num))

#第三种方法(不适用内置函数)
def getMax(arr):
    for i in range(0, len(arr)):
        for j in range(i + 1, len(arr)):
            first = int(arr[i])
            second = int(arr[j])
            if first < second:
                arr[i] = arr[j]
                arr[j] = first
    print(arr[0])

arr = [19, 29, 30, 48]
getMax(arr)

142-斐波那契数列

斐波那契数列指的是这样一个数列 0, 1, 1, 2, 3, 5, 8, 13;特别指出:第0项是0,第1项是第一个1。从第三项开始,每一项都等于前两项之和。

# 判断输入的值是否合法
if nterms <= 0:
  print("请输入一个正整数。")
elif nterms == 1:
  print("斐波那契数列:")
  print(n1)
else:
  print("斐波那契数列:")
  print(n1, ",", n2, end=" , ")
  while count < nterms:
    nth = n1 + n2
    print(n1+n2, end=" , ")
    # 更新值
    n1 = n2
    n2 = nth
    count += 1

143-十进制转二进制、八进制、十六进制

# 获取输入十进制数
dec = int(input("输入数字:"))

print("十进制数为:", dec)
print("转换为二进制为:", bin(dec))
print("转换为八进制为:", oct(dec))
print("转换为十六进制为:", hex(dec))

144-最大公约数

def hcf(x, y):
  """该函数返回两个数的最大公约数"""

  # 获取最小值
  if x > y:
    smaller = y
  else:
    smaller = x

  for i in range(1, smaller + 1):
    if ((x % i == 0) and (y % i == 0)):
      hcf = i

  return hcf

# 用户输入两个数字
num1 = int(input("输入第一个数字: "))
num2 = int(input("输入第二个数字: "))

print(num1, "和", num2, "的最大公约数为", hcf(num1, num2))

145-最小公倍数

# 定义函数
def lcm(x, y):
 
   #  获取最大的数
   if x > y:
       greater = x
   else:
       greater = y
 
   while(True):
       if((greater % x == 0) and (greater % y == 0)):
           lcm = greater
           break
       greater += 1
 
   return lcm
  
# 获取用户输入
num1 = int(input("输入第一个数字: "))
num2 = int(input("输入第二个数字: "))
 
print( num1,"和", num2,"的最小公倍数为", lcm(num1, num2))

146-简单计算器

# 定义函数
def add(x, y):
    """相加"""
    return x + y

def subtract(x, y):
    """相减"""
    return x - y

def multiply(x, y):
    """相乘"""
    return x * y

def divide(x, y):
    """相除"""
    return x / y

# 用户输入
print("选择运算:")
print("1、相加")
print("2、相减")
print("3、相乘")
print("4、相除")

choice = input("输入你的选择(1/2/3/4):")

num1 = int(input("输入第一个数字: "))
num2 = int(input("输入第二个数字: "))

if choice == '1':
    print(num1, "+", num2, "=", add(num1, num2))

elif choice == '2':
    print(num1, "-", num2, "=", subtract(num1, num2))

elif choice == '3':
    print(num1, "*", num2, "=", multiply(num1, num2))

elif choice == '4':
    if num2 != 0:
        print(num1, "/", num2, "=", divide(num1, num2))
    else:
        print("分母不能为0")
else:
    print("非法输入")

147-生成日历

# 引入日历模块
import calendar

# 输入指定年月
yy = int(input("输入年份: "))
mm = int(input("输入月份: "))

# 显示日历
print(calendar.month(yy, mm))

148-文件IO

# 写文件
with open("test.txt", "wt") as out_file:
    out_file.write("该文本会写入到文件中\n看到我了吧!")

# Read a file
with open("test.txt", "rt") as in_file:
    text = in_file.read()

print(text)

149-字符串判断

# 测试实例一
print("测试实例一")
str = "runoob"
print(str.isalnum()) # 判断所有字符都是数字或者字母
print(str.isalpha()) # 判断所有字符都是字母
print(str.isdigit()) # 判断所有字符都是数字
print(str.islower()) # 判断所有字符都是小写
print(str.isupper()) # 判断所有字符都是大写
print(str.istitle()) # 判断所有单词都是首字母大写,像标题
print(str.isspace()) # 判断所有字符都是空白字符、\t、\n、\r

print("------------------------")

# 测试实例二
print("测试实例二")
str = "Bake corN"
print(str.isalnum()) 
print(str.isalpha()) 
print(str.isdigit()) 
print(str.islower()) 
print(str.isupper()) 
print(str.istitle()) 
print(str.isspace())

150-字符串大小写转换

str = "https://wwwblogs/ailiailan/"
print(str.upper())          # 把所有字符中的小写字母转换成大写字母
print(str.lower())          # 把所有字符中的大写字母转换成小写字母
print(str.capitalize())     # 把第一个字母转化为大写字母,其余小写
print(str.title())          # 把每个单词的第一个字母转化为大写,其余小写

151-计算每个月天数

import calendar
monthRange = calendar.monthrange(2016,9)
print(monthRange)

152-获取昨天的日期

# 引入 datetime 模块
import datetime
def getYesterday(): 
    today=datetime.date.today() 
    oneday=datetime.timedelta(days=1) 
    yesterday=today-oneday  
    return yesterday
 
# 输出
print(getYesterday())

153-列表去重

#方法一
def delList(L):
    L1 = [ ]
    for i in L:
        if i not in L1:
            L1.append(i)
    return L1
print(delList(L1))

#方法二:去重
L1=listset(L))

#a = [2,2,2,2,6,84,5,9]
#print(delList(a))
#a2 = list(set(a))
#print(a2)

154-列表插入

l = [1,2,3]
l.insert(0,4)         #在列表的索引处插入  
print(l)

155-列表元素替换

x = "hello world "
y = x.replace("hello","hi")
print(y)                                               # 结果为:hi world

156-a=1,b=2,不用中间变量交换 a 和 b 的值?

#方法一:
a = a+b
b = a-b
a = a-b
#方法二:
a = a^b
b =b^a
a = a^b
#方法三:
a,b = b,a

157-下面这段代码的输出结果将是什么?请解释?

class Parent(object):
    x=1
class Child1(Parent):
    pass
class Child2(Parent):
    pass
print(Parent.x, Child1.x, Child2.x)
Child1.x = 2
print( Parent.x, Child1.x, Child2.x)
Parent.x = 3
print( Parent.x, Child1.x, Child2.x)

#结果为:
1 1 1        #继承自父类的类属性 x,所以都一样,指向同一块内存地址。
1 2 1        #更改 Child1,Child1 的 x 指向了新的内存地址。
3 2 3        #更改 Parent,Parent 的 x 指向了新的内存地址。

158-阅读下面的代码,写出 A0,A1 至 An 的最终值。

A0 = dict(zip(('a','b','c','d','e'),(1,2,3,4,5)))          
A1 = range(10)                                                                
A2 = [i for i in A1 if i in A0]
A3 = [A0[s] for s in A0]                  #[]
A4 = [i for i in A1 if i in A3]
A5 = {i:i*i for i in A1}
A6 = [[i,i*i] for i in A1]
#结果为:
A0 = {'a': 1, 'c': 3, 'b': 2, 'e': 5, 'd': 4}
A1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
A2 = []
A3 = [1, 3, 2, 5, 4]
A4 = [1, 2, 3, 4, 5]
A5 = {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
A6 = [[0, 0], [1, 1], [2, 4], [3, 9], [4, 16], [5, 25], [6, 36],[7, 49],[8, 64] [9,81]]

159-考虑以下 Python 代码,如果运行结束,命令行中的运行结果是什么?

l = []
for i in range(10):
    l.append({'num':i})
print (l)

#结果为:
 [{'num':0},{'num':1},{'num':2},{'num':3},{'num':4},{'num':5},{'num':6},{'num':7},{'num':8},{'num':9}]

再考虑以下代码,运行结束后的结果是什么?

l = []
a = {'num':0}
for i in range(10):
    a['num'] = i
    l.append(a)
print(l)

#结果为:
 [{'num':9},{'num':9},{'num':9},{'num':9},{'num':9},{'num':9},{'num':9},{'num':9},{'num':9},{'num':9}]

160-返回文件及其子文件路径

def print_directory_contents(sPath):
 """
这个函数接收文件夹的名称作为输入参数
返回该文件夹中文件的路径
以及其包含文件夹中文件的路径
"""
# ------------代码如下--------------------
    import os
    for sChild in os.listdir(sPath):
        sChildPath = os.path.join(sPath, sChild)
        if os.path.isdir(sChildPath):
            print_directory_contents(sChildPath)
        else:
            print(sChildPath)

161-输入某年某月某日,判断这一天是这一年的第几天?(可以用 Python 标准库)

import datetime
def dayofyear():
    year = input("请输入年份:")
    month = input("请输入月份:")
    day = input("请输入天:")
    date1 = datetime.date(year=int(year),month=int(month),day=int(day))
    date2 = datetime.date(year=int(year),month=1,day=1)
    return (date1 - date2 + 1).days

162-打乱一个排好序的 list 对象 alist?

import random
alist = [1,2,3,4,5,98,56]
random.shuffle(alist)
print(alist)

163-Python 是如何进行类型转换的?

int(x,base=10)                #x字符串或数字,base进制数,默认十进制 浮点转为整数
float                                                          #整数转换为浮点型
complex(1,2)                                        #转换为复数
str(10)                                                     #将对象转换为字符串
repe()                                                      #将对象转换为表达式字符串
repr(dict)                                              #将对象转换为表达式字符串
eval(str)                                #用来计算在字符串中有效的python表达式,返回一个对象
tuple(listi)                                           #将列表转化为元组
list()                                                      #将元组转换为列表
set                                                         #转换集合

164-按 alist 中元素的 age 由大到小排序

alist =[{'name':'a','age':20},{'name':'b','age':30},{'name':'c','age':25}]
def sort_by_age(list1):
    return sorted(alist,key=lambda x:x['age'],reverse=True)

re = sort_by_age(alist)
print(re)

165-写一个列表生成式,产生一个公差为 11 的等差数列?

print([x*11 for x in range(10)])

166-给定两个列表,怎么找出他们相同的元素和不同的元素?

1. list1 = [1,2,3]
2. list2 = [3,4,5]
3. set1 = set(list1)
4. set2 = set(list2)
5. print(set1&set2)
6. print(set1^set2)

167-请写出一段 Python 代码实现删除一个 list 里面的重复元素?

比较容易记忆的是用内置的 set:

l1 = ['b','c','d','b','c','a','a']
l2 = list(set(l1))
print(l2)

如果想要保持他们原来的排序:
用 list 类的 sort 方法:

l1 = ['b','c','d','b','c','a','a']
l2 = list(set(l1))
l2.sort(key=l1.index)
print (l2)

也可以这样写:

l1 = ['b','c','d','b','c','a','a']
l2 = sorted(set(l1),key=l1.index)
print (l2)

也可以用遍历:

l1 = ['b', 'c', 'd', 'b', 'c', 'a', 'a']
l2 = []
for i in l1:
    if not i in l2:
        l2.append(i)
        print (l2)

168-获取 1~100 被 6 整除的偶数?

def A():
    alist = []
    for i in range(1,100):
        if i % 6 == 0:
            alist.append(i)
    print(alist)

A()

169-将以下 3 个函数按照执行效率高低排序

def f1(lIn):
    l1 = sorted(lIn)
    l2 = [i for i in l1 if i<0.5]
    return [i*i for i in l2]

def f2(lIn):
    l1 = [i for i in l1 if i<0.5]
    l2 = sorted(l1)
    return [i*i for i in l2]

def f3(lIn):
    l1 = [i*i for i in lIn]
    l2 = sorted(l1)
    return [i for i in l1 if i<(0.5*0.5)]

按执行效率从高到低排列:f2、f1 和 f3。要证明这个答案是正确的,你应该知道如何分析自己代码的性能。Python
中有一个很好的程序分析包,可以满足这个需求。

import random
import cProfile
lIn = [random.random() for i in range(100000)]
cProfile.run('f1(lIn)')
cProfile.run('f2(lIn)')
cProfile.run('f3(lIn)')

170-请尝试用“一行代码”实现将 1-N 的整数列表以 3 为单位分组,比如 1-100 分组后为?

print([[x for x in range(1,100)][i:i+3] for i in range(0,len(list_a),3)])

171-给定一个 int list a,满足 a[i + 1]>=a[i],给定 int key找出 list a 中第一个大于等于 key 的元素的 index,无满足要求的元素则返回-1

def findindex(int_list,int_key):
    int_list = sorted(int_list)
    for i in range(len(int_list)):
        if int_list[i] == int_key:
            return i
    return -1
if __name__ == "__main__":
    lista = [12,3,4,5,8,6]
    index = findindex(lista,5)
    print(index)

172-字典转换为字符串

a = {"name":"jack","age":30}
#现在需要生成字符串:name=jack|age=30
#请用一行代码实现:
s = '|'.join([str(x)+'='+str(a[x]) for x in a])

173-请将这两个list合并,去重并按照升序排列

list1 = [2, 3, 8, 4, 9, 5, 6]
list2 = [5, 6, 10, 17, 11, 2]
list_new = list1 + list2
list = []
for x in list_new:
	if x not in list:
		list.append(x)
list.sort()
print(list)

174-写一段程序,判断字符串内左右括号是否配对

class SStack():
    def __init__(self):
        self.__elem = []
    def is_empty(self):
        return self.__elem == []
    def top(self):
        return self.__elem[-1]
    def push(self,elem):
        self.__elem.append(elem)
    def pop(self):
        return self.__elem.pop()

def kuohao(text):
    kinds = "()[]{}" #用来定义出现的括号,因为待匹配的字符中含有其他的字符,我们值检查括号是否匹配,而且是只有出现括号后再进行匹配
    zuo = "([{"   #定义左括号,如果是左括号就入栈
    dict0 = {")":"(","]":"[","}":"{"} #匹配字典,这个字典定义了匹配规则,如果字典的键值对匹配就可以认定括号是匹配的
    def pipei(text):     #将等待匹配的文本输入,这个函数的目标是从文本中过滤出括号
        i,text_len = 0,len(text) #扫描指针用来记录匹配位置
        while True:
            while  i< text_len and text[i] not in kinds: #用来寻找到括号
                i += 1
            if i >= text_len: #如果字符串中没有包含括号则结束
                return
            yield text[i],i  #返回括号字符和字符对应的下标
            i += 1

    st = SStack()
    for text0,i in pipei(text):#获取得到的符号进行匹配,因为pipei()是一个含有yield函数,所以是一个生成器,调用它会产生一个可迭代的对象
        if text0 in zuo: #如果是左括号就让它入栈
            #print(text0)
            st.push(text0)
        elif st.pop() != dict0[text0]:#如果是右括号,就弹出栈顶元素进行匹配检查
            print("本次不匹配")
            return False #遇到不匹配的,就直接退出函数,结束匹配
    print("所有的括号都已经匹配完毕,匹配成功!") #如果函数还能够执行到这里说明所有的括号都是匹配的
    return True
#kuohao("({{[]}})")
kuohao("[{}]")

175-将一个正整数分解质因数。例如输入90,打印90=233*5.

n = num = int(input('请输入一个数字:'))  # 用num保留初始值
f = []  # 存放质因数的列表

for j in range(int(num / 2) + 1):  # 判断次数仅需该数字的一半多1次
    for i in range(2, n):
        t = n % i  # i不能是n本身
        if t == 0:  # 若能整除
            f.append(i)  # 则表示i是质因数
            # 除以质因数后的n重新进入判断,注意应用两个除号,使n保持整数	
            n = n // i
            break  # 找到1个质因数后马上break,防止非质数却可以整除的数字进入质因数列表

if len(f) == 0:  # 若一个质因数也没有
    print('该数字没有任何质因数。')
else:  # 若至少有一个质因数
    f.append(n)  # 此时n已被某个质因数整除过,最后一个n也是其中一个质因数
    f.sort()  # 排下序
    print('%d=%d' % (num, f[0]), end='')
    for i in range(1, len(f)):
        print('*%d' % f[i], end='')

176-实现一个函数,在给定数组中寻找第2 大的数。

def fn():
	a=[1,3,5,7,9]
	return sorted(a[1])

177-求二叉树深度

class TreeNode(object):
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None
class Solution(object):
    def isBalanced(self, root):
        if root==None:
            return 0
        leftheight=self.isBalanced(root.left)
        rightheight=self.isBalanced(root.right)
        if leftheight>=rightheight:
            return leftheight+1
        else:
            return rightheight+1
input_3=TreeNode(3)
input_4=TreeNode(4)
input_5 = TreeNode(5)
input_5.left=input_3
input_5.right=input_4
input_18 = TreeNode(18)
input_all = TreeNode(2)
input_all.left = input_5
input_all.right = input_18
slu_ = Solution()
print (input_all)
t = slu_.isBalanced(input_all)
print (t)

178-求两个字符串的最长公共子串

def initindexs(char, string):
    index = []
    length = len(string)
    for i in range(length):
        if char == string[i]:
            index.append(i + 1)  # 保存相同字符坐标+1的位置
    return index

def Substring(str1, str2):
    str1_len = len(str1)
    str2_len = len(str2)
    length = 0
    longest = 0
    startposition = 0
    start = 0
    for i in range(str1_len):
        start = i
        index = initindexs(str1[i], str2)
        index_len = len(index)
        for j in range(index_len):
            end = i + 1
            while end < str1_len and index[j] < str2_len and str1[end] == str2[index[j]]:  # 保证下标不会超出列表范围
                end += 1
                index[j] += 1
            length = end - start
            if length > longest:
                longest = length
                startposition = start

    return startposition, longest

str1 = "pmcdcdfe"
str2 = 'aoccddcdfe'
Substring(str1, str2)
(start, longest) = Substring(str1, str2)
print(start, longest)
for i in range(longest):
    print(str1[start + i], end=' ')

179-如何快速计算两个list的交集、并集

#简单的方法:
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
b = [2, 5, 8, 11, 0]
# 交集(intersection)
intersection = [v for v in a if v in b]
# 并集( union)
union = b.extend([v for v in a])

#高效的方法:
# 交集(intersection)
intersection = list(set(a).intersection(set(b)))
# 并集(union)
union = list(set(a).union(set(b)))

180-翻转一个字符串s = “abcdef”

string = 'abcdef'
#第一种方法
def string_reverse1(string):
    return string[::-1]
#第二种方法
def string_reverse2(string):
    t = list(string)
    l = len(t)
    for i,j in zip(range(l-1,0,-1),range(1/2)):
        t[i],t[j] = t[j],t[i]
    return "".join(t)
#第三种方法
def string_reverse3(string):
    if len(string) <= 1:
        return string
    return string_reverse3(string[1:] + string[0])
#第四种方法
from collections import deque
def string_reverse4(string):
    d = deque()
    d.extendleft(string)
    return ''.join(d)
#第五种方法
def string_reverse5(string):
    # return ''.join(string[len(string) - i] for i in range(1,len(string) + 1))
    return  ''.join(string[i] for i in range(len(string) -1 ,-1,-1))

print(string_reverse1(string))   #fedcba
print(string_reverse1(string))   #fedcba
print(string_reverse1(string))   #fedcba
print(string_reverse1(string))   #fedcba
print(string_reverse1(string))   #fedcba

181-判断一个字符串是否为回文字符串(将字符串反转之后,得到的字符串同原字符串,称为回文字符串

s = input("请输入文字: ")
# 反转字符串s
r = s[::-1]
if s == r:
    print(s, "是回文")
else:
    print(s, "不是回文")

更多推荐

python编程实例