1.生成器
2.wordfreq一个库,集成了jieba,一些英语的词典什么的,可以用来分词,但是我感觉可能就不能自定义用户字典了。
tokens = wordfreq.tokenize(l.strip(), ‘zh’)
3.pytorch的排序
y, i = torch.sort(x, d, true) --有true,则表示降序,默认升序
返回y是相应的值,而i是坐标,存储的是LongStorage类型的
如果x不是一维的,那么返回的i是一个LongStrage的多维的值
4.生成等间隔的数:numpy.linspace( *start*, *stop*, *num=50*, *endpoint=True*, *retstep=False*, *dtype=None*)
num是在这个开始到结束之间我们取多少个数,endpoint是包不包括结束的数。
5.生成某个范围内不重复的数的list:
1⃣️(a,b)之间取列表长度个数形成一个list, random.sample方法random_id = random.sample(range(a,b),列表长度)
如:rand_index = random.sample(range(0,len(x)),batch_size)
2⃣️random.randint方法
如:random_index = [random.randint(0, len(x)-1) for i in range(batch_size)]
6.正则,匹配时间,以及文件读写和路径
import re
import os
import sys
# 获取当前路径
cur = sys.path[0]
data = os.path.join(cur,"data")
new_data = os.path.join(cur,"new_data")
print(data)
for filename in os.listdir(data):
# print(filename)
with open(os.path.join(data,filename),encoding="utf-8")as f:
contentents = f.readlines()
new_file = []
for line in contentents:
line = line.strip()
line_need = re.findall("成功采集并更新到数据库:",line)
if line_need:
# 下面的正则匹配的是01/07 16:30:54:这种日期格式
need = re.sub(r'([012]\d)/([012]\d) ([01]\d|2[0-3])\:([0-5]\d)\:([0-5]\d)',"",line)
# print(need)
need = need.replace("[Success]:成功采集并更新到数据库:","")
new_file.append(need)
with open(os.path.join(new_data,filename),"w",encoding="utf-8") as f2:
f2.writelines([line+'\n' for line in new_file])
- collections
collections.OrderedDict() 有顺序的词典。
8.随机打乱数据,输入是list形式,会改变原有数据。
import random
data = [[1,1,1,1],[2,2,2,2],[3,3,3,3],[4,4,4,4]]
random.shuffle(data)
print(data)
输出:
[[2, 2, 2, 2], [1, 1, 1, 1], [3, 3, 3, 3], [4, 4, 4, 4]]
9.2019年1月15,今日踩坑:
二维不等长的list转numpy时,使用np.array转换失败。
data = [[1,1,1,1],[2,2,2,2,2],[3,3,3,3,3,3],[4,4,4,4,4,4,4]]
data_np = np.array(data)
print(data_np)
输出:
[list([1, 1, 1, 1]) list([2, 2, 2, 2, 2]) list([3, 3, 3, 3, 3, 3])
list([4, 4, 4, 4, 4, 4, 4])]
解决方法:(这种方法会让numpy数组的长度相同,不够的补0)
data = [[1,1,1,1],[2,2,2,2,2],[3,3,3,3,3,3],[4,4,4,4,4,4,4]]
# print(type(data))
max_len = np.max([len(item) for item in data])
new_array = np.zeros((len(data), max_len))
for index, data in enumerate(data):
# print(index,data)
new_array[index][:len(data)] = data
print(new_array)
补充一下查到的二维numpy转list,尽量用array.tolist()方法。
10.python vars
vars() 函数返回对象object的属性和属性值的字典对象.
用法:vars([object])
11.将print的日志写到文件里:
def write_log(filename,things):
with open(filename,"a") as f:
f.write(things+"\n")
print_log = '[epoch:{},on the {} st batch] loss: {:.8f} accuracy:{:.3f}'.format((epoch+1),(i+1),(running_loss/(print_every*batch_size)),(right_num/(print_every*batch_size)))
print(print_log)
write_log("log.txt",print_log)
格式化的时候保留的小数位数,见上面的代码➡️{:.8f}
12.向上取整math.ceil()
13.单下划线开头(_foo)的代表不能直接访问的类属性,需通过类提供的接口进行访问,不能用“from xxx import ”而导入;以双下划线开头的(__foo
)代表类的私有成员;以双下划线开头和结尾的(__foo__
)代表python里特殊方法专用的标识,如__init__()
代表类的构造函数。
14.文件有多少行:lineNums = len(open(fileName).readlines())
文件编码的坑可以看我之前写的这个博客写python时遇到的问题
15.sys.argv[]的用法简明解释
sys.argv[]说白了就是一个从程序外部获取参数的桥梁,这个“外部”很关键,所以那些试图从代码来说明它作用的解释一直没看明白。因为我们从外部取得的参数可以是多个,所以获得的是一个列表(list),也就是说sys.argv其实可以看作是一个列表,所以才能用[]提取其中的元素。其第一个元素是程序本身,随后才依次是外部给予的参数
16.Mac下在用os.listdir()读取文件列表时出现了.DS_Store文件,.DS_Store是Mac OS保存文件夹的自定义属性的隐藏文件,如文件的图标位置或背景色,相当于Windows的desktop.ini.处理方法:
[f for f in os.listdir(path) if not f.startswith('.')]
17.数组切片的逆序输出:
print(l[::-1])
18.可变参数
*args和**kwargs
*args会按顺序将输入的参数送入函数内,多余的打包成tuple送到函数内,**kwargs则是将多余输入的参数打包成字典送入函数内。
def test_args(x, y, *args):
print(x, y, args)
def test_kwargs(x,**kwargs):
print(x,kwargs)
def args_kwargs(*args,**kwargs):
print("args:",args)
print("kwargs:",kwargs)
print("---test *args------")
test_args(1,2,3,4,5)
print("---test *kwargs------")
test_kwargs(1,a=2,b=3,c=4)
print("---test *args and *kwargs------")
args_kwargs(1,2,a=2,b=3,c=4)
结果:
---test *args------
1 2 (3, 4, 5)
---test *kwargs------
1 {'a': 2, 'b': 3, 'c': 4}
---test *args and *kwargs------
args: (1, 2)
kwargs: {'a': 2, 'b': 3, 'c': 4}
19.闭包
闭包定义:内部函数引用外部作用域的变量,并且外函数的返回值是内函数的引用。
外部函数发现自己的临时变量会在将来的内部函数中用到,自己在结束的时候,返回内函数的同时会把外函数的临时变量送给内函数绑定在一起。
闭包不能修改外部作用域的局部变量,如果想要修改闭包变量的时候,可以用nonlocal关键字声明这个变量,或者把闭包变量在外函数的修改成可变数据类型,如列表。
20.字符与ASCII码之间的转换
ord©返回字符的ASCII码,例如ord(‘a’)返回整形数值97。
chr(i)返回对应字符。例如chr(97)返回字符’a’。
21.用python判断读入的文件是什么编码方式
import chardet
f = open("1.txt","rb")
print(chardet.detect(f.read())['encoding'])
22.一直混的write和writelines方法,区别就是write写入的是字符串,writelines写入的是list型的可迭代对象
file.write(str)的参数是一个字符串,就是你要写入文件的内容.
file.writelines(sequence)的参数是序列,比如列表,它会迭代帮你写入文件
23.sorted是不会改变list的内容的,而.sort()会改变
sorted还可以根据长度排序:
list1 = ['orange', 'apple', 'zoo', 'internationalization', 'blueberry']
list4 = sorted(list1, key=len)
print(list4)
24.一个没懂的斐波那契?
def fib(n):
a, b = 0, 1
for _ in range(n):
a, b = b, a + b
yield a
def main():
for val in fib(20):
print(val)
25.约瑟夫环
def main():
persons = [True] * 30
counter, index, number = 0, 0, 0
while counter < 15:
if persons[index]:
number += 1
if number == 9:
persons[index] = False
counter += 1
number = 0
index += 1
index %= 30
# for person in persons:
# print('基' if person else '非', end='')
26.Python面向对象
如果想定义一个类中的属性是私有的,可以在给属性命名时前面加两个下划线开头。实际上Python是将这些私有属性/私有方法重新换了个名字,访问时可以采用下面的方法访问:
私有变量:实例._类名__变量名
私有方法:实例._类名__方法名()
如:
class Student(object):
def __init__(self, name, age):
self.__name = name
self.__age = age
def __str__(self):
return self.__name + ': ' + str(self.__age)
stu = Student('哈哈', 23)
# 'Student' object has no attribute '__name'
print(stu.__name)
# 用下面的方式照样可以访问类中的私有成员
print(stu._Student__name)
print(stu._Student__age)
此外,如果我们想要暗示属性是受保护的不建议外界直接访问,可以使用@property包装器来包装getter和setter方法。
class Person(object):
def __init__(self, name, age):
self._name = name
self._age = age
# 访问器 - getter方法
@property
def name(self):
return self._name
# 访问器 - getter方法
@property
def age(self):
return self._age
# 修改器 - setter方法
@age.setter
def age(self, age):
self._age = age
写在类中的方法并不都需要是对象方法,可以使用@staticmethod静态方法来对某些调用方法时还未创建出的对象。静态方法无隐含参数。
类方法隐含的参数为类本身cls,使用@classmethod这种类方法去定义一个防范能够访问类属性;
self代表类的实例
继承
- class 派生类名(基类名)
- 子类不重写__init__,实例化子类时会自动调用父类定义的__inti__;如果重写时要继承父类的构造方法,可以使用super关键字:
super(子类,self).__init__(参数1,参数2,....)
或者父类名称.__init__(self,参数1,参数2,...)
多态
- 子类继承了父类的方法后,对父类已有的方法进行了重写,当我们调用这个子类重写的方法时,不同的子类对象会表现出不同的行为,这个就是多态。
@abstractmethod:抽象方法,含abstractmethod方法的类不能实例化,继承了含abstractmethod方法的子类必须复写所有abstractmethod装饰的方法,未被装饰的可以不重写。常见是在含abstractmethod方法的类定义抽象方法时直接在函数体内写pass,继承时再进行重写
27.增强读取文件的健壮性:使用try…except…finally
try:
with open('致橡树.txt', 'r', encoding='utf-8') as f:
print(f.read())
except FileNotFoundError:
print('无法打开指定的文件!')
except LookupError:
print('指定了未知的编码!')
except UnicodeDecodeError:
print('读取文件时解码错误!')
读取文件的三种方法:
#一次性读取整个文件内容
f.read()
#通过for in循环逐行读取
for line in f:
print(line,end='')
#读取文件按行读取到列表中
lines=f.readlines()
直接将dict类型的数据写入json文件中会发生报错,因此在将数据写入之前先使用json.dump()
json模块主要有四个比较重要的函数,分别是:
- dump - 将Python对象按照JSON格式序列化到文件中
- dumps - 将Python对象处理成JSON格式的字符串
- load - 将文件中的JSON数据反序列化成对象
- loads - 将字符串的内容反序列化成Python对象
28.正则表达式文档正则表达式30分钟入门教程
要实现多个线程间的通信,比较常想到的方法就是设置一个全局变量让多个线程共享。但是当多个线程共享同一个变量(我们通常称之为“资源”)的时候,很有可能产生不可控的结果从而导致程序失效甚至崩溃。如果一个资源被多个线程竞争使用,那么我们通常称之为“临界资源”,对“临界资源”的访问需要加上保护,否则资源会处于“混乱”的状态。也就是通过锁来保护临界资源。
########多线程#######
from time import sleep
from threading import Thread,Lock
class Account(object):
def __init__(self):
self._balance = 0
self._lock = Lock()
def deposit(self, money):
# 先获取锁才能执行后续的代码
self._lock.acquire()
try:
new_balance = self._balance + money
sleep(0.01)
self._balance = new_balance
finally:
# 在finally中执行释放锁的操作保证正常异常锁都能释放
self._lock.release()
@property
def balance(self):
return self._balance
class AddMoneyThread(Thread):
def __init__(self, account, money):
super().__init__()
self._account = account
self._money = money
def run(self):
self._account.deposit(self._money)
def main():
account = Account()
threads = []
# 创建100个存款的线程向同一个账户中存钱
for _ in range(100):
t = AddMoneyThread(account, 1)
threads.append(t)
t.start()
# 等所有存款的线程都执行完毕
for t in threads:
t.join()
print('账户余额为: ¥%d元' % account.balance)
if __name__ == '__main__':
main()
30.filter
filter的作用是过滤集合(过滤掉经过函数处理的返回值为0,false的元素)filter(function, iterable)
newlist = list(filter(lambda x: x%2 , [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]))
#输出:[1, 3, 5, 7, 9]
mapmap(function, iterable, ...)
map的作用是对集合里面的每一个元素进行处理
newlist2 = list(map(lambda x:x%2,[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]))
#输出:[1, 0, 1, 0, 1, 0, 1, 0, 1, 0]
匿名函数(Lambda)用法:1⃣️使代码更加简洁2⃣️把一个函数变成更多其他重复要用的函数。如下:
def add_n(x, y):
return x+y
#由于我们在使用中其中一个参数只用到了3,那么我们可以重新利用匿名函数定一个add_three的函数
add_three = lambda x: add_n(x, 3)
print(add_three(3))
31.参数的元信息
用法:增加方法的可读性
def add(x:int, y:int) -> int:
return x + y
print(add(3, 4))
print(help(add))
- 装饰器
装饰器:python装饰器 装饰器的作用:本质上是一个 Python 函数或类,它可以让其他函数或类在不需要做任何代码修改的前提下增加额外功能,装饰器的返回值也是一个函数/类对象
#装饰器
from functools import wraps
def decorator_name(f):
#避免装饰器重写函数名字和注释文档
@wraps(f)
def decorated(*args, **kwargs):
if not can_run:
return "Function will not run"
return f(*args, **kwargs)
return decorated
@decorator_name
def func():
return ("Function is running")
can_run = True
print(func())
# Output: Function is running
can_run = False
print(func())
#Output: Function will not run
使用装饰器写单例模式:
from functools import wraps
from threading import Lock
def singleton(f):
"""线程安全的单例装饰器"""
instances = {}
locker = Lock()
@wraps(f)
def wrapper(*args, **kwargs):
if f not in instances:
with locker:
if f not in instances:
instances[f] = f(*args, **kwargs)
return instances[f]
return wrapper
@singleton
class President():
"""总统(单例类)"""
pass
p1=President()
p2=President()
print(p1)
print(p2)
33.深拷贝&浅拷贝
34.反射
这篇文章写的特别好:
使用场景:当需要执行对象里的某个方法,或需要调用对象中的某个变量,但是由于种种原因我们无法确定这个方法或变量是否存在,这是我们需要用一个特殊的方法或机制要访问和操作这个未知的方法或变量,这中机制就称之为反射。所谓反射,就是把字符串反射成内存对象。
四个内置函数:
hasattr
getattr 接收两个参数,第一个是类或者模块,后面的是一个字符串
delattr
hasattr
Cls和slef有啥区别:cls主要用在类方法定义,而self是实例方法
35.__new__和__init__方法的区别
看下这篇文章:https://www.jianshu.com/p/08d7956601de
Python中的__new__()方法
__new__()是在新式类中新出现的方法,它作用在构造方法建造实例之前,可以这么理解,在Python 中 存在于类里面的构造方法__init__()负责将类的实例化,而在__init__()启动之前,__new__()决定是否 要使用该__init__()方法,因为__new__()可以调用其他类的构造方法或者直接返回别的对象来作为本类 的实例。
__new__()必须要有返回值,返回实例化出来的实例,需要注意的是,可以return父类__new__()出来的实例,也可以直接将object的__new__()出来的实例返回。
__init__()有一个参数self,该self参数就是__new__()返回的实例
36.内存回收机制
写的炒鸡好的文章,看这篇大概就够了:
Python采用引用计数机制为主,标记-清除和分代收集两种机制为辅的策略。
引用计数:每个对象都保存了一个称为引用计数的整数值,来追踪到底有多少引用指向了这个对象。
分代收集:把对象分为三代,一开始,对象在创建的时候,放在一代中,如果在一次一代的垃圾检查中,改对象存活下来,就会被放到二代中,同理在一次二代的垃圾检查中,该对象存活下来,就会被放到三代中。
37.生成二维码(好玩的)
主要用到的是myqr这个库
第一个参数传的是一个网址,也就是扫二维码你想要打开哪个网页。-p后面接的是一张图片或者gif,-c表示生成的二维码是彩色的。下面是我生成的一个例子:
myqr https://www.zhihu.com -p qrcode_pic.jpg -c
- 进程与线程
一个进程中可以包括多个线程,进程是资源分配的基本单位,线程是资源调度的基本单位。
守护线程:setDaemon(True)是设置当前线程为守护线程,表示该线程是不重要的,进程退出时不需要等待这个线程执行完成。setDeamon一定要在start之前设置。设置为True, 则主线程执行完毕后会将子线程回收掉,设置为false,主进程执行结束时不会回收子线程
如果想让守护线程执行结束之后,主线程再结束,我们可以使用join方法,让主线程等待子线程执行,也就是说主线程运行结束后,会继续等待子线程运行。
今天看的代码是:
def main():
create_dir('pic')
queue = [i for i in range(1, 72)] # 构造 url 链接 页码。
threads = []
while len(queue) > 0:
for thread in threads:
if not thread.is_alive():
threads.remove(thread)
while len(threads) < 5 and len(queue) > 0: # 最大线程数设置为 5
cur_page = queue.pop(0)
url = 'http://meizitu.com/a/more_{}.html'.format(cur_page)
thread = threading.Thread(target=execute, args=(url,))
thread.setDaemon(True)
thread.start()
print('{}正在下载{}页'.format(threading.current_thread().name, cur_page))
threads.append(thread)
在python中当一个线程被执行时需要GIL锁(全局解释器锁),正是这个锁能保证同时只有一个线程在运行。多线程环境中Python虚拟机的执行过程如下:
设置GIL–>切换到一个线程去执行–>运行–>把线程设置为睡眠状态–>解锁GIL
因此,Python多线程相当于单核多线程,虽然不能利用多线程实现多核任务,但可以通过多进程实现多核任务,各个进程有独立的GIL锁,互不影响。
39.isinstance()
isinstance()会考虑继承关系,用于判断两个类型是否相同
使用方法:isinstance(object, classinfo)
其中,classinfo可以是直接或间接类名、基本类型或者由它们组成的元组