• 装饰器:

定义:本质是函数,(装饰其他函数)就是为其他函数添加附加功能

原则:1.不能修改被装饰的函数的源代码

   2.不能修改被装饰的函数的调用方式

实现装饰器知识储备:

1.函数即“变量”

 import time
def timmer(func):
def warpper(*args,**kwargs):
start_time=time.time()
func()
stop_time=time.time()
print('the func run time is %s'%(stop_time-start_time))
return warpper @timmer
def test1():
time.sleep(3)
print("in the test1") test1()

decorator_

 # def foo():
# print("in the foo")
# bar()
# foo() # def foo():
# print("in the foo")
# bar()
# def bar():
# print("in the bar")
# foo() def foo():
print("in the foo")
bar()
foo()
def bar():
print("in the bar")

decorator1

x=1 x相当于门牌号,python解释器中有引用计数,y=x,相当于1所在的房间有两个门牌号,当没有门牌号时,python就会把房间清空掉。函数的回收机制和变量一样。

函数和变量都是先定义再调用,在调用之前定义好了就OK

2.高阶函数

满足以下其中一个就是高阶函数

①:把一个函数名当做实参传给另外一个函数(在不修改被装饰函数源代码的情况下为其添加功能)

 import time
def bar():
time.sleep(3)
print("in the bar")
def test1(func):
start_time=time.time()
func() # run bar
stop_time = time.time()
print("the func time is %s"%(stop_time-start_time)) test1(bar)

test1

②:返回值中包含函数名(不修改函数的调用方式)

 import time
def bar():
time.sleep(3)
print("in the bar")
def test2(func):
print(func)
return func #print(test2(bar))
# t=test2(bar)
# t() #run bar
bar=test2(bar)
bar()

test2

3.嵌套函数

 def foo():
print('in the foo')
def bar(): #相当于局部变量,不能在外边调用
print('in the bar') bar()
foo()

decorator3

高阶函数+嵌套函数 =》装饰器

局部作用域和全局作用域的访问顺序(从里往外找)

 x=0
def grandpa():
# x=1
def dad():
x=2
def son():
x=3
print(x)
son()
dad()
grandpa()

装饰器1

 import time
# def deco(func):
# start_time=time.time()
# return func #返回函数的内存地址
# stop_time=time.time()
# print('the func run time is %s' % (stop_time - start_time))
def timer(func): #timer(test1) func=test1()
def deco(*args,**kwargs): #加上非固定参数*args,**kwargs才通用
start_time=time.time()
func(*args,**kwargs) #run test1()
stop_time=time.time()
print('the func run time is %s' % (stop_time - start_time))
return deco # def timer():
# def deco():
# pass #仿照这个格式
@timer #test1=timer(test1) =deco
def test1():
time.sleep(1)
print('in the test1')
@timer
def test2(naem,age):
time.sleep(1)
print('in the test2') #test1=timer(test1)
test1() #-->run deco
test2("jyh",24)

decorator4

装饰器2

 import time
user,passwd='alex','abc123'
def auth(auth_type):
print("auth func:",auth_type)
def outer_wrapper(func):
def wrapper(*args, **kwargs):
print("warpper func args:",*args, **kwargs)
if auth_type=="local":
username = input('Username:').strip()
password = input('Password:').strip()
if user == username and passwd == password:
print("\033[32;1mUser has passed authentication\033[0m")
res = func(*args, **kwargs) # from home
print("---after authentication")
return res
else:
exit('"\033[32;1mInwalid username or password\033[0m"')
elif auth_type=="ldap":
print("ldap,搞毛线!")
return wrapper
return outer_wrapper def index():
print("welcom to index page")
@auth(auth_type="local") #home=wrapper()
def home():
print("welcom to home page")
return "from home"
@auth(auth_type="ldap")
def bbs():
print("welcom to bbs page")
index()
print(home()) #wrapper
bbs()

decorator5

断点

 import time
def timer(func): #timer(test1) func=test1()
def deco():
start_time=time.time()
func() #run test1()
stop_time=time.time()
print('the func run time is %s' % (stop_time - start_time))
return deco
@timer #test1=timer(test1)
def test1():
time.sleep(3)
print('in the test1')
test1() #-->run deco

decorator5

  • 列表生成式

  • 生成器

通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。

所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。

要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:

生成器:只有在调用时才会生成相应的数据。

只记录当前位置

只有一个__next__()方法。 "next()" in python2.x

斐波拉契

 def fib(max): #
n, a, b = 0, 0, 1
while n < max:
#print(b)
yield b #生成器
a, b = b, a + b
n = n + 1
return 'done' #处理异常,返回值
f=fib(10)
print(f.__next__())
print(f.__next__())
print(f.__next__())
print(f.__next__())
# 注意,赋值语句:
# a, b = b, a + b
# 相当于:
# t = (b, a + b) # t是一个tuple
# a = t[0]
# b = t[1]
# 但不必显式写出临时变量t就可以赋值
# 仔细观察,可以看出,fib函数实际上是定义了斐波拉契数列的推算规则,可以从第一个元素开始,推算出后续任意的元素,这种逻辑其实非常类似generator。
# 也就是说,上面的函数和generator仅一步之遥。要把fib函数变成generator,只需要把print(b)改为yield b就可以了: print("===start loop===")
for i in f:
print(i)

fibna_

异常处理:

 def fib(max):
n, a, b = 0, 0, 1
while n < max:
#print(b)
yield b
a, b = b, a + b
n = n + 1
return '---done---' #处理异常时返回的值
f = fib(6)
while True:
try:
x = next(f)
print('f:', x)
except StopIteration as e:
print('Generator return value:', e.value)
break

fibna_2

捕获StopIteration错误,返回值包含在StopIterationvalue中。

还可通过yield实现在单线程的情况下实现并发运算的效果。

 import time
def consumer(name): #消费者
print("%s 准备吃包子啦!" %name)
while True:
baozi = yield print("包子[%s]来了,被[%s]吃了!" %(baozi,name)) # c=consumer("jyh")
# c.__next__()
# b1="韭菜馅"
# c.send(b1) #与next区别:不仅调用,还传值
# c.__next__() def producer(name): #生产者
c = consumer('A')
c2 = consumer('B')
c.__next__()
c2.__next__()
print("老子开始准备做包子啦!")
for i in range(10):
time.sleep(1)
print("做了1个包子,分两半!")
c.send(i)
c2.send(i) producer("XXX")
#协程比线程更小的单位
#异步io, Nginx 雏形 。

bingxing

  • 迭代器

我们已经知道,可以直接作用于for循环的数据类型有以下几种:

一类是集合数据类型,如listtupledictsetstr等;

一类是generator,包括生成器和带yield的generator function。

这些可以直接作用于for循环的对象统称为可迭代对象:Iterable

可以使用isinstance()判断一个对象是否是Iterable对象:

而生成器不但可以作用于for循环,还可以被__next__()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。

*可以被__next__()函数调用并不断返回下一个值的对象称为迭代器:Iterator

生成器都是Iterator对象,但listdictstr虽然是Iterable,却不是Iterator

listdictstrIterable变成Iterator可以使用iter()函数:

你可能会问,为什么listdictstr等数据类型不是Iterator

这是因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。

Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。

  • 小结

凡是可作用于for循环的对象都是Iterable类型;

凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;

集合数据类型如listdictstr等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。

Python的for循环本质上就是通过不断调用next()函数实现的,例如:

实际上完全等价于:

for line in f 也是迭代器的方式去取

  • 内置参数

内置参数详解 https://docs.python.org/3/library/functions.html?highlight=built#ascii

#hash():

 print(all([1,-5,3])) #True
print(any([0,-5,3])) #True
print(any([])) #False
#ascii()没什么用
print(bin(255)) #0b11111111 把数字十进制转二进制
print(bool(0)) #返回布尔值 a=bytes("abcd",encoding="utf-8")
print(a.capitalize(),a) #字符串不可以修改,字节更不可以修改,只能生成新的 #改二进制
b=bytearray("abcd",encoding="utf-8")
print(b[1])
b[1]=50 #ascii码中的50--->2
print(b) #可否调用
def func():
pass
print(callable([])) #False
print(callable(func)) #True print(chr(98)) #ascii码中的98--->b
print(ord("b")) # b--->ascii码中的98 #classmethod #类方法,以后讲 #compile() #基本用不到,底层,把代码进行编译的过程。
code= "for i in range(10):print(i)"
#c=compile(code,'',"exec")
exec(code)
#complex() 复数...
#delattr() 有用,面向对象的时候再讲
print(dict(a=2))#生成字典 a={}
print(dir(a))#打印字典a的所有"方法" print(divmod(5,3)) #--->(1,2) 1是商,2是余数 # enumerate()
# eval()
# exec #匿名函数
def sayhi(n):
print(n)
sayhi(3)
# (lambda n:print(n))(5)
calc=lambda n:print(n) #只能写三元运算
calc(5)
print("-----") #res=filter(lambda n:n>5,range(10)) #筛选
#res=map(lambda n:n*2,range(10))
# for i in res:
# print(i)
import functools
res=functools.reduce(lambda x,y:x+y,range(1,10))
print(res) # # float
# format()
#a=frozenset([1,4,333,212,33,33,12,4]) #不可变集合,列表
#getattr #面向对象时讲
print(globals()) #返回的是当前整个程序所有变量的key-value格式
print(hash("jyh")) #将对象转化为固定的值,对于算法,很有用,见上图。
#help()
print(hex(23))#把一个数字转化为16进制
# id()、# input()、# int()、# isinstance()、# issubclass()、#iter()、#len()
def test():
local_var=333
print(locals())
print(globals())
test()
print(globals()) #只打印全局变量
print(globals().get("local_var"))
#max(),min(),next(),object python中世间万物皆为对象,对象有属性,有功能,通过.调用
print(oct(8) ) #转8进制
# open(),ord(),print(),range()
print(pow(2,8)) # 2的8次方
# property #以后讲
#repr() #没什么用
#reversed()
print(round(1.3342,3))#保留小数点后"2"(或其他)位
#setattr 重要,后面讲
#slice 忘记吧 a={6:2,8:0,1:4,-5:6,99:11,4:22}
print(sorted(a.items())) #默认按key排序 [(-5, 6), (1, 4), (4, 22), (6, 2), (8, 0), (99, 11)]
print(sorted(a.items(),key=lambda x:x[1])) #[(8, 0), (6, 2), (1, 4), (-5, 6), (99, 11), (4, 22)]
#@staticmethod 后面讲
#sum() 求和,super() 后面讲
#vars()#返回对象的所有属性名,用不到 a=[1,2,3,4,5,6]
b=["a","b","c","d"]
for i in zip(a,b): #按个数最小的来
print(i) __import__("decorator_")#与import decorator_一样,很有用

neizhi_

  • Json & pickle 数据序列化

用于序列化的两个模块

  • json,用于字符串 和 python数据类型间进行转换
  • pickle,用于python特有的类型 和 python的数据类型间进行转换

Json模块提供了四个功能:dumps、dump、loads、load

pickle模块提供了四个功能:dumps、dump、loads、load

 import json #json用于与java,c等不同语言(简单类型--列表,字典,字符串。函数不行)数据交互,取代xml
#序列化:把内存的数据对象变成字符串存到硬盘上 def sayhi(name):
print("hello,",name)
info={
"name":"jyh",
"age":24,
"func":sayhi
} f=open("test.text","w")
#print(json.dumps(info))
f.write(json.dumps(info)) #用dumps序列化
f.close()

json_xuliehua

 import json
info={
"name":"jyh",
"age":24
} f=open("test.text","r")
data=json.loads(f.read()) #用load反序列化
print(data["age"])
f.close()

json_fanxuliehua

 import pickle

 def sayhi(name):
print("hello,",name)
info={
"name":"jyh",
"age":24,
"func":sayhi
} f=open("test.text","wb")
#print(json.dumps(info))
f.write(pickle.dumps(info))
f.close()

pickle_xuliehua

 import pickle

 def sayhi(name):

     print("hello2,",name)

 info={
"name":"jyh",
"age":24,
"func":sayhi
} f=open("test.text","rb")
data=pickle.loads(f.read())
print(data["func"]("jyh"))
f.close()

pickle_fanxuliehua

 import json

 def sayhi(name):
print("hello,",name)
info={
"name":"jyh",
"age":24,
#"func":sayhi
} f=open("test.text","w")
f.write(json.dumps(info))
info["age"]=21
f.write(json.dumps(info))
f.close()

json_xuliehua2

 import json
info={
"name":"jyh",
"age":24
} f=open("test.text","r")
data=json.load(f.read())
print(data)
f.close() #可以dump多次,load出错。所以最好dump一次,load一次

json_fanxuliehua2

 import pickle

 def sayhi(name):
print("hello,",name)
info={
"name":"jyh",
"age":24,
"func":sayhi
} f=open("test.text","wb")
pickle.dump(info,f) #与f.write(pickle.dumps(info))一样
f.close()

pickle_xuliehua2

 import pickle

 def sayhi(name):

     print("hello2,",name)

 info={
"name":"jyh",
"age":24,
"func":sayhi
} f=open("test.text","rb")
data=pickle.load(f) #与data=pickle.loads(f.read())一样
print(data["func"]("jyh"))
f.close()

pickle_fanxuliehua2

  • 软件目录结构规范

"设计项目目录结构",就和"代码编码风格"一样,属于个人风格问题。对于这种风格上的规范,一直都存在两种态度:

  1. 一类同学认为,这种个人风格问题"无关紧要"。理由是能让程序work就好,风格问题根本不是问题。
  2. 另一类同学认为,规范化能更好的控制程序结构,让程序具有更高的可读性。

我是比较偏向于后者的,因为我是前一类同学思想行为下的直接受害者。我曾经维护过一个非常不好读的项目,其实现的逻辑并不复杂,但是却耗费了我非常长的时间去理解它想表达的意思。从此我个人对于提高项目可读性、可维护性的要求就很高了。"项目目录结构"其实也是属于"可读性和可维护性"的范畴,我们设计一个层次清晰的目录结构,就是为了达到以下两点:

  1. 可读性高: 不熟悉这个项目的代码的人,一眼就能看懂目录结构,知道程序启动脚本是哪个,测试目录在哪儿,配置文件在哪儿等等。从而非常快速的了解这个项目。
  2. 可维护性高: 定义好组织规则后,维护者就能很明确地知道,新增的哪个文件和代码应该放在什么目录之下。这个好处是,随着时间的推移,代码/配置的规模增加,项目结构不会混乱,仍然能够组织良好。

所以,我认为,保持一个层次清晰的目录结构是有必要的。更何况组织一个良好的工程目录,其实是一件很简单的事儿。

目录组织方式

关于如何组织一个较好的Python工程目录结构,已经有一些得到了共识的目录结构。在Stackoverflow的这个问题上,能看到大家对Python目录结构的讨论。

这里面说的已经很好了,我也不打算重新造轮子列举各种不同的方式,这里面我说一下我的理解和体会。

假设你的项目名为foo, 我比较建议的最方便快捷目录结构这样就足够了:

Foo/
|-- bin/
| |-- foo
|
|-- foo/
| |-- tests/
| | |-- __init__.py
| | |-- test_main.py
| |
| |-- __init__.py
| |-- main.py
|
|-- docs/
| |-- conf.py
| |-- abc.rst
|
|-- setup.py
|-- requirements.txt
|-- README
#还少一个配置文件目录(conf目录) 。

简要解释一下:

  1. bin/: 存放项目的一些可执行文件,当然你可以起名script/之类的也行。
  2. foo/: 存放项目的所有源代码。(1) 源代码中的所有模块、包都应该放在此目录。不要置于顶层目录。(2) 其子目录tests/存放单元测试代码; (3) 程序的入口最好命名为main.py
  3. docs/: 存放一些文档。
  4. setup.py: 安装、部署、打包的脚本。
  5. requirements.txt: 存放软件依赖的外部Python包列表。
  6. README: 项目说明文件。

除此之外,有一些方案给出了更加多的内容。比如LICENSE.txt,ChangeLog.txt文件等,我没有列在这里,因为这些东西主要是项目开源的时候需要用到。如果你想写一个开源软件,目录该如何组织,可以参考这篇文章

下面,再简单讲一下我对这些目录的理解和个人要求吧。

关于README的内容

这个我觉得是每个项目都应该有的一个文件,目的是能简要描述该项目的信息,让读者快速了解这个项目。

它需要说明以下几个事项:

  1. 软件定位,软件的基本功能。
  2. 运行代码的方法: 安装环境、启动命令等。
  3. 简要的使用说明。
  4. 代码目录结构说明,更详细点可以说明软件的基本原理。
  5. 常见问题说明。

我觉得有以上几点是比较好的一个README。在软件开发初期,由于开发过程中以上内容可能不明确或者发生变化,并不是一定要在一开始就将所有信息都补全。但是在项目完结的时候,是需要撰写这样的一个文档的。

可以参考Redis源码中Readme的写法,这里面简洁但是清晰的描述了Redis功能和源码结构。

关于requirements.txt和setup.py

setup.py

一般来说,用setup.py来管理代码的打包、安装、部署问题。业界标准的写法是用Python流行的打包工具setuptools来管理这些事情。这种方式普遍应用于开源项目中。不过这里的核心思想不是用标准化的工具来解决这些问题,而是说,一个项目一定要有一个安装部署工具,能快速便捷的在一台新机器上将环境装好、代码部署好和将程序运行起来。

这个我是踩过坑的。

我刚开始接触Python写项目的时候,安装环境、部署代码、运行程序这个过程全是手动完成,遇到过以下问题:

  1. 安装环境时经常忘了最近又添加了一个新的Python包,结果一到线上运行,程序就出错了。
  2. Python包的版本依赖问题,有时候我们程序中使用的是一个版本的Python包,但是官方的已经是最新的包了,通过手动安装就可能装错了。
  3. 如果依赖的包很多的话,一个一个安装这些依赖是很费时的事情。
  4. 新同学开始写项目的时候,将程序跑起来非常麻烦,因为可能经常忘了要怎么安装各种依赖。

setup.py可以将这些事情自动化起来,提高效率、减少出错的概率。"复杂的东西自动化,能自动化的东西一定要自动化。"是一个非常好的习惯。

setuptools的文档比较庞大,刚接触的话,可能不太好找到切入点。学习技术的方式就是看他人是怎么用的,可以参考一下Python的一个Web框架,flask是如何写的: setup.py

当然,简单点自己写个安装脚本(deploy.sh)替代setup.py也未尝不可。

requirements.txt

这个文件存在的目的是:

  1. 方便开发者维护软件的包依赖。将开发过程中新增的包添加进这个列表中,避免在setup.py安装依赖时漏掉软件包。
  2. 方便读者明确项目使用了哪些Python包。

这个文件的格式是每一行包含一个包依赖的说明,通常是flask>=0.10这种格式,要求是这个格式能被pip识别,这样就可以简单的通过 pip install -r requirements.txt来把所有Python包依赖都装好了。具体格式说明: 点这里

关于配置文件的使用方法

注意,在上面的目录结构中,没有将conf.py放在源码目录下,而是放在docs/目录下。

很多项目对配置文件的使用做法是:

  1. 配置文件写在一个或多个python文件中,比如此处的conf.py。
  2. 项目中哪个模块用到这个配置文件就直接通过import conf这种形式来在代码中使用配置。

这种做法我不太赞同:

  1. 这让单元测试变得困难(因为模块内部依赖了外部配置)
  2. 另一方面配置文件作为用户控制程序的接口,应当可以由用户自由指定该文件的路径。
  3. 程序组件可复用性太差,因为这种贯穿所有模块的代码硬编码方式,使得大部分模块都依赖conf.py这个文件。

所以,我认为配置的使用,更好的方式是,

  1. 模块的配置都是可以灵活配置的,不受外部配置文件的影响。
  2. 程序的配置也是可以灵活控制的。

能够佐证这个思想的是,用过nginx和mysql的同学都知道,nginx、mysql这些程序都可以自由的指定用户配置。

所以,不应当在代码中直接import conf来使用配置文件。上面目录结构中的conf.py,是给出的一个配置样例,不是在写死在程序中直接引用的配置文件。可以通过给main.py启动参数指定配置路径的方式来让程序读取配置内容。当然,这里的conf.py你可以换个类似的名字,比如settings.py。或者你也可以使用其他格式的内容来编写配置文件,比如settings.yaml之类的。

atm.py

 #环境变量不能写死,只能写相对路径。我们要把这个程序的绝对路径获取到,动态的加到系统的环境变量里。
# print(__file__) #当前程序的相对路径
import os
# print(os.path.abspath(__file__)) #当前程序的绝对路径
print(os.path.dirname(os.path.abspath(__file__))) #dirname返回目录名不要文件名
print(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
import sys
sys.path.append(BASE_DIR) #添加环境变量
from conf import settings
from core import main main.login()

atm.py

main.py

 def login():
print("Welcom to my Atm")

main.py

  • 作业需求:

模拟实现一个ATM + 购物商城程序

  1. 额度 15000或自定义
  2. 实现购物商城,买东西加入 购物车,调用信用卡接口结账
  3. 可以提现,手续费5%
  4. 每月22号出账单,每月10号为还款日,过期未还,按欠款总额 万分之5 每日计息
  5. 支持多账户登录
  6. 支持账户间转账
  7. 记录每月日常消费流水(账单)
  8. 提供还款接口
  9. ATM记录操作日志
  10. 提供管理接口,包括添加账户、用户额度,冻结账户等。。。
  11. 用户认证用装饰器

示例代码https://github.com/triaquae/py3_training/tree/master/atm 

简易流程图:https://www.processon.com/view/link/589eb841e4b0999184934329

python学习笔记_week4的更多相关文章

  1. python学习笔记整理——字典

    python学习笔记整理 数据结构--字典 无序的 {键:值} 对集合 用于查询的方法 len(d) Return the number of items in the dictionary d. 返 ...

  2. VS2013中Python学习笔记[Django Web的第一个网页]

    前言 前面我简单介绍了Python的Hello World.看到有人问我搞搞Python的Web,一时兴起,就来试试看. 第一篇 VS2013中Python学习笔记[环境搭建] 简单介绍Python环 ...

  3. python学习笔记之module && package

    个人总结: import module,module就是文件名,导入那个python文件 import package,package就是一个文件夹,导入的文件夹下有一个__init__.py的文件, ...

  4. python学习笔记(六)文件夹遍历,异常处理

    python学习笔记(六) 文件夹遍历 1.递归遍历 import os allfile = [] def dirList(path): filelist = os.listdir(path) for ...

  5. python学习笔记--Django入门四 管理站点--二

    接上一节  python学习笔记--Django入门四 管理站点 设置字段可选 编辑Book模块在email字段上加上blank=True,指定email字段为可选,代码如下: class Autho ...

  6. python学习笔记--Django入门0 安装dangjo

    经过这几天的折腾,经历了Django的各种报错,翻译的内容虽然不错,但是与实际的版本有差别,会出现各种奇葩的错误.现在终于找到了解决方法:查看英文原版内容:http://djangobook.com/ ...

  7. python学习笔记(一)元组,序列,字典

    python学习笔记(一)元组,序列,字典

  8. Pythoner | 你像从前一样的Python学习笔记

    Pythoner | 你像从前一样的Python学习笔记 Pythoner

  9. OpenCV之Python学习笔记

    OpenCV之Python学习笔记 直都在用Python+OpenCV做一些算法的原型.本来想留下发布一些文章的,可是整理一下就有点无奈了,都是写零散不成系统的小片段.现在看 到一本国外的新书< ...

随机推荐

  1. Python单元测试框架之pytest 1 ---如何执行测试用例

    From: https://www.cnblogs.com/fnng/p/4765112.html 介绍   pytest是一个成熟的全功能的Python测试工具,可以帮助你写出更好的程序. 适合从简 ...

  2. Foxmail Gmail Outlook

    三个邮件客户端都比较好,但是作为用户精力是非常有限地,必须优中选优. 我选outlook,非常值得拥有. 理由如下: (1)和office完美契合 (2)和生产环境完美契合 (3)免费 (4)良好地任 ...

  3. 《Java并发编程实战》笔记-synchronized和ReentrantLock

    在一些内置锁无法满足需求的情况下,ReentrantLock可以作为一种高级工具.当震要一些高级功能时才应该使用ReentrantLock,这些功能包括:可定时的.可轮询的与可中断的锁获取操作,公平队 ...

  4. 学习笔记之Java

    Java (programming language) - Wikipedia https://en.wikipedia.org/wiki/Java_(programming_language) Ja ...

  5. docker下centos安装ping命令

    https://blog.csdn.net/king_gun/article/details/78423115 [问题] 从docker hub上拉取到则镜像centos:6.7在执行ping命令是报 ...

  6. [UE4]关卡蓝图

  7. curl 与wget的区别

    CURL与wget的区别 当想要直接通过linux 命令行下载文件,马上就能想到两个工具:wget 和 CURL.它们有很多一样的特征,可以很轻易的完成一些相同的任务,虽然它们有一些相似的特征,但它们 ...

  8. Find the peace with yourself

    The purpose of being mature is to find the real calm and peace with yourself. Or you can say the tur ...

  9. css样式,高斯模糊

    .blur-container.blur-3 { --bg: url("background.jpg"); background-image: var(--bg); } .blur ...

  10. KafkaAPI实战

    新旧API使用 Flume和Kafka集成: Kafka有两套API: 过时的API 和新API 准备工作 <dependencies> <dependency> <gr ...