重点一:字典中取某字段的最大值
prices = {
'ACME': 45.22,
'AAPL': 642.17,
'IBM': 30.20,
'FB': 10.20
}
print(min(prices, key=lambda k: prices[k]))
print(max(prices, key=lambda k: prices[k]))
重点二:词语数组中出现次数最多的词
words = [
'look', 'into', 'my', 'eyes', 'look', 'into', 'my', 'eyes',
'the', 'eyes', 'the', 'eyes', 'the', 'eyes', 'not', 'around', 'the',
'eyes', "don't", 'look', 'around', 'the', 'eyes', 'look', 'into',
'my', 'eyes', "you're", 'under'
]
word_counts = Counter(words)
print(word_counts.most_common(3))
重点三:字典排序问题
rows = [
{'fname': 'Brian', 'lname': 'Jones', 'uid': 1003},
{'fname': 'David', 'lname': 'Beazley', 'uid': 1002},
{'fname': 'John', 'lname': 'Cleese', 'uid': 1001},
{'fname': 'Big', 'lname': 'Jones', 'uid': 1004}
]
rows_by_fname = sorted(rows, key=itemgetter('fname'))
rows_by_uid = sorted(rows, key=itemgetter('uid'))
print(rows_by_fname)
print(rows_by_uid)
重点四:列表生成式
print([a * a for a in range(1, 20)])
print([a * a for a in range(1, 20) if a % 2 == 0])
重点五:字符操作常用方法
字符串格式转换re.sub(匹配内容的正则表达式, 替换结果的表达式, 目标字符串)
text = 'Today is 11/27/2012. PyCon starts 3/13/2013.'
print(re.sub(r'(\d+)/(\d+)/(\d+)', r'\3-\1-\2', text))
正则表达式常用优先编译式(在用之前就把匹配规则进行了编译,这样重复利用效率更高)
(.*?)并不支持多行模式(原因是.是无法匹配换行符的)
(?:.|\n) 让 . 可以匹配任何字符,包括换行符
re.DOTALL也可以让.匹配所有字符
comment = re.compile(r'/\*(.*?)\*/')
text1 = '/* this is a comment */'
text2 = '''/* this is a
multiline comment */
'''
print(comment.findall(text1))
print(comment.findall(text2))
字符审查,剔除掉一些非法的字符(\n \t 等)
s = 'pýtĥöñ\fis\tawesome\r\n'
remap = {
ord('\t'): ' ',
ord('\f'): ' ',
ord('\r'): None # Deleted
}
a = s.translate(remap)
print(a)
重点六:上下文管理协议(with)
如果需要一个对象能进行with操作,那么就需要使用__enter__()/exit()方法进行修饰一个类
可以看作一个对象初始化函数的前置函数和后置函数
class Open:
def __init__(self, name):
self.name = name
def __enter__(self):
print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
# return self
def __exit__(self, exc_type, exc_val, exc_tb):
print('with中代码块执行完毕时执行我啊')
with Open('a.txt') as f:
print('=====>执行代码块')
# print(f,f.name
理解与装饰器的区别:虽然装饰器也能起到上下文协议的效果,做前置后置函数,
但是装饰器的作用更加宽泛一些,例如给对象添加属性,实现本不属于这个对象的
功能,或者替代掉原生的方法和返回值等,而上下文协议并不能做到这点。
TODO 无法触发描述符
重点七:__set__方法的作用:set、__get__把一个类或者对象视为一种数据,
class Foo(object):
def __init__(self, name="shei"):
print(name)
self.name = name
def __get__(self, instance, owner):
raise ValueError('Testing!!!!')
def __set__(self, key, value):
raise ValueError('Testing!!!!')
def __delete__(self, instance):
print('触发delete')
class Foo2(object):
name = Foo()
foo = Foo('ssss2')
foo.name = 'abc'
print(foo.name)
foo.name = 'sss'
print(foo.name)
del foo
print(Foo.name)
重点八:常用的os方法
是否存在xxx文件
print(os.path.exists('test.txt'))
# 是xxx是否为文件
print(os.path.isfile('test.txt'))
# xxx是否为文件夹
print(os.path.isdir('test.txt'))
# xxx是否是链接
print(os.path.islink('/usr/local/bin/python3'))
# 返回xxx使用软链的真实地址(linux、unix中才存在)
print(os.path.realpath('test.txt'))
# 获取xxx的占用大小
print(os.path.getsize('test.txt'))
重点九:文件夹遍历的几种写法
方式一 递归遍历
all_file = []
def getallfile(path):
all_file_list = os.listdir(path)
for file in all_file_list:
file_path = os.path.join(path, file)
# 判断是不是文件夹
if os.path.isdir(file_path):
getallfile(file_path)
all_file.append(file_path)
return all_file
path = "C:\Users\zs\PycharmProjects\demo"
all_files = getallfile(path)
for item in all_files:
print(item)
方式二 walk()函数遍历
dirpath:要列出指定目录的路径
dirnames:目录下的所有文件夹
filenames:目录下的所有文件
def getallfiles(path):
allfile = []
for dirpath, dirnames, filenames in os.walk(path):
for dir in dirnames:
allfile.append(os.path.join(dirpath, dir))
for name in filenames:
allfile.append(os.path.join(dirpath, name))
return allfile
path = "C:\Users\zs\PycharmProjects\demo"
allfile = getallfiles(path)
for file in allfile:
print(file)
重点十:生成器,迭代器(next()方法)大文件、大列表常用(避免一次性读完整个文件)
通过生成器的方式去访问有可能需要访问大文件、大列表,避免一次性把所有的内容都搬到内存中
a = frange(0, 4, 0.5)
print(next(a))
print(next(a))
print(next(a))
重点十一:RPC底层原理(核心:序列化和反序列化)
PRC架构:Client、Client Stub、Server、Server Stub
Client和Server就是本来就存在的服务方和消费服务方
而Stub则可以理解为服务方与消费方之间的翻译官
重点十二:启动线程的常用写法
def countdown(n, started_evt):
print('countdown starting')
started_evt.set()
while n > 0:
print('T-minus', n)
n -= 1
time.sleep(5)
started_evt = Event()
# t1 = Thread(target=countdown, args=(10, started_evt), daemon=True)
# t2 = Thread(target=countdown, args=(10, started_evt), daemon=True)
重点十三:多线程与多进程
多进程的写法
def pstart(name):
# time.sleep(0.1)
print("Process name: %s, pid: %s " % (name, os.getpid()))
subproc = Process(target=pstart, args=('subprocess',))
subproc.start()
subproc.join()
print("subprocess pid: %s" % subproc.pid)
print("current process pid: %s" % os.getpid())
多线程和多进程的区别:在python中,多线程其实是假的多线程,原因是因为Python运行过程中
有GIL锁(用于锁住CPython解释器,同一时刻只允许一个执行单位在CPU上进行运算)
因此很多情况下,多线程效率并没有提升
而多进程则没有这样的问题,前提是能处理好数据的同步问题
重点十四:多线程自动释放锁(with lock写法)避免死锁
num = 0 # 全局变量多个线程可以读写,传递数据
mutex = threading.Lock() # 创建一个锁
class Mythread(threading.Thread):
def run(self):
global num
with mutex: # with Lock的作用相当于自动获取和释放锁(资源)
for i in range(1000000): # 锁定期间,其他线程不可以干活
num += 1
print(num)
# mythread = []
# for i in range(5):
# t = Mythread()
# t.start()
# mythread.append(t)
# for t in mythread:
# t.join()
# print("game over")
重点十五:unittest
setUp()方法用于测试用例执行前的初始化工作。如测试用例中需要访问数据库,可以在setUp中建立数据库连接并进行初始化。如测试用例需要登录web,可以先实例化浏览器。
tearDown()方法用于测试用例执行之后的善后工作.如关闭数据库连接/关闭浏览器
import requests
import unittest
class Test_Tq(unittest.TestCase):
def setUp(self):
print("开始")
def tearDown(self):
print("结束")
def test01(self):
# 接口地址
url = "http://v.juhe.cn/weather/index"
# 构造数据
para = {"cityname": "北京", "key": "221ec2c9d854d2859310ea808cb760fd"}
res = requests.get(url, params=para)
r = res.json()
self.assertEqual(r["reason"], "successed!")
# self.assertEqual(r["reason"],"failed!")
unittest.main()
**重点十六:实现一个装饰器
装饰器=高阶函数+函数嵌套+闭包
1.高阶函数 = 参数是函数 || 返回值为函数
2.函数嵌套 = 函数中有函数
3.闭包 = 内函数中有外函数的变量 && 外函数的返回值指向内函数
其实就是将一个已有的函数,放到另外一个方法中,作为新方法的参数或者操作之一
这样的代码块就称为装饰器**
例子:
def timmer(func):
def wrapper():
print(func)
start_time = time.time()
func()
stop_time = time.time()
print('运行的时间是:%s' % (stop_time - start_time))
return wrapper()
def test():
time.sleep(3)
print('test执行!!')
test = timmer(test)
try:
test()
except TypeError as reason:
print('出错了!!!TT/n, 错误原因是:'+str(reason))
print("出错也能执行")