AoboSir 博客

与15年前的我比,我现在是大人;与15年后的我比,我现在还是个婴儿

Git(GitHub) 002 如何在GitHub for Windows 软件上为代码库创建一个版本标签


参考网站:


要想给代码库贴标签,Github For Windows 软件上没没有这个按钮。你需要在Github For Windows 软件上打开 Git 命令行窗口,还是要使用命令行工具来完成这个工作。

Alt text

1
2
git tag -a v1.0 -m "description information"
git push origin v1.0

当你执行完git tag -a v1.0 -m "description information",想要查看一下,你可以执行:

1
git show v1.0

如果你执行完git tag -a v1.0 -m "description information",想要删除这个标签,可以执行:

1
git tag -d v1.0

Learning Python 023 类编程


  • 使用的电脑系统:Windows 10 64位
  • 使用的开发集成环境:PyCharm 2016.1.4
  • 使用的Python的版本:python 3.5.0

怎么使用python编写一个

参考网站:Python3-cookbook 类与对象

随便编写一个Python类,类里面至少有下面三个函数:

1
2
3
4
5
6
7
8
9
10
class Pair:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __repr__(self):
        return 'Pair({0.x!r}, {0.y!r})'.format(self)

    def __str__(self):
        return '({0.x!s}, {0.y!s})'.format(self)
  • __init__() 函数就是类的构造函数。
  • __repr__()__str__() 函数 都是用来输出字符串用的。
1
2
3
4
5
6
>>> p = Pair(3, 4)
>>> p
Pair(3, 4) # __repr__() output
>>> print(p)
(3, 4) # __str__() output
>>>

Learning Python 022 调用DOS命令 --- 实例:调用Windows里面的copy命令


  • 使用的电脑系统:Windows 10 64位
  • 使用的开发集成环境:PyCharm 2016.1.4
  • 使用的Python的版本:python 2.7.10 和 python 3.5.0

本篇博客对 Python2 和 Python3 都适用。


实例:调用Windows里面的copy命令

比如现在,我想把这个路径F:\原文件夹里面的所有文件复制到这个路径F:\目标文件夹里面。可以在DOS命令行窗口里面执行:

1
copy "F:\原文件夹\*" "F:\目标文件夹\"

所以,我们要使用Python调用DOS命令行工具的步骤就两步:

  1. 构造命令字符串。
  2. 使用os.system()函数执行命令字符串。

我们使用python调用Windows系统DOS命令行里面的copy工具来进行文件的复制。代码如下:

适合在Python3中执行的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# -*- coding: utf-8 -*-

import os

org_folder = r'F:\原文件夹'
res_folder = r'F:\目标文件夹'

# 构造命令字符串
copy_command = 'copy "' + org_folder + r'\*" "' + res_folder + r'\"'
# copy_command = copy_command.decode('utf-8').encode('GB18030')
print(copy_command) # 如果你使用的是Python2,需要将这一行的注释去掉。
# print(copy_command)
# 使用os.system()函数执行命令字符串
os.system(copy_command)

上面的代码如果在python2中执行,不将第10行的注释去掉的话,会因为字符串编码和解码的不正确问题,导致系统找不到指定的路径。:

1
2
copy "F:\鍘熸枃浠跺す\*" "F:\鐩爣鏂囦欢澶筡"
系统找不到指定的路径。

经验:我发现了两件事:

第一件事 .DOS 里面,执行下面的命令,有的是对的,有的是错的:

1
2
3
4
5
6
7
8
9
# Succesfull
copy "F:\原文件夹\*" "F:\目标文件夹\"
# Succesfull
copy "F:\原文件夹\\*" "F:\目标文件夹\\"

# error
copy "F:/原文件夹/*" "F:/目标文件夹/"
# error
copy "F://原文件夹//*" "F://目标文件夹//"

总结:

  1. \是一个特殊字符,它不能再字符串中正常的显示,如果必须显示,就这样写:\\
  2. DOS 命令里面指定文件路径时,只能使用\,不能使用/// ,使用这两个都是错的,都会导致 DOS找不到指定的文件路径
  3. DOS 命令里面,指定文件路径的 \ ,你写成 \\ 或者 \\\ 或者 \\\\\\ … 对是可以正常执行的,不会出现错误。

第二件事 . 同时,我发现:

python 的字符串前面加上r,说明这个字符串是raw string,即无需转义的字符串,意思就是这个字符串里面有什么就是什么。

但是我发现了python的一个bug:

1
2
3
# error
str = r'D:\WorkSpace\test_ws\'
# 经验:就算是在字符串前面加上了 r ,字符串最后一个字符也不能是 /
1
2
3
4
# succes
str = r'D:\WorkSpace\test_ws\\'
print(str)
# 输出:D:\WorkSpace\test_ws\\
1
2
3
4
# succes,但是不是我们要的结果
str = 'D:\WorkSpace\test_ws\\'
print(str)
# 输出:D:\WorkSpace   est_ws\

Learning Python 021 创建文件夹、创建文件


  • 使用的电脑系统:Windows 10 64位
  • 使用的开发集成环境:PyCharm 2016.1.4
  • 使用的Python的版本:python 2.7.10 和 python 3.5.0

本篇博客对 Python2 和 Python3 都适用。

Python 创建文件夹

参考网站:


1
2
3
4
5
6
7
8
# -*- coding: utf-8 -*-

import os

folder_name = '2016-11-27-demo'
root_directory = 'D:/WorkSpace/test_ws/'

os.mkdir(root_directory+folder_name)

注意:如果想要创建的文件夹是已经存在的,那么执行上面的程序会出现下面的错误:FileExistsError: [WinError 183] 当文件已存在时,无法创建该文件。

所以这段代码容易出现错误:如果文件夹已存在或者文件夹名中有不允许使用的字符时,os.mkdir()函数都会执行失败。所以,这段代码需要进行异常处理:

参考网站:Python 异常处理

1
2
3
4
try:
    os.mkdir(root_directory+folder_name)
except OSError:
    pass

这样,在运行程序的时候就不会再出现错误了。但是当你给定的文件名中有非法字符时,创建文件夹是不会成功的,但是程序不会报错。

Python 创建文件

参考网站:Python文件处理 open()

比如你想在F:\根目录里面创建一个名为 data.txt 文件,你可以这样做:

1
2
file_path = r'F:\data.txt'
file = open(file_path, 'w')

第二个参数 'w' 也可以写成:'wt'。它们等价。

或者

如果你想创建以指定编码的文件,请参考这篇博客:写文件时,将其用指定的编码方式保存(比如:UTF-8无BOM编码方式)

Learning Python 020 Pass 的用法


  • 使用的电脑系统:Windows 10 64位
  • 使用的开发集成环境:PyCharm 2016.1.4
  • 使用的Python的版本:python 2.7.10 和 python 3.5.0

pass 的用法

参考网站:Python pass 语句

Python2 和 Python3 中 pass 的用法都是一样的。

pass 就是一个空语句,没有任何实际意义,作用是保存程序结构的完整性。

因为Python不像C/C++语言那样,定义一个代码块使用 {}。Python是使用缩进的形式来表述一个代码块的。

比如说想C语言里面的下面这段代码,如果换成Python,怎么写呢?

1
2
while(1){
}

换成Python,这样写:

1
2
while True:
  pass

Learning Python 019 生成器(Generators)和 Yield


  • 使用的电脑系统:Windows 10 64位
  • 使用的开发集成环境:PyCharm 2016.1.4
  • 使用的Python的版本:python 2.7.10 和 python 3.5.0

知识点:生成器

生成器只能用于迭代操作。

一个函数,其中带 yield 关键字的代码,它不会执行,只是记下有这个操作;其他代码正常的执行。而被记下的这些操作会像队列一样存起来,这个“队列”就是 生成器,并且会类似于return一样返回。

一个函数的代码里面有 yield 关键字,那么这个函数就是一个制造生成器的函数

生成器是Python中的高级特性。我之前学习过,还写了一个博客:Learning Python 011 高级特性 2


Python3 例子

1
2
3
4
5
>>> def f():
...     yield 1
...     yield 2
...     yield 3
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
>>> g = f()
>>> g
<generator object f at 0x0000023B63151258>
>>> type(g)
<class 'generator'>
>>> next(g)
1
>>> next(g)
2
>>> next(g)
3
>>> next(g)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>> list(g)
[]
>>> g = f()
>>> list(g)
[1, 2, 3]
>>> list(g)
[]
>>>

1
2
3
4
5
6
7
8
9
10
>>> def counter(num):
...     print('Run to the ' + str(num) + ' yield')
...
>>> def f():
...     print('start!')
...     yield counter(1)
...     yield counter(2)
...     yield counter(3)
...     print('Done!')
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
>>> g = f()
>>> g
<generator object f at 0x000001D4843E1258>
>>> next(g)
start!
Run to the 1 yield
>>> next(g)
Run to the 2 yield
>>> next(g)
Run to the 3 yield
>>> next(g)
Done!
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>> list(g)
[]
>>> g = f()
>>> list(g)
start!
Run to the 1 yield
Run to the 2 yield
Run to the 3 yield
Done!
[None, None, None]
>>>

Python2 实例

生成器在 python2 的用法和在python3中的用法一样,唯一的区别是:

  • python2 中 可以使用next(g) 或者 g.next()。 这样两个等价
  • python3 中 只有next(g),没有g.next()

参考网站:生成器

Learning Python 018 Python2 和 Python3 中 Range()函数的使用


  • 使用的电脑系统:Windows 10 64位
  • 使用的开发集成环境:PyCharm 2016.1.4
  • 使用的Python的版本:python 2.7.10 和 python 3.5.0

range() 函数

  • Python2中:用来创建一个列表(list)。
  • Python3中:用来创建一个可以生成list或者tuple的生成器。

Python2 range()函数 知识点

Python2 中的range() 函数可以生成一个list。(分配内存空间)

1
2
3
4
a = range(10)
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
b = range(4,10)
# [4, 5, 6, 7, 8, 9]

Python2 中的xrange()函数不是生成一个list,而是生成一个生成器,不分配内存。

1
2
3
4
5
6
a = xrange(10)
# xrange(10)
b = list(xrange(10))
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
c = tuple(xrange(10))
# (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

Python3 range()函数 知识点


1
2
a = range(10)
# range(0, 10)

输出:(打印出来的不是一个列表,而是一个生成器)。

Python3 选择这样做的原因:可以节约内存空间,详情请参考这篇博客:Python2和Python3的内存释放

Python3中的range()函数的功能和Python2中的xrange()函数一样,所以在Python3中没有xrange()函数。


要想生成list或者tuple,这样做:

1
2
3
4
5
6
7
8
9
a = list(range(10))
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
b = list(range(4,10))
# [4, 5, 6, 7, 8, 9]

a = tuple(range(10))
# (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
b = tuple(range(4,10))
# (4, 5, 6, 7, 8, 9)

range()函数的使用

下面这段代码在Python2 和 Python3中得到的运行结果都是一样的。

1
2
for i in range(10):
    print(i)

输出:

1
2
3
4
5
6
7
8
9
10
0
1
2
3
4
5
6
7
8
9

运行结果是一样的,但是运行的原理不同:

  • Python2:在第一次执行 range(10),就生成了一个[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]列表。
  • Python3:在每次执行range(10)时,生成一个元素i

Learning Python 017 — Python2 和 Python3 的内存释放


  • 使用的电脑系统:Windows 10 64位
  • 使用的开发集成环境:PyCharm 2016.1.4
  • 使用的Python的版本:python 2.7.10 和 python 3.5.0

学习Python的内存释放知识点的动机

之前我学过很多Python的程序,偶然的一次,我打开任务管理器,看到我写的程序,运行时占用了大量的内存,所以,我希望学会如何释放内存,来优化我的程序,也不给电脑照成太大的负担,所以,我想学会:Python的内存释放这个知识点。


参考网站: gc模块–Python内存释放

下面写几个实验程序,里面都是使用range() 函数来分配内存空间的。range()函数的详细介绍,请见这篇博客:range()函数在python2 和 python3中的使用介绍

Python2 内存释放

未优化前的代码:

1
2
3
a = range(1000*10000)
while True:
  pass

Alt text


优化内存的代码:

使用手动释放内存的方法来优化内存。

1
2
3
4
5
6
import gc
a = range(1000*10000)
del a
gc.collect()
while True:
  pass

可以看出,占用的内存空间明显减小了。

Alt text


既优化了内存,也优化了CPU 的代码

使用睡眠来优化CPU运行。

1
2
3
4
5
6
7
8
9
import gc
import time

a = range(1000*10000)
del a
gc.collect()
while True:
  time.sleep(1.0)
  pass

Alt text


Python3 内存释放

未优化前的代码:

1
2
3
a = range(1000*10000)
while True:
  pass

使用Python3库运行未优化的代码,所需要的消耗的内存空间和使用Python2运行优化内存的代码消耗的内存空间 差不多。

Alt text


优化内存的代码:

1
2
3
4
5
6
import gc
a = range(1000*10000)
del a
gc.collect()
while True:
  pass

可以看出,所暂用的内存空间没有任何增减。

Alt text


既优化了内存,也优化了CPU 的代码:

1
2
3
4
5
6
7
8
9
import gc
import time

a = range(1000*10000)
del a
gc.collect()
while True:
  time.sleep(1.0)
  pass

Alt text


总结

Python3 真的是比 Python2 更加的完善了,从这一点上也可以看出来,Python语言是第4代语言里面非常杰出的语言。随着它的不断发展,它会运行速度慢和内存消耗大的缺点会慢慢的消失(因为:许多Python内置库是用C语言写的)。我看好Python。

Learning Python 016 写文件时,将其用指定的编码方式保存(比如:UTF-8无BOM编码方式)


  • 使用的电脑系统:Windows 10 64位
  • 使用的开发集成环境:PyCharm 2016.1.4
  • 使用的Python的版本:python 3.5.0

学习这个知识点的原因

举一个实例:

Octopress站点路径里面博文文件(.markdown后缀文件)必须要是以UTF-8无BOM编码方式编码的文件,否则执行rake generate命令会出现下面这个错误:

Alt text

1
2
Error reading file F:/octopress/source/_posts/xxxx.markdown: invalid byte sequence in UTF-8
  Liquid Exception: invalid byte sequence in UTF-8 in _posts/xxxx.markdown/#excerpt

所以,为了解决不要出现这个问题,我们需要将文件指定你希望的编码方式保存。

将其用指定的编码方式保存(比如:UTF-8无BOM编码方式)

其实很简单,我们只需要这样做:

1
file = open(file_path, 'w', encoding='utf-8')

这样file文件就是以Utf-8无BOM编码方式编码的文件。

我们也看到了,其实不是将file保存为以Utf-8无BOM编码方式编码的文件,而是创建这个一个以Utf-8无BOM编码方式编码的文件 file

Learning Python 015 解决问题:读取文件时,出现乱码或者“UnicodeDecodeError 'Gbk' Codec Can't Decode Byte 0xXX in Position XX: Incomplete Multibyte Sequence” 错误


  • 使用的电脑系统:Windows 10 64位
  • 使用的开发集成环境:PyCharm 2016.1.4
  • 使用的Python的版本:python 3.5.0

出现的错误

读取文件时,出现乱码或者UnicodeDecodeError: 'gbk' codec can't decode byte 0xXX in position XX: incomplete multibyte sequence 错误


出现错误的原因

这两个错误可能会出现一个,两个错误的出现的原因是一样的:当我们使用了一个不正确的编码方式去读取一个不是用这个编码方式编码的文件时,轻者出现乱码,重者出现UnicodeDecodeError错误。


模拟错误发生现场

1
2
3
4
5
6
file = open('newfile.txt', 'w', encoding='utf-8')
file.write('你好,AoboSir.')
file.close()
file = open('newfile.txt', 'r')
print(file.read())
file.close()

运行输出:

1
浣犲ソ锛孉oboSir.

1
2
3
4
5
6
file = open('newfile.txt', 'w', encoding='utf-8')
file.write('你好,AoboSir。')
file.close()
file = open('newfile.txt', 'r')
print(file.read())
file.close()

运行输出:

1
2
3
4
Traceback (most recent call last):
  File "D:/WorkSpace/test_ws/demo/learning_python_15.py", line 6, in <module>
    print(file.read())
UnicodeDecodeError: 'gbk' codec can't decode byte 0x82 in position 35: incomplete multibyte sequence

解决办法

读取文件时,指定正确的编码方式:

1
file = open('newfile.txt', 'r', encoding='utf-8')

现在再运行,就正常了:

1
你好,AoboSir

搞定