Skip to content

Commit

Permalink
personal info
Browse files Browse the repository at this point in the history
  • Loading branch information
gameofby committed Jan 13, 2024
1 parent 34d8aab commit 4f2e166
Show file tree
Hide file tree
Showing 23 changed files with 902 additions and 2,041 deletions.
402 changes: 1 addition & 401 deletions README.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion app/tag-data.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"markdown":1,"code":1,"features":1,"next-js":6,"math":1,"ols":1,"github":1,"guide":5,"tailwind":3,"holiday":1,"canada":1,"images":1,"feature":2,"writings":1,"book":1,"reflection":1,"multi-author":1}
{"multi-author":1,"next-js":1,"feature":1}
20 changes: 7 additions & 13 deletions data/authors/default.mdx
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
---
name: Tails Azimuth
avatar: /static/images/avatar.png
occupation: Professor of Atmospheric Science
company: Stanford University
email: [email protected]
twitter: https://twitter.com/Twitter
linkedin: https://www.linkedin.com
github: https://github.com
name: Brian
avatar: /static/images/avatar_black.jpg
occupation: Software Engineer
email: [email protected]
twitter: https://twitter.com/blackorangebros
github: https://github.com/timelxy
---

Tails Azimuth is a professor of atmospheric sciences at the Stanford AI Lab. His research interests includes complexity modelling of tailwinds, headwinds and crosswinds.

He leads the clean energy group which develops 3D air pollution-climate models, writes differential equation solvers, and manufactures titanium plated air ballons. In his free time he bakes raspberry pi.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed neque elit, tristique placerat feugiat ac, facilisis vitae arcu. Proin eget egestas augue. Praesent ut sem nec arcu pellentesque aliquet. Duis dapibus diam vel metus tempus vulputate.
I'm Brian, welcome to my blog.
31 changes: 31 additions & 0 deletions data/blog/2 ways to parse http json body in golang.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@

# Samples
---

## 1. json.NewDecoder

```go
func handleUser(w http.ResponseWriter, r *http.Request) {
var user User
err := json.NewDecoder(r.Body).Decode(&user)
}
```

## 2. json.Unmarshal
```go
func handleUser(w http.ResponseWriter, r *http.Request) {
var user User
p, _ := io.ReadAll(r.Body)
err := json.Unmarshal(p, &user)
}
```

# Differences
---

- `json.NewDecoder()`将请求body读取为JSON token流,并用它来填充目标结构体。这种方式允许更高效地解析大型JSON负载,因为解码器只需要读取所需的JSON,以填充目标结构体。
- `json.Unmarshal()`将整个请求body读取为一个字节切片,并一次性解析JSON以填充目标结构体。这可能对于大型负载不太有效,因为它需要一次性将整个负载加载到内存中

在大多数情况下,这两种方法之间的性能差异通常是可以忽略不计的,因为大多数http请求body不会太大。使用哪种方法通常取决于个人喜好或应用程序的特定要求

另外 `json.NewDecoder()`在解析完后,剩下的body会保留下来,不会全部读完
99 changes: 99 additions & 0 deletions data/blog/Deque in Python.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
[官方文档 3.12.4](https://docs.python.org/3/library/collections.html#collections.deque)

这里主要总结下deque这个数据结构的特点和使用场景。 如果是关注具体用法,可以直接看官方文档里的示例,很清晰。

# deque的特点
底层实现上使用了双向链表(doubly linked list)

线程安全

deque是栈和队列的结合,又可以叫做“双端队列”。顾名思义,两端都可以append, pop

list数据结构也提供了类似deque的能力,但是在左端进行append, pop操作时,时间复杂度是O(n),因为要移动每个位置的底层数据。 相比之下,deque左端的pop, append操作,时间复杂度是近似O(1)

但是,list任意位置的index读取是O(1),而deque除了两端,中间位置的读取需要O(n)

list和deque的类似操作对比如下:

```python
from collections import deque

l = [1, 2, 3, 4]
d = deque(l)

# 右端pop
l.pop()
d.pop()

# 右端append
l.append()
d.append()

# 左端pop
l.pop(0)
d.popleft()

# 左端append
v = 0
l.insert(0, v)
d.appendleft(v)

```

# deque很有意思的几个使用场景

1. 类Unix的tail命令实现

因为deque支持固定长度maxlen,如果初始化的时候设定了maxlen,并且deque的实际长度已经等于maxlen,进一步在两端append,会把相反方向的头部“挤出”deque

利用这个特点,可以实现tail文件尾部固定长度的工程。实现如下:

```python
def tail(filename, n=10):
"""Return the last n lines of a file"""
with open(filename) as f:
return deque(f, n)
```


2. 实现[moving average](https://en.wikipedia.org/wiki/Moving_average)。和1类似,也是利用了maxlen

```python
def moving_average(iterable, n=3):
# moving_average([40, 30, 50, 46, 39, 44]) --> 40.0 42.0 45.0 43.0
it = iter(iterable) # 如果iterable比较大,避免一次性加载到内存中,转为迭代器,一个一个处理
# 取it的前n-1个数字
d = deque(itertools.islice(it, n-1))
d.appendleft(0) # 边界兼容处理,让下面第一次循环执行完后,d中是前3个数字
s = sum(d)
for elem in it:
s += elem - d.popleft()
d.append(elem)
yield s / n
```

3. round-robin scheduler
round-robin是负载均衡中常用的算法。通俗点就是轮着来。音乐循环播放。主要是利用deque的rotate方法

```python
def roundrobin(*iterables):
"""roundrobin('ABC', 'D', 'EF') --> A D E B F C"""
iterators = deque(map(iter, iterables))
while iterators:
try:
while True:
yield next(iterators[0]) #输出左端元素的第一个子元素
iterators.rotate(-1) #把右端元素挪到左端,进行一个环形循环
except StopIteration: # 如果左端头部元素已经没有next了,catch Exception
# Remove an exhausted iterator.
iterators.popleft()
```

4. 对deque进行slice或者指定位置删除
```python
def delete_nth(d, n):
"""类似list del d[n] 的deque实现"""
d.rotate(-n)
d.popleft()
d.rotate(n)
```
131 changes: 131 additions & 0 deletions data/blog/Python中的heapq与PriorityQueue用哪个?.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# Similarities and Differences


1. heapq是堆算法的python库函数;PriorityQueue是优先队列数据结构对应的类
2. queue.PriorityQueue基于heapq实现,加了thread-safety。性能上会慢
3. queue.PriorityQueue只有queue的基本操作,没有heapq灵活

# heapq
[Heap queue algorithm](https://stackoverflow.com/questions/36991716/whats-the-difference-between-heapq-and-priorityqueue-in-python)

`heap[k] <= heap[2*k+1]` and `heap[k] <= heap[2*k+2]`

和textbook上的堆算法有两点不同:
1. index从0开始
2. 小顶堆。textbook更多是大顶,便于原地排序

这两点使得heap可以基于python的list结构实现

```python
# 初始化空heap
heap = []

# 初始化heap, in-place
heap = [3, 4, 2, 1]
heapq.heapify(heap)

# push、pop
heapq.heappush(heap, 0)
heapq.heapop(heap)

# get smallest element
heap[0]

# sort by heap
def heapsort(iterable):
h = []
for value in iterable:
heappush(h, value)
return [heappop(h) for i in range(len(h))]

heapsort([1, 3, 5, 7, 9, 2, 4, 6, 8, 0])


```




# queue.PriorityQueue

[普通实现source code](https://github.com/python/cpython/blob/5113ed7a2b92e8beabebe5fe2f6e856c52fbe1a0/Lib/queue.py#L223)
![](/images/priorityqueue1.png)
[多线程安全实现source code](https://github.com/python/cpython/blob/5113ed7a2b92e8beabebe5fe2f6e856c52fbe1a0/Lib/asyncio/queues.py#L218)
![](/images/priorityqueue2.png)

基本使用
```python
from queue import PriorityQueue

# 创建一个优先级队列对象
queue = PriorityQueue()

# 插入元素到队列中
queue.put((2, 'B'))
queue.put((1, 'A'))
queue.put((3, 'C'))

# 从队列中获取具有最高优先级的元素
item = queue.get()
print(item) # 输出:(1, 'A')

# 判断队列是否为空
print(queue.empty()) # 输出:False

# 遍历队列中的元素
while not queue.empty():
item = queue.get()
print(item)

# 输出:
# (2, 'B')
# (3, 'C')
```


# 高阶应用


按priority排列,可以将item和priority作为entry输入
>Entries are typically tuples of the form: (priority number, data).
```python
h = []
heappush(h, (5, 'write code'))
heappush(h, (7, 'release product'))
heappush(h, (1, 'write spec'))
heappush(h, (3, 'create tests'))
heappop(h)

# PriorityQueue类似

```



item之间比大小是按照sorted实现的([参考](https://stackoverflow.com/questions/57487170/is-it-possible-to-pass-a-comparator-to-a-priorityqueue-in-python)),因此插入元素要可对比。当不可对比时,需要用类包装下原始数据结构,类中实现包含__lt__, \_\_eq\_\_方法

```python
class ListNode:
def __init__(self, val=0, next=None):
self.val = val

# 对不可比的ListNode的类进行包装,提供__lt__方法。 这样SortedLink就可以作为可比元素push到heapq中
class SortedLink(object):
def __init__(self, p):
self.p = p

def __lt__(self, new):
return self.p.val < new.p.val

lists = [
ListNode(3),
ListNode(1),
ListNode(2)
]

q = []
for item in lists:
heapq.heappush(q, SortedLink(item))

```
38 changes: 0 additions & 38 deletions data/blog/code-sample.mdx

This file was deleted.

Loading

0 comments on commit 4f2e166

Please sign in to comment.