集团公司开封一日游
集团公司今天带着郑州上海的管理层到开封游玩了一次,听说这样的机会很少,今天一分钱没花,老板还每人发了150元,最后还得了一箱猕猴桃,虽然这箱猕猴桃差点没得到,但总体感觉是相当好的。






集团公司今天带着郑州上海的管理层到开封游玩了一次,听说这样的机会很少,今天一分钱没花,老板还每人发了150元,最后还得了一箱猕猴桃,虽然这箱猕猴桃差点没得到,但总体感觉是相当好的。






1 | #!/bin/bash |
网上的其它版本, nmcli con show –active 这一句是不一样的。 nmcli con status这个命令在这个版本下是无法显示的。
更新:
下面的操作已经不行了,这个项目被废弃了,使用其它翻墙吧。
项目地址:https://github.com/jimmyxu/chnroutes
利用来自APNIC的数据生成路由命令脚本,让VPN客户端在连接时自动执行。通过这些路由脚本,可以让用户在使用VPN作为默认网关时,不使用VPN访问中国国内IP,从而减轻VPN负担,并提高访问国内网站的速度。
这个和自动翻墙还是有区别的,只能根据IP提高国内网站访问速度,我设置成功后,发现好多国内网站访问仍然慢。
PPTP
Linux
执行python chnroutes.py -p linux,这将生成ip-pre-up和ip-down两个文件;
将ip-pre-up移入/etc/ppp/,ip-down移入/etc/ppp/ip-down.d/;
重新连接VPN,观察测试。
如果发现没有改变,那很可能是权限的问题了,我也遇到了,添加一下权限
1 | chmod -R 777 /etc/ppp/ip-pre-up |
可以使用tracerout qq.com 查看路由情况 。
1 | ip route get 4.2.2.1 |
1 | ip route add 209.99.17.0/24 via 192.168.1.1 metric 5 |
今天配置了purevpn,花了我比较久的时间,今天在这记录下,也许别人也会遇到同样的问题。
PureVPN的openvpn服务器全部被封锁在中国,所以你连不上是正常的,在Ubuntu下,无法使用openvpn. 我在这上面花了太多时间,后来改为PPTP才行。
https://support.purevpn.com/pptp-configuration-guide-for-ubuntu
Ubuntu上面配置 PPTP,默认每次是询问密码的不会保存,可以在这儿修改。
/etc/NetworkManager/system-connections/[vpnname]
文件中的password-flags修改下:
1 | password-flags=0 代表将密码保存到该配置文件中(keyfile) |
还需要添加
1 | [vpn-secrets] |
这一项操作可以在可视化界面下操作,选择保存密码。
3、通过 tail -f /var/log/syslog 可以查看你的VPN连接情况
支付宝可以设置定时转账,比如自己有一个还房贷的卡,每月1号还款,你可以设置每月1号从支付宝转到银行卡,我自己最近使用了这个功能,发现它的到账时间不是2小时内到账,不过不影响使用,如果你设置1号到账,它会在前一天转账,如果遇到假期会提前转,但是到账时间很晚,去6-30号自动转账,7-1上午12点才到账,需要注意。
Python 的 generator(生成器)是指包含有 yield 关键字的函数。即使这个函数同时包含 return 和 yield 关键字,它也是一个 generator。
generator(生成器)的作用和函数有点像,但是区别在于:如果需要生成并返回一个很长很长的列表,那么函数必须把这个列表的每个值全部计算完后一起返回。然而有时候这个列表是无穷无尽的,或者全部计算完的话耗时很久,亦或是列表的长度超过了内存容量,而实际上我们一次只需要取一个值。此时就可以使用 generator 来『一边用,一边生成』,有点类似『流式处理』。
比如说著名的斐波那契数列,一次生成所有值是不可能的,因为是个无穷序列。但是可以用 generator 来逐个生成各项的值,即调用一次只得到下一个需要的值。
TL;DR (一句话解释):
yield 相当于特殊版的 return。当第一次运行生成器的代码时,会从头开始,直到遇到 yield [某个值] 就返回一个值。以后再次调用这个生成器时,会从那个 yield 处恢复执行,而不像普通函数一样每次调用都从第一句开始。
yield 关键字可以用来实现协程(coroutine),能够让程序运行时在各个函数间跳来跳去,『多次进入,多次返回,每次接着上次的断点运行』。协程比多线程的开销要小得多,可以让多个函数配合完成一项任务,在函数遇到了阻塞(比如要等待网络上远程发来的信息)时及时跳出来去处理其他事情,避免空等。因此协程在在异步 I/O 设计中十分常见。
生成器只能向前,不能回头,也不保存之前生成的任何值。当所有值都生成完毕后,就会抛出 StopIteration 异常,再也不能使用它了。如果需要提前终止,调用 close() 方法即可。
首先来看一段代码:
1 | def get_sequence(): |
上述代码定义了一个生成器,可以依次生成 1, 2, 3, 4 …. 到 ∞ 的整数序列。每调用一次 next(get_num) 就可以得到一个下一个需要生成的值。
运行结果是:
1 | > get_sequence: 生成 1 之前 |
在第一次调用 next(get_num) 时,也是第一次进入 get_sequence() 函数。然后 i = 1,进入 while 循环,然后打印get_sequence: 生成 1 之前。之后遇到了 yield i 语句,就返回当前的 i 的值给调用者 main(),生成器在此保存断点。main() 得到了返回值,就传递给 print 语句来输出 main: 得到了生成器返回的值 1。
main() 函数接着运行,遇到了下一个 next(get_num),相当于 next_num.send(None),给生成器发送信息会重新切换到 get_sequence() 函数,并接着之前的断点执行。然后就输出了 get_sequence: 生成 1 之后,执行 i += 1,i 的值变为 2,然后进入下一轮 while 循环,直到再次遇到 yield 关键字才返回 main 函数。
调用生成器的 close() 方法可以强制关闭它。这样再次给它 send 任何信息,都会抛出 StopIteration 异常,表明没什么可以生成了。
另一个例子:
1 | # 定义一个生成器 |
运行结果是:
1 | > 得到返回值: 1 |
可以通过在 PyCharm 或者 pdb 加断点的方式来追踪程序的运行流程,从而发现『交替执行』的规律。
这段代码定义了一个生成器,其中最难理解的是 recv = yield i 这个语句。这句话并不是一句普通的赋值语句,而是分两步完成:
首先可以将 yield i 先理解为暂时的 return i,这样就会把 i 的值返回给调用者(main 函数)。然后生成器的执行被冻结在这一行,CPU 切换回 main() 函数。
print("得到返回值: %d" % next(m)) 这句代码将 next(m) 的返回值打印到屏幕上。
然后执行到下一个 next(m) 或者 m.send() 语句时,就会给生成器发回一个值(None 也是一个值),然后再次回到之前被冻结到的 recv = yield i 这一行,随后把这个发回的值赋给 recv 变量,并输出 recv 变量的值。然后继续执行,直到遇到下一个 yield 语句… (文字描述有些绕,单步调试可以看得很清晰)
yield from 可以实现『 generator 嵌套』,也就是一个 generator 嵌套另一个 generator。有没有联想到装饰器的相关知识?可以用 yield from 来很方便地实现『生成器的装饰器』。
将上述代码稍作修改,就加上了装饰器功能;
1 | def generator_decorator(the_generator): |
运行结果如下:
1 | > 我是装饰器。在您使用 generator 前后,我负责做一些处理工作... |
与之前运行结果作对比,可以看到,除了第一行是 我是装饰器。在您使用 generator 前后,我负责做一些处理工作...,与不加装饰器一模一样。说明装饰起作用了,可以先做一些预处理工作,然后完成被装饰对象(generator)的本职功能。
动态语言之间是越来越像了,JavaScript 的 ES6 支持 yield 关键字来实现生成器,C# 也早就支持了它。知识点总是相通的,不同语言之间也经常相互借鉴,而它们追根溯源,往往都来自于几十年前提出的概念(维基百科上说生成器的概念 1975 年就有了)。
解包就是把序列或映射中每个元素单独提取出来,序列解包的一种简单用法就是把首个或前几个元素与后面几个元素分别提取出来,例如:
1 | first, seconde, *rest = sequence |
如果sequence里至少有三个元素,那么执行完上述代码后:
1 | first == sequence[0] |
当函数的参数不确定时,可以使用*args 和 **kwargs,*args 没有key值,**kwargs有key值。
1 | #!/usr/bin/python |
打印结果:
1 | data1: <type 'str'> this is data1 |
Python是支持可变参数的,最简单的方法莫过于使用默认参数,例如:
1 | def test_defargs(one, two = 2): |
当然,本文章的主题并不是讲默认参数,而是另外一种达到可变参数 (Variable Argument) 的方法:使用*args和**kwargs语法。其中,*args是可变的positional arguments列表,**kwargs是可变的keyword arguments列表。并且,*args必须位于**kwargs之前,因为positional arguments必须位于keyword arguments之前。
首先介绍两者的基本用法。
下面一个例子使用*args,同时包含一个必须的参数:
1 | def test_args(first, *args): |
下面一个例子使用*kwargs, 同时包含一个必须的参数和*args列表:
1 | def test_kwargs(first, *args, **kwargs): |
*args和**kwargs语法不仅可以在函数定义中使用,同样可以在函数调用的时候使用。不同的是,如果说在函数定义的位置使用*args和**kwargs是一个将参数pack的过程,那么在函数调用的时候就是一个将参数unpack的过程了。下面使用一个例子来加深理解:
1 | def test_args(first, second, third, fourth, fifth): |
使用*args和**kwargs可以非常方便的定义函数,同时可以加强扩展性,以便日后的代码维护。
参考资料:
1 | import datetime |
1 | # -*- coding:utf-8 -*- |