猪圈里的公民

我的学校有一个很奇怪的事情。

学校的网络由现代技术中心控制,按照程序的设定,每周日到周四晚上十一点断网。但是遇到一些小的假期(比如说中秋节、端午节),这些假期常常是在断网的这几天,这时因为工作人员没有去修改设定,所以仍然会像往常一样断网。

可以想象的是,正在联机打游戏的,看电影看到一半的,正在刷社交动态的人。都会像炸锅了一样疯狂。人一疯狂,就会做出一些平日里不会做的事情,就像很多女生回到宿舍就不再矜持一样。他们或是她们打开窗户大骂,不过也不知道在骂什么,骂路由器?骂网线?骂现代技术中心?骂控制断网的那几行代码?还是骂写那几行代码的人?统统不清楚,他们只是骂,好像上帝听到会把网还给他们一样。到处都是嚎叫和咒骂。

可是这还不过瘾。例行的节目是,勇敢的男同学们开始把自己的或是偷来的暖壶从楼上往下扔,砰!——欢呼——砰!——欢呼——砰!——欢呼。这样几番下来,几栋楼的荷尔蒙逐渐开始安静了。可是还有人不甘心,“再来一个!”,砰!——欢呼,“再来一个!”,“你他妈自己扔呀!”,“……”。终于,一切归于平静。大家都躺倒在床上,举起小屏幕来。虽然屏幕小,网络却不差。

像是一段录好的带子一样,每一个假期都要拿出来放一遍。

这让我想起来猪圈里的猪。猪和主人相处的很融洽,但是有一天,主人恋爱了,经常整天待在外面,很晚才回来。这样一来,就经常忘记给猪喂猪食。猪很生气,于是就在地上拱土,拱出来一个大洞来,然后又去拱门。主人回来很生气,觉得这些猪脑子出问题了,第二天就把它们便宜卖掉了。当然,我可没说扔暖壶的人是猪,毕竟他们那么勇敢和潇洒。

这还让我想起来——张大爷发现邻居赵大爷家的狗经常来他家偷东西吃,就在自己家的院子里转了三圈,以示抗议。

猪不会说话,情有可原。但人能说能走,不管好不好使,总还有个脑子。既然觉得事情不合理,为什么不去找相关部门反映呢。何况这种生活上的事情,完全不会触及到任何敏感点。虽然他们的效率可能会很低,就像我去年报修加投诉,半个月里跑了三趟,才让他们把一个漏水的水龙头修好。但假如扔水壶的人都去跑一趟,我相信问题很快就会解决的。不过反正我不需要,既然没人想去解决,就让故事这样继续下去吧。

那个粗心或是懒惰的程序员,肯定不知道自己竟然带动了整个大学城附近超市的暖壶销量。不过这也顺便害苦了保洁阿姨。

保洁阿姨每次放假回来,都会惊讶的发现,宿舍楼中间的小路上多了好多碎掉的暖壶。时间久了,保洁阿姨也习惯了。在家里的时候,阿姨们很爱跟别人讲这个事情。后来大家都知道了,XX学校的学生上学太压抑太苦了,一放假就兴奋的往楼下扔暖壶……

这个故事告诉我们:写好代码,能救暖壶。

Flask问题集:单个页面两个(多个)表单

出于简化交互的考虑,我们经常见到很多网站把登录页面和注册界面放在同一个页面上,而当我们使用Flask来实现时,却发现问题重重:

  • 不管是哪个表单按下了提交按钮,总是提交第一个表单的数据;
  • 当一个表单数据验证出错时,两个表单都出现了错误提示;

问题的解决

简单来说,问题的主要原因是Flask-WTF的form1.validate_on_submit()并不验证是哪个表单的submit按钮被按下了,只是通过HTTP方法是否是“PUT”或“POST”来判断。

同时form1.submit1.data的data函数会迭代字段的名字(submit)和数据(True/False)作为一个字典,这会产生键重复的问题,所以确保两个表单的submit字段的名字不同。

另外,更改if语句判断条件的顺序(只对按下按钮的表单执行.validate_on_submit()),避免一个表单出错时两个表单同时出现错误提示信息。具体见下面两个代码块。

为你的不同表单里的SubmitField定义不同的名字,像这样:

class Form1(Form):
    name = StringField('name')
    submit1 = SubmitField('submit')

class Form2(Form):
    name = StringField('name')
    submit2 = SubmitField('submit')

....

在 view.py 里添加if判断:

....
form1 = Form1()
form2 = Form2()
....

if form1.submit1.data and form1.validate_on_submit(): # 注意顺序 
    ....
if form2.submit2.data and form2.validate_on_submit(): # 注意顺序
    ....

现在问题解决了,如果你想了解更多一点,那就继续读下去。

探究问题的本质

这是 validate_on_submit():

def validate_on_submit(self):
    """
    Checks if form has been submitted and if so runs validate. This is
    a shortcut, equivalent to ``form.is_submitted() and form.validate()``
    """
    return self.is_submitted() and self.validate()

这是 is_submitted():

def is_submitted(self):
    """
    Checks if form has been submitted. The default case is if the HTTP
    method is **PUT** or **POST**.
    """
    return request and request.method in ("PUT", "POST")

当你对表单调用 form.validate_on_submit() 的时候,它只是通过HTTP方法来检查提交的表单,而不是哪个表单上的按钮被按下了。所以上面的小技巧只是添加一个过滤器(也就是检查按钮是不是有数据,即 form1.submit.data)。

另外,我们改变了if判断的顺序。这样当我们点击其中一个表单上的按钮时,它只对这个表单调用验证函数validate(),所以不会两个表单都出现错误提示。

故事还没完,这是静态方法.data:

@property
def data(self):
    return dict((name, f.data) for name, f in iteritems(self._fields))

它返回一个以字段名(field name)和字段值(field value)作为键值对的字典,但要注意的是,两个表单的提交按钮的字段名都是submit!

这带了什么问题呢?想一想Python里字典的特性就知道了,字典用键来索引一个值,所以会有键重复的问题。

当我们点击第一个表单上的提交按钮(submit)时,form1.submit1.data返回一个像这样的字典:

temp = {'submit': True}

毫无疑问,当我们调用 if form1.submit.data时,它会返回True。

而当我们点击第二个表单上的提交按钮(也是submit)时,if form1.submit.data先生成了一个键值对,然后form2.submit.data生成了键值对,结果这个字典就变成了这样:

temp = {'submit': False, 'submit': True}

这就是为什么我们不论点击那个表单上的按钮,对第一个表单的验证总是返回True。我们通过为两个表单的字段设定不同的名字解决了这个问题。

感谢你读到这里,这样看来,你有很强的好奇心和耐心,而且对编程怀有很大的热情,我说的没错吧:p

首发于Stack Overflow:python – flask-bootstrap with two forms in one page

更多关于Flask的优质内容,欢迎关注Hello, Flask! – 知乎专栏

Flask笔记(5):表单

Flask有众多的扩展来简化集成各种常用的库和框架,比如Flask-Bootstrap集成了Bootstrap,Flask-WTF集成了WTForms。这篇要介绍的就是Flask-WTF。

 

安装和配置

安装很简单,使用pip:

pip install flask-wtf

Flask-WTF默认支持CSRF(跨站请求伪造)保护,只需要在程序中设置一个密钥。Flask-WTF使用这个密钥生成加密令牌,再用令牌验证表单中数据的真伪。(关于Flask项目的配置和初始化,后续文章会谈到)你可以使用app.config字典来存储配置变量:

app = Flask(__name__)
app.config['SECRET_KEY'] = 'hard to guess string'

或是从系统环境变量中获取

app = Flask(__name__)
app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY')

很多重要的信息,比如邮箱账户和密码都不能直接下载程序里,而要设置系统环境变量,设置方法如下(Windows CMD):

set SECRET_KEY=very very hard to guess string

后面的字符串不需要用任何符号括起来。

 

表单

每个表单都用一个继承自Form的类表示,每个字段都用一个对象表示,每个对象可以附加多个验证函数。常见的验证函数有Required()Length()Email()等。
一个登录表单示例:

from flask_wtf import Form # 导入Form
from wtforms import StringField, SubmitField, RadioField, PasswordField, BooleanField # 导入字段
from wtforms.validators import Required, Length, Email # 导入验证函数
class LoginForm(Form):
    email = StringField(u'邮箱', validators=[Required(message= u'邮箱不能为空'), Length(1, 64), Email(message= u'请输入有效的邮箱地址,比如:username@domain.com')])
    password = PasswordField(u'密码', validators=[Required(message= u'密码不能为空')])
    remember_me = BooleanField(u'记住我')
    submit = SubmitField(u'登录')
  • 在验证函数中传入出错时的提示信息,覆盖默认的英文错误提示。
  • WTForms支持的基本字段
  • WTForms支持的验证函数
 

渲染表单

表单有很多种渲染方式。
下面以一个撰写文章的表单为例。

 

默认的渲染方式

<form class="form" method="POST">
    {{ form.hidden_tag() }}
    {{ form.title.label }}{{ form.title() }}
    {{ form.body.label }}{{ form.body() }}
    {{ form.submit() }}
</form>

这种方式渲染出来的表单没有样式,而且很繁琐(当然,你也可以使用for循环来遍历字段)。

 

使用Flask-Bootstrap渲染

Flask-Bootstrap提供了一个模板(wtf.html),可以让你快速生成样式良好的表单。

{% import "bootstrap/wtf.html" as wtf %}
<form class="form" method="POST">
    {{ form.hidden_tag() }}
    {{ wtf.form_field(form.title) }}
    {{ wtf.form_field(form.body) }}
    {{ wtf.form_field(form.submit) }}
</form>

假如你不需要调整Boostrap的默认表单样式,只想要快速生成表单,那么Flask-Bootstrap还提供了一个强大的函数,只需要一行就可以快速生成表单):

{% import "bootstrap/wtf.html" as wtf %}
{{ wtf.quick_form(form) }}
 

控制表单的样式

对于样式,可以通过给表单增加id或class来实现。比如这样:

{{ form.body.label }}{{ form.body(class="post-body") }} # 默认渲染
{{ wtf.form_field(form.body, class="post-body") }} # 使用Flask-Bootstrap渲染

也可以在表单类里传入参数,像这样:

body = TextAreaField(u'正文', validators=[Required(u'内容不能为空!')], render_kw={'rows': 20, 'placeholder': u'你有什么想法?'})

在表单字段里传入一个render_kw字典,将HTML的参数和值以键值对的形式写入字典。WTForms2.1及以上版本适用。

这里需要注意的是,Flask-Bootstrap会给表单添加class来控制样式,这时你再通过render_kw传入已经被定义过的参数会失败。所以,如果要使用render_kw传入class,得确保表单字段使用默认的渲染方式。

 

提交表单视图

这是一个添加文章的视图。

@main.route('/new/post', methods=['GET', 'POST'])
@login_required
def new_post():
form = PostForm()
if form.validate_on_submit():
    post = Post(
    title = form.title.data,
    body = form.body.data)
    db.session.add(post)
    db.session.commit()
    return redirect(url_for('.post', id=post.id))
return render_template('edit/new_post.html', form=form)
 

常见问题索引

  1. 一个页面里有多个表单
  2. 文件及多文件上传
  3. 文本编辑器支持

 

Flask笔记索引

这个系列的文章是我学习Flask的经验总结。大致按照《Flask Web开发》这本书的主要章节来分类,总结书里内容的同时增加了其他内容。还有一些是我在开发翻相册的过程中遇到的问题和解决方案。预计在年底完成所有文章。

Flask开发

  1. 环境搭建与项目结构
  2. 程序配置与初始化
  3. 路由和视图函数
  4. 模板
  5. 表单
  6. 数据库
  7. 电子邮件
  8. 测试
  9. 部署

实际应用

  1. 用户认证
  2. 用户角色与权限
  3. Markdown文章
  4. 分页
  5. 关注 
  6. 应用编程接口

问题集

  1. 单个页面多个表单
  2. 文件和多文件上传
  3. 喜欢按钮
  4. 动态删除照片

CSS笔记:Layout

目录

 

一、Display

元素的默认display值是block或inline。

block

block层级的元素总是新起一行,占全宽度。下面的元素默认为block:

<div>
<h1> – <h6>
<p>
<form>
<header>
<footer>
<section>

如果不想让block元素占据全宽度,可以使用width属性设置宽度,同时,如果想让内容适应不同大小的屏幕,使用max-width

inline

inline元素不新起一行,而且只占用需要的宽度。inline元素有:<span>、<a>、<img>

可以重写元素的display默认值来获得特殊效果。

inline-block

inline-block元素和inline元素差不多,但是它可以设置固定的高宽。

none

如果元素的display的属性值为none,那么这个元素将不会显示。<script>元素的display值就是none。这经常被用来控制一个元素的显示的隐藏(使用JavaScript):

document.getElementById("mask").style.display ='none';

display:none or visibility:hidden?

display:none是隐藏一个元素,像是这个元素不存在一样。而visibility:hidden只是使元素不可见,元素仍然占据原有的空间

 

二、Position

有四种值(默认为static):

static 
relative 
fixed 
absolute

static

position属性为static的元素的位置没有特殊效果。

relative

相对定位。这里的relative是指相对于正常的位置进行定位。可以设置top,right,bottom和left来偏移位置。

fixed

固定定位。相对于浏览器窗口来说是固定的,无论你怎么缩放窗口大小,或是滚动内容。可以设置top,right,bottom和left来偏移位置。

absolute

绝对定位。相对于最近的父元素(position值为static的元素除外)进行定位。可以设置top,right,bottom和left来偏移位置。

z-index

z-index属性用来指定一个元素在z轴上的位置,利用这个属性可以实现元素的重叠。如果不指定,在HTML文件里,代码位置靠后的元素会在上面。主要使用场景有: 1. 在图片上添加一个按钮,这时把按钮的z-index设置比图片大,就可以点击到按钮而不是图片。 2. 在图片上显示文字,只要把图片的z-index设为-1就可以了。

 

三、Overflow

Overflow用来定义当元素的内容超过限定的范围后的显示方式。有四种值:

visible

默认值。超出的内容仍然显示。

hidden

超出的内容将被隐藏。

scroll

添加一个滑动条。(将同时添加水平方向和竖直方向的滚动条,即使不需要。)

auto

类似于scroll,不过只在需要的时候添加滑动条。

overflow-x overflow-y

这两个值用来分别定义两个方向的overflow值。

div { 
    overflow-x: hidden; /* 隐藏超出内容 */ 
    overflow-y: scroll; /* 添加垂直滑动条 */ 
}

 

四、Float

float用来设置元素的滚动,像这样float: left;。一般的用法有:让文字包裹图片;制作navbar,让li元素向左浮动。

浮动的元素下面的元素会包裹住浮动的元素,这时可以用clear用来控制元素的滚动,下面这行让左边的元素不滚动:

div { 
    clear: left; 
}

 

五、Align

  • 水平居中:使用margin: auto;(在IE8里需要声明!DOCTYPE)。这时要给元素限定宽度,比如width: 50%;,限定的宽度之外的空间会被一分为二。
  • 垂直居中:使用padding属性可以让元素在父容器里垂直居中padding: 50px 0;
  • 文本居中:text-align: center;
  • 图片居中:

display: block; 
margin: auto;
  • 居左或右:使用float。

  • 水平+垂直居中:使用padding加上text-align: center;。或是使用position和transform:

.center { 
    height: 200px; 
    position: relative; 
    border: 3px solid green; 
} 

.center p { 
    margin: 0; 
    position: absolute; 
    top: 50%; 
    left: 50%; 
    transform: translate(-50%, -50%); 
}

Flask笔记(1):环境搭建与项目结构

环境搭建

完成一个Flask项目需要三个工具: – git:用于版本控制 – pip:用来安装各种包 – virtualenv:用来创建虚拟环境 git和pip是基本工具,就不多说了,这里主要介绍一下virtualenv。

virtualenv

virtualenv可以用来建立一个独立的Python虚拟环境。你可以为每一个项目建立不同的虚拟环境,各个环境互相独立。这样可以带来很多好处:方便分发项目,避免Python环境杂乱。 在Python3.4中,可以使用原生的pyvenv。 使用pip安装virtualenv

pip install virtualenv  

切换到你的项目目录,然后使用下面的命令创建一个虚拟环境

virtualenv venv 

venv 是虚拟环境的名字,你可以更改它,但一般常使用venv。每次要使用这个虚拟环境时,你都要激活它。在你的项目根目录使用下面的命令激活虚拟环境。

# Linux:
source venv/bin/activate
# Windows:
venv\Scripts\activate

激活以后你会看到你的命令行提示符前面多了一个虚拟环境的名称:(venv)。当你需要退出虚拟环境时,在命令行下输入deactivate即可。

项目结构

一个大的Flask项目需要合理的组织,比如把数据库模型、路由、表单等分别放在不同的文件里。良好的项目结构可以使开发更加高效,也利于代码的维护和测试。 典型的Flask项目结构是这样的:

|-flask*  你的项目名称
    |-app/
        |-templates/  模板文件
        |-static/  静态文件(CSS和JS文件,图片等)
        |-main/
            |-__init__.py
            |-errors.py  错误处理
            |-forms.py  表单
            |-views.py  路由
        |-__init__.py
        |-email.py  邮件
        |-models.py  数据库模型
    |-migrations/  数据库迁移
    |-tests/  单元测试
        |-__init__.py
        |-test*.py
    |-venv/  虚拟环境
    |-requirements.txt  项目依赖的库
    |-config.py  配置(项目变量等)
    |-manage.py  管理(启动程序等)

###requirements.txt(需求文件) 需求文件是你的项目所依赖的库和版本号。类似这样:

Flask==1.1
Flask-Bootstrap==3.0.
Mako==1.4

借助这个需求文件,你可以在其他电脑上快速生成相同的环境。使用pip生成:

pip freeze >requirements.txt

在其他的电脑创建副本时,使用下面的命令:

pip install -r requirements.txt

对Stack Overflow的思考

我大约在2015年的年末注册了Stack Overflow(下面简称SO)。那时候正在学Python,在Google上搜索编程方面的问题,跳出来的很多结果都是SO上面的,于是顺便注册了一个账号。直到最近才开始使用它,发现这不是一个普通的网站。

Stack Overflow是什么?

简单的说,这是一个问答网站(包括StackExchange),有人提出关于编程的问题,然后有人来回答。

每一个用户在SO都有一个Reputation值(声誉),类似于积分。你回答的问题得到了vote up(+10),或是被提问者接受(+15),你会获得相应的reputation。而如果你做了坏事,乱写答案被vote down(-2),发表不友善的内容被六个人标记(-100),你会被减掉相应的reputation。一定的reputation可以解锁Privileges(特权),privileges控制着你在SO上的权限。简单列举几个:

  • 15个reputation可以vote up;
  • 50个reputation可以对问题进行评论;
  • 125个reputation可以vote down(同时减掉一个reputation);
  • 1500个reputation可以创建标签;
  • 2000个reputation可以修改别人的问题和答案;
  • 25000个reputation可以获得里程碑特权(Milestone Privilege),这时你可以接触到网站的内部数据。

这样的声誉系统和特权系统带来的是什么呢?一个由社区用户们运行和管理的,有着良好的秩序、效率和氛围的问答网站。 除此之外,SO还有成就系统和影响力数据。一共有金银铜三种勋章,当你完成了特定的任务后就可以获得。而影响力是你的答案帮到了多少人,和你的其他活动数量:投票,标记和修改。

Stack Overflow的介绍

Stack Overflow的介绍

和知乎的对比

既然是问答网站,免不了想把知乎拿来比一比。知乎上的太多问题(缺点)在SO上都能找到相应的解决方案。在网站内容上,SO不欢迎任何讨论性的,非Problem-Solving类的问题。而知乎上的内容过于混杂,几乎所有值得不值得讨论的问题都有。很多问题仅仅是为了引起一些讨论,而不是要解决什么问题。比如典型的“如何看待XXX”。经常看到的现象是,有相同观点和价值观的人在这里抱成一团,一起打压和攻击其他意见。

知乎上的赞成和反对更多的是用户基于对答案里的观点和价值观的(主观)喜好来判断的(这两个词本身就能说明一些问题)。对于提问者来说的好答案可能还没有取悦观众们的差答案票数高。

知乎的社区管理却是实在的短板,新用户可以随便的投反对票,修改答案,攻击侮辱别人,发表充满恶意的评论。对回答也没有限制,任何人都可以发言,不管你有没有在回答问题。而在SO上,你要做这些事情,得先解决别人的问题,然后获得reputation来解锁这些权限。在SO上,你几乎看不到攻击,批评和嘲笑。因为你的任何非善意的答案和评论都会被别人标记,当你收到六个垃圾信息标记或攻击性标记时,你的reputation将会被减去100(你的回答被接受才得到15个reputation!)。当你提的问题太宽泛,不涉及具体的问题,或是太简单时会很快被关闭,当你的回答不合适时也会有人来提醒和投票删除,或是vote down。而你的没有帮助的回答,和自我营销式的信息(知乎上很多见)会被投票删除,或是vote down。

在SO的帮助中心里,有这样的文章:

在帮助中心的《Be Nice》的末尾是这样写的:

We’re proud to be a large, user-driven space on the internet where name-calling, harassment, and other online nastiness are almost non-existent. It’s up to all of us to keep it that way.

In summary, have fun, and be good to each other.

(我们感到骄傲的是,作为一个庞大的,用户驱动的网络空间里,在这里,辱骂、骚扰和其他网络污秽几乎不存在。是我们大家一起维护着这个良好的环境。

综上,找点乐子,互相友好。)

不完美的完美

SO的创建人之一(Jeff Atwood)在博客里写了这些话:

Stack Overflow is you. This is the scary part, the great leap of faith that Stack Overflow is predicated on: trusting your fellow programmers. The programmers who choose to participate in Stack Overflow are the “secret sauce” that makes it work. You are the reason I continue to believe in developer community as the greatest source of learning and growth. You are the reason I continue to get so many positive emails and testimonials about Stack Overflow. I can’t take credit for that. But you can. I learned the collective power of my fellow programmers long ago writing on Coding Horror. The community is far, far smarter than I will ever be. All I can ask — all any of us can ask — is to help each other along the path. And if your fellow programmers decide to recognize you for that, then I say you’ve well and truly earned it.

当然,SO并不完美。这个SO用户是top 2%的用户(24898 reputation),他写了一篇文章叫Why I no longer contribute to StackOverflow(为什么我不再为Stack Overflow社区贡献),文章里讲了很多SO的问题。比如过于严格的内容控制,不合理的奖励机制,授人以鱼式的教育等等。

这些问题的确存在,但相对来说,SO是个很棒的社区,值得我去做点什么。

我的资料页

这是我的账号:lihui

Markdown——简单的世界

Markdown 是一种轻量级标记语言,创始人为约翰·格鲁伯(John Gruber)。它允许人们“使用易读易写的纯文本格式编写文档,然后转换成有效的XHTML(或者HTML)文档”。
—— 维基百科

很早就接触到Markdown,但投入使用是从用Github和Stack Overflow开始的。使用Markdown,你不用再和难用的编辑器纠缠,手也不用离开键盘,这让你更专注于内容本身。

 

基本用法

Phrase Emphasis

*italic*   **bold**
_italic_   __bold__

Links

Inline:

An [example](http://url.com/ "Title")

Reference-style labels (titles are optional):

An [example][id]. Then, anywhere
else in the doc, define the link:

  [id]: http://example.com/  "Title"

Images

Inline (titles are optional):

![alt text](/path/img.jpg "Title")

Reference-style:

![alt text][id]

[id]: /url/to/img.jpg "Title"

Headers

Setext-style:

Header 1
========

Header 2
--------

atx-style (closing #’s are optional):

# Header 1 #

## Header 2 ##

###### Header 6

Lists

Ordered, without paragraphs:

1.  Foo
2.  Bar

Unordered, with paragraphs:

*   A list item.

    With multiple paragraphs.

*   Bar

You can nest them:

*   Abacus
    * answer
*   Bubbles
    1.  bunk
    2.  bupkis
        * BELITTLER
    3. burper
*   Cunning

Blockquotes

> Email-style angle brackets
> are used for blockquotes.

> > And, they can be nested.

> #### Headers in blockquotes
> 
> * You can quote a list.
> * Etc.

Code Spans

`<code>` spans are delimited
by backticks.

You can include literal backticks
like `` `this` ``.

Preformatted Code Blocks

Indent every line of a code block by at least 4 spaces or 1 tab.

This is a normal paragraph.

    This is a preformatted
    code block.

Horizontal Rules

Three or more dashes or asterisks:

---

* * *

- - - - 

Manual Line Breaks

End a line with two or more spaces:

Roses are red,   
Violets are blue.

 

其他规则

  • 支持HTML标签,可以自由的插入HTML。
  • 自动转义特殊字符:“&”和“<”。
  • 如果你想显示一个被用作标记的符号,使用反斜线进行转义。比如下面这行将不会加粗文本,而只是显示出两个星号。
\*literal asterisks\*
  • 可以被转义的符号:
\   backslash
`   backtick
*   asterisk
_   underscore
{}  curly braces
[]  square brackets
()  parentheses
#   hash mark
+   plus sign
-   minus sign (hyphen)
.   dot
!   exclamation mark

 

编辑器

大部分编辑器都能实现即时预览和PDF、HTML文件输出。下面的推荐来自维基百科的Markdown词条页面

  • Cmd Markdown Cmd Markdown 编辑阅读器,支持实时同步预览,区分写作和阅读模式,支持在线存储,分享文稿网址。
  • Dillinger.io 一个在线Markdown编辑器,提供实时预览以及到 GitHubDropbox 的拓展连接。
  • notepag 另一个在线Markdown编辑器,支持实时预览,提供临时网址和和密码,可以分享给其他人。
  • 简书 一个在线Markdown编辑器与阅读社区,支持实时预览,提供分享网址。
  • Mou 一个Mac OS X上的Markdown编辑器。
  • MacDown OS X 上的 Markdown 开源编辑器,作者称其深受 Mou 启发。
  • MarkdownPad Windows上的全功能Markdown编辑器。
  • WMD a Javascript “WYSIWYM” editor for Markdown (from AttackLab)
  • PageDown 一个Javascript写的 “WYSIWYM”(所见即所得)Markdown编辑器 (来自 StackOverflow)
  • IPython Notebook 以IPython为后台,利用浏览器做IDE,支持Markdown与LaTex公式。

 

参考链接

2016下半年计划

生活里有很多内容和细节,让人很容易沉浸。在某一方面这是好事,这是心理学上的精神贯注和心流(Flow)。但如果贯注的对象是错的,那就不是件好事了。如果你对盗版没有道德判断,又缺乏自律,那么网上有无数的电影,音乐,资料,足以让你变成下载狂。如果你贯注的对象是金钱,那么你很容易变成唯利是图的人。

这就是为什么人需要计划。计划让你远离不重要的细节和琐碎,让你不再关注电脑换什么壁纸、拖鞋买什么颜色、最近出了什么新手机。(如果你是开鞋店和手机店的,那当我没说。:)

不知道怎么做计划?先认识和了解自己,找到你的目标,找到对自己来说生活中最重要的事情。分解你的目标,关注你的重点。然后列出计划来。

 

主要目标

  1. 完成写作计划(100篇)
  2. 用Flask做一个网站
  3. 找到Python方面的实习

 

一、编程

重点

  1. 学习Flask
  2. 完成《Python核心编程》的习题
  3. 100Words网页版
  4. 翻相册网站

 

其他

  1. ManyHead
  2. HowMany
  3. Shakeword
  4. 完善其他项目
  5. CS50
  6. 做本地和网页端的小程序练手
    1. 计算器
    2. 邮箱客户端
    3. 聊天软件
    4. 翻译软件
    5. RSS阅读器
    6. TODO清单(web)
    7. 便签本(web)
    8. 计时器(web)

 

学习和了解

  1. C
  2. SQL
  3. Bootstrap
  4. JavaScript
  5. Linux
  6. Vim/Emacs
  7. Java

 

二、阅读

预期数量:20本
主要主题:计算机、文学

  1. Learn C The Hard Way
  2. Think Java
  3. 编码
  4. 重读幸福之路
  5. 重读写作这回事
  6. 黑客与画家
  7. 世界是平的
  8. 文学回忆录(下)
  9. 怎样解题
  10. 雪国
  11. 银河系漫游指南
  12. ……

 

三、写作

至少完成45篇

 

四、英语

主要工作:大量听读输入,朗读练习

  1. 重读语法书《文法俱乐部》
  2. 完成口语教材《American Accent Training》
  3. 每天朗读20分钟
  4. 每天听20分钟
  5. 每天阅读30分钟

 

五、技能

  1. 学习并使用双拼
  2. 魔方
  3. 继续练习羽毛球
  4. 学习游泳

 

六、其他

  1. 学习并通过三门自考课程
  2. 拍大量照片
  3. 健身重点:腹肌,下肢和背部
  4. 养成使用英文关键词搜索的习惯
  5. 多喝牛奶和吃水果,避免零食和饮料
  6. 避免发牢骚,或在文章里发泄对别人的情绪
  7. 练习宽容和礼貌
  8. 和气或虚心的对待不同意见和反对意见
  9. 清理不必要的物品
  10. 养成和改掉一些习惯

 

七、时间计划

(以天为单位)

  1. 编程:约240小时(2小时/天)
  2. 阅读:约120小时(1小时/天)
  3. 写作:约60小时(30分钟/天)
  4. 英语:约120小时(1小时/天)
  5. 运动:约60小时(30分钟/天)(每周三次去健身房,周末打羽毛球或游泳)
  6. 娱乐:不超过100小时(不超过1小时/天)

typing.js——打字机效果

前一段时间,无意间在某个人的个人页面看到一个很有趣的打字机效果,可以自动的打出一段文字,删掉,然后打出另一段文字。经过半天的尝试,自己写了一个出来。因为没有系统学过JavaScript(只看过一本JavaScript编程精解……),写出来的代码不够简洁和优雅,嵌套了太多if语句。欢迎到Github上提交修改。

GitHub项目地址: https://github.com/greyli/typing.js

DEMO

打字机效果很适合用在个人页面和主页的头部,下面是几个示例。

用法

首先把CSS和JS文件放到相应的目录下,然后在HTML文件里分别引入这两个文件:

CSS

<link href="typing.css" rel="stylesheet">

JS

<script src="typing.js"></script>

在需要放置的地方插入下面这行

<span id="words"></span><span id="cursor">|</span>

cursor是文字后面闪烁的光标,你可以更换它。

最后在末尾设置你要定义的字段和相关的设置。首先你需要定义一个数组,然后写入单个或多个字段。

<script>
  var strings = new Array("一段文字"); // 单个字段
</script>
<script>
  var strings = new Array("文段1", "文段2"); // 多个字段
</script>

可选的设置有打字速度和删除速度,是否循环(默认为循环)等。

<script>
  var strings = new Array("文段1", "文段2") ; // multi words
  var typingSpeed = 100; // 打出每个字的间隔时间
  var deleteSpeed = 40; // 删除每个字的间隔时间
  var isLoop = true; // 是否循环,true/false
  var waitTime = 800; // 打完一个字段后的等待时间
</script>

最后

如果你在使用这个JS库,那么请让我知道,我会把你加入DEMO里。 

2016暑假总结

和前几个暑假一样,两个月很快就过去了。回过头来看,七月几乎没有多少成果,八月才开始稳定的学习和工作。

现在还能回想起来和家人相处的快乐:妈和奶奶做的好吃的菜;安静的晚上;和弟弟玩的游戏;和瑶瑶在楼顶看的星空。希望以后还能有能力和时间来制造这样快乐的回忆。

阅读(完成度:75%)

  1. 撒冷镇
  2. 牛鬼蛇神录
  3. 程序员修炼之道(注重实效的程序员)
  4. Powerful Sleep
  5. The Element of Style
  6. 少有人走的路(重读*2
  7. Flask Web开发
  8. JavaScript 编程精解
  9. 一滴泪

未完成:

  • Learn C The Hard Way :完成了10%。
  • Python Cookbook:当做工具书用了。
  • Python核心编程:这本书在暑假前就已经读完,不过习题只完成到十三章,计划年底完成全书的习题。

写作(完成度:85%)

  1. 2016暑假计划
  2. 小说和改编电影
  3. 《撒冷镇》笔记
  4. 通过这12个问题认识自己
  5. 大学应该怎么度过?
  6. 写作的乐趣
  7. AutoHotkey——自动化你的生活
  8. AutoHotkey——进阶实践与思考
  9. 如何获得优质的睡眠?
  10. Tkinter效果总结
  11. 我的信息处理系统:收集
  12. 日常快捷键配置:daily.ahk
  13. 告别盗版
  14. SimpleWords——幻灯片生成器
  15. 100Words
  16. 十个初级Python练习题
  17.  2016暑假总结

未完成:三篇

编程(完成度:56%)

未完成:

  • 翻相册(网站、Windows程序):虽然看了Flask Web开发,也跟着作者敲了书中所有的样例代码,还是把web编程想的太简单了,还需要一些时间。
  • 俯卧撑俱乐部(网站、文章)

知识和技能(完成度:78%)

  • Google搜索技术
  • 打字标准指法
  • 英语EnglishPod60
  • Java基本知识
  • C基本知识
  • JavaScript基本知识
  • Git常用命令
  • MarkDown语法
  • AutoHotkey基本知识

未完成:

  • 英语跟读:虽然没有每天抽出单独的时间来练习,听播客的时候有跟读。
  • 练字:练了大概有一周时间,没能坚持下来。
  • 双拼:形成了标准指法打字,但没有继续学习双拼。排进下半年的计划里。

其他(完成度:28%)

  • 电影若干
  • 游戏传送门系列

未完成:

  • 腹肌:虽然每周三次锻炼腹肌,但肌肉还是没有很明显,不过已经形成雏形了……
  • 十幅涂鸦
  • 浏览教材:计算机网络原理 —— 完成40%
  • 浏览教材:JAVA语言程序设计 —— 完成70%
  • 浏览教材:高数

时间

  • 编程:79小时22分钟
  • 写作:39小时50分钟
  • 阅读:64小时19分钟
  • 英语学习:16小时24分钟
  • 运动:29小时6分钟
  • 娱乐:143小时10分钟

娱乐太多了,达到了143小时(其中有104小时是七月的数据),主要原因是因为七月的不稳定的生活。下面是相应的时间数据饼图:

七月   

七月时间数据

七月时间数据

八月

八月时间数据

八月时间数据

总完成度:85%

虽然达到了计划的指标,但目前的完成度统计是用项目数量作为计算依据的,还不算太准确。未来会慢慢完善这种统计的准确性。

最后一个暑假结束了。

10个Python练习题

从开始学Python以来,接触了不少练习题。下面十个练习题,是我做出来的和想做出来的题里比较有趣的,现在按照难度由低到高排列。欢迎到Github上提交你的答案。

Github地址:https://github.com/lihuii/PythonExercises

 

一、猜数字

经典的猜数字游戏,几乎所有人学编程时都会做。

功能描述:随机选择一个三位以内的数字作为答案。用户输入一个数字,程序会提示大了或是小了,直到用户猜中。

 

二、FizzBuzz

另一道经典编程题。

功能描述:遍历并打印0100,如果数字能被3整除,显示Fizz;如果数字能被5整除,显示Buzz;如果能同时被35整除,就显示FizzBuzz。结果应该类似:0,1,2Fizz4Buzz6……14FizzBuzz16……

 

三、猜数字的AI

和猜数字一样,不过这次是设计一个能猜数字的AI

功能描述:用户输入一个单位以内的数字,AI要用最少的次数猜中,并且显示出猜的次数和数字。

 

四、整点报时

老式挂钟会在整点的报时,响铃的次数和时间相等。我们设计一个在电脑上运行的报时器。

功能描述:运行后,在每一个整点长响一声,半个整点短响两声。实现睡眠模式,晚上十二点到早上六点不响铃。

 

五、敏感词审查

一向痛恨网络审查的你成了某网站的审查员,要求审查网络上违反上头规定的名词。

功能描述:要审查的帖子在这个文本文档【todo】里,要求将所有的和谐,三个代表,言论自由,64替换为“*”号。

 

六、文字冒险游戏

你想做个清新脱俗的文字游戏,只在命令行的黑框里运行。

功能描述:尽量参考回合制RPG游戏的模式,游戏剧情自编,要有战斗模式,主角有HP属性,战斗和吃东西会对HP有相应的增减效果。

 

七、词频统计

你想分析某个英语写作者的写作风格,你想先从他使用词语的频率入手。

功能描述:分析这个文本文档【todo】里的词频,按照出现频率由高到低排列结果,不区分大小写,过滤掉标点(可以使用正则表达式)。结果类似ok234play122funny78

 

八、Markdown转换器

你一向喜欢在Windows的记事本里写文章,为了能方便的生成网页,你使用Markdown的格式写了篇文章,现在需要一个把Markdown转换成HTML格式的程序。

功能描述:将这个文本文档【todo】里的内容转换成HTML文档。要尽可能的支持Markdown标签,越多越好。建议使用正则表达式。

 

九、邮件轰炸机

你的一个朋友生日快到了,你决定搞个恶作剧——用邮件塞满他的邮箱。

功能描述:首先去注册十个邮箱,然后用这是个邮箱轮流发送随机生成的邮件内容给你的朋友。调整发送的频率,以免被服务器拒绝。

 

十、用邮件控制电脑

你的电脑放在宿舍,这时你在教室上课,你又决定搞个恶作剧吓吓装病请假在宿舍玩游戏的室友。

功能描述:使用邮件发送特定的命令,让电脑上的程序判断发信方是否为控制邮箱,如果是就执行发送过来的命令。通过不同的方式实现尽可能多的功能。

 

想要更多的挑战?可以去这里看看:http://www.pythonchallenge.com/

注:上面的几个文本还没有弄好>_<。