【程式語言】What's new in C++17

Structured Bindings

1
auto [a, b, c] = tuple('a', 1, 0.5);
1
2
3
4
5
map<int, int> mymap = {{1, 2}, {3, 4}};

for (const auto& [key, value] : mymap) {
// ...
}
1
2
3
for (auto [a, b] = tuple(0, 'a'); a < 5; a++) {
// ...
}

Template Argument Deduction

c++17
1
auto p = pair(2, 4.5);
c++14
1
auto p = pair<int, double>(2, 4.5);

Selection Initialization

1
2
3
if (auto a = getval(); a < 10) {
// ...
}
1
2
3
switch (auto ch = getnext(); ch) {
// ...
}

  1. https://www.fluentcpp.com/2018/06/19/3-simple-c17-features-that-will-make-your-code-simpler/
  2. https://hackernoon.com/a-tour-of-c-17-if-constexpr-3ea62f62ff65
  3. https://stackoverflow.com/questions/38060436/what-are-the-new-features-in-c17
Read more

【程式語言】Python 的奇淫技巧

列了一些我新發現的各種花招

Function Attributes (python 2.1)

PEP 232

1
2
3
4
5
6
7
8
9
def a():
a.count += 1

a.count = 0

for i in range(10):
a()

print(a.count) # 10

跟 C++ 中,在 function 裡面宣告 static 變數差不多

Keyword-Only Arguments (python 3.0)

PEP 3102

1
2
def func(a, b, *, c = None):
pass
  • func(1, 2, 3) 不行
  • func(1, 2, c = 3) 這樣才合法

Additional Unpacking Generalizations (python 3.5)

PEP 448

1
2
3
a = [1, 2, 3]
b = [*a, 4, 5]
print(b) # [1, 2, 3, 4, 5]

Merge Dicts

1
2
3
4
a = {1: 2}
b = {3: 4}
c = {**a, **b}
print(c) # {1: 2, 3: 4}

Metaclasses

Python Metaclasses

1
2
3
4
5
6
7
8
9
10
11
12
13
class A:
pass

B = type('B',
(A,),
{
'attr': 10,
'func': lambda obj: obj.attr
})

b = B()
print(b.attr) # 10
print(b.func()) # 10
正常寫法
1
2
3
4
5
6
7
8
9
10
11
class A:
pass

class B(A):
attr = 10
def func(self):
return self.attr

b = B()
print(b.attr) # 10
print(b.func()) # 10

看看就好xD

shallow vs deep copy

Shallow vs Deep Copying of Python Objects

assign

1
2
3
4
5
6
7
8
9
10
a = [[1, 2, 3], [4, 5, 6]]
b = a

b.append('hello')
b[0].append('world')

print(a)
# [[1, 2, 3, 'world'], [4, 5, 6], 'hello']
print(b)
# [[1, 2, 3, 'world'], [4, 5, 6], 'hello']

copy

1
2
3
4
5
6
7
8
9
10
11
12
import copy

a = [[1, 2, 3], [4, 5, 6]]
b = copy.copy(a)

b.append('hello')
b[0].append('world')

print(a)
# [[1, 2, 3, 'world'], [4, 5, 6]]
print(b)
# [[1, 2, 3, 'world'], [4, 5, 6], 'new object']

deepcopy

1
2
3
4
5
6
7
8
9
10
11
12
import copy

a = [[1, 2, 3], [4, 5, 6]]
b = copy.deepcopy(a)

b.append('hello')
b[0].append('world')

print(a)
# [[1, 2, 3], [4, 5, 6]]
print(b)
# [[1, 2, 3, 'world'], [4, 5, 6], 'new object']

  • copy.copy (shallow) 只複製該物件,不會複製子物件
  • copy.deepcopy (deep) 會遞迴複製所有子物件

shallow copy on list

1
2
a = [1, 2, 3]
b = list(a)
1
2
a = [1, 2, 3]
b = a[:]
1
2
a = [1, 2, 3]
b = a.copy()
1
2
3
4
import copy

a = [1, 2, 3]
b = copy.copy(a)

annotations

function annotations

1
2
3
4
5
def func(a: int, b: list) -> int:
pass

print(func.__annotations__)
# {'a': <class 'int'>, 'b': <class 'list'>, 'return': <class 'int'>}

class annotations

1
2
3
4
5
class A():
var: int

print(A.__annotations__)
# {'var': <class 'int'>}

variable annotations

1
2
3
4
5
a: int
b: int = 2

print(__annotations__)
# {'a': <class 'int'>, 'b': <class 'int'>}

intern string

1
2
s = 'hello'
s = sys.intern(s)

把字串存進快取池,相同的字串只會存一次
做字串比對會比較快且節省空間


  1. http://guilload.com/python-string-interning/
  2. http://www.laurentluce.com/posts/python-string-objects-implementation/
Read more

【指令怎麼用】SSH 的十大妙用

ssh config

~/.ssh/config
1
2
3
4
Host vps
HostName 123.45.67.89
User oalieno
Port 22000

每次都打一長串的參數很麻煩,可以先在 ~/.ssh/config 設定好
像上面這樣設定好後 ssh vps 就等同於 ssh -p 22000 oalieno@123.45.67.89

IdentityFile

~/.ssh/config
1
2
3
4
Host vps
HostName 123.45.67.89
User oalieno
IdentityFile ~/.ssh/id_rsa

IdentityFile 就是指定要用哪個 key,等同於 -i ~/.ssh/id_rsa
預設會抓 id_*.pub 中最新的 ( /usr/bin/ssh-copy-id 59 行 )

local port forwarding ( ssh tunnel )

~/.ssh/config
1
2
3
4
Host vps
HostName 123.45.67.89
User oalieno
LocalForward 5555 127.0.0.1:6666

設定好後可以直接打以下指令

1
2
3
ssh -f -N vps
# -f : run in background
# -N : not execute remote command, useful for forwarding ports

就會等同於以下指令

1
2
3
ssh -f -N -L 5555:127.0.0.1:6666 oalieno@123.45.67.89
# -f : run in background
# -N : not execute remote command, useful for forwarding ports

local:5555 -> remote:127.0.0.1:6666
執行這個指令,就會在 local 聽 5555 port 然後把流量都導到 remote 的 127.0.0.1 的 6666 port

remote port forwarding ( reverse ssh tunnel )

~/.ssh/config
1
2
3
4
Host vps
HostName 123.45.67.89
User oalieno
RemoteForward 6666 127.0.0.1:5555

設定好後可以直接打以下指令

1
2
3
ssh -f -N vps
# -f : run in background
# -N : not execute remote command, useful for forwarding ports

就會等同於以下指令

1
2
3
ssh -f -N -R 6666:127.0.0.1:5555 oalieno@123.45.67.89
# -f : run in background
# -N : not execute remote command, useful for forwarding ports

remote:6666 -> local:127.0.0.1:5555
執行這個指令之後,就會在 remote 聽 6666 port 然後把流量都導到 local 的 127.0.0.1 的 5555 port

dynamic port forwarding

~/.ssh/config
1
2
3
4
Host vps
HostName 123.45.67.89
User oalieno
DynamicForward 9999

設定好後可以直接打以下指令

1
2
3
ssh -f -N vps
# -f : run in background
# -N : not execute remote command, useful for forwarding ports

就會等同於打以下指令

1
2
3
ssh -f -N -D 9999 oalieno@123.45.67.89
# -f : run in background
# -N : not execute remote command, useful for forwarding ports

會開一個 SOCKS 代理伺服器聽在 local 的 9999 port,把流量都轉從 remote 的機器出去

情境一:存取內網資源

你在你租的 vps 伺服器上面跑了一個 mattermost 在測試
但你不想讓 mattermost 聽在 0.0.0.0 公開在網路上讓大家都可以連,有風險
所以你開在 127.0.0.1 只有 vps 本地可以連
但是你又想用你的筆電上的瀏覽器測試
這時候就可以用到 local port forwarding 把 local:8065 -> remote:127.0.0.1:8065
設定如下之後,執行 ssh -f -N vps-mattermost
就可以在本地瀏覽器上面輸入 http://localhost:8065 連到你架好的 mattermost 了

~/.ssh/config
1
2
3
4
Host vps-mattermost
HostName 123.45.67.89
User oalieno
LocalForward 8065 127.0.0.1:8065

情境二:透過跳板 ssh 到沒有 public ip 的機器

你在家裡組了一台桌機,但是這台桌機沒有 public ip,所以在外面的時候沒辦法 ssh 連到家裡的桌機
不過你剛好租了一台有 public ip 的 vps 伺服器
這時候就可以用到 remote port forwarding 把 remote:22000 -> local:127.0.0.1:22
設定如下之後,在桌機上執行 ssh -f -N vps-reverse-ssh
就可以從你的筆電先 ssh 到 vps
然後再從 vps 通過 remote port forwarding ssh 到桌機了
有 public ip 的 vps 伺服器在這裡扮演了跳板的角色

~/.ssh/config (桌機)
1
2
3
4
Host vps-reverse-ssh
HostName 123.45.67.89
User oalieno
RemoteForward 22000 127.0.0.1:22
~/.ssh/config (vps)
1
2
3
4
Host home
HostName 127.0.0.1
User oalieno
Port 22000

autossh

autossh 可以幫你自動重連

~/.ssh/config
1
2
3
4
5
6
7
Host vps
HostName 123.45.67.89
User oalieno
IdentityFile ~/.ssh/id_rsa
LocalForward 5555 127.0.0.1:6666
ServerAliveInterval 30
ServerAliveCountMax 3

設定好後可以直接打以下指令

1
2
3
4
autossh -M 0 -f -N vps
# -M 0 : autossh echo port, recommend disable it by setting it to 0
# -f : run in background
# -N : not execute remote command, useful for forwarding ports

就會等同於打以下指令

1
2
3
4
autossh -M 0 -f -N -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" -L 5555:localhost:6666 oalieno@123.45.67.89
# -M 0 : autossh echo port, recommend disable it by setting it to 0
# -f : run in background
# -N : not execute remote command, useful for forwarding ports

escape sequence

有時候連線斷掉後,畫面就會卡在那裡
這時候就可以直接在鍵盤上打 ~. 這個 escape sequences 就可以直接跳出來啦,感覺像是在逃脫 vim 呢xD
下面還有更多的神秘金手指可以打

1
2
3
4
5
6
7
8
9
10
11
12
Supported escape sequences:
~. - terminate connection (and any multiplexed sessions)
~B - send a BREAK to the remote system
~C - open a command line
~R - request rekey
~V/v - decrease/increase verbosity (LogLevel)
~^Z - suspend ssh
~# - list forwarded connections
~& - background ssh (when waiting for connections to terminate)
~? - this message
~~ - send the escape character by typing it twice
(Note that escapes are only recognized immediately after newline.)

  1. https://linux.die.net/man/5/ssh_config
  2. https://nerderati.com/2011/03/17/simplify-your-life-with-an-ssh-config-file/
  3. https://www.everythingcli.org/ssh-tunnelling-for-fun-and-profit-local-vs-remote/
  4. https://askubuntu.com/questions/29942/how-can-i-break-out-of-ssh-when-it-locks
  5. https://johnliu55.tw/ssh-tunnel.html
Read more