孔天逸'Blog

人間って、不自由な生き物ね。


  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

Python学习笔记(四)——报错记录

发表于 2016-07-04 | 分类于 Python |

用Sublime搭建了Python的开发环境,粘来了一段Python代码,
发现各种报错,都是一些格式控制方面的问题,记录如下:

  • [W] PEP 8(E225):missing whitespace around operator
    在运算符的两边缺少空格
  • [W] PEP 8(E501):line too long(150>79 characters)
    一行代码过长
  • [W] PEP 8(E131):continue line unaligned for hanging indent
    缩进不对
  • [V] PEP 8(W291):trailing whitespace
    多余的空格
  • [W] PEP 8(E231):missing whitespace after ':'
    冒号后缺少空格
  • [E] unexpected indent
    缩进不对
  • [W] PEP 8(E101):indentation contains mixed spaces and tabs
    空格和制表符混用
  • [V] PEP 8(W191):indentation contains tabs
    缩进包含制表符
  • [W] PEP 8(E231):missing whitespace after ','
    逗号后缺少空格
  • [W] PEP 8(E227):missing whitespace around bitwise or shift operator
    位运算符或移位运算符两边缺少空格

Python学习笔记(三)——基础知识

发表于 2016-06-30 | 分类于 Python |

学习来源

本笔记的学习资源是慕课网。

注释

Python的注释以#开头,不同于C/C++/JAVA中的双斜杠,例如:

1
print 'hello world'  #我是注释

变量

  • 命名规范:变量名必须是大小写英文、数字和下划线(_)的组合,且不能用数字开头。
  • 不必声明变量类型,等号=是赋值语句,可以把任意数据类型赋值给变量,同一个变量可以反复赋值,而且可以是不同类型的变量,例如:

    1
    2
    3
    4
    a = 123    # a是整数
    print a
    a = 'imooc' # a变为字符串
    print a

这种变量本身类型不固定的语言称之为动态语言,与之对应的是静态语言。

多行字符串

用'''...'''表示:

1
2
3
'''Line 1
Line 2
Line 3'''

raw字符串

如果一个字符串包含很多需要转义的字符,对每一个字符都进行转义会很麻烦。为了避免这种情况,我们可以在字符串前面加个前缀 r ,表示这是一个 raw 字符串,里面的字符就不需要转义了。例如:

1
r'\(~_~)/ \(~_~)/'

还可以在多行字符串前面添加 r ,把这个多行字符串也变成一个raw字符串:

1
2
3
r'''Python is created by "Guido".
It is free and easy to learn.
Let's start learn Python in imooc!'''

unicode字符串

以Unicode表示的字符串用u’…’表示,比如:

1
2
print u'中文'
中文

注意:

  • 历史原因, 不加 u 为ASCII编码,中文不能正常显示。
  • Unicode字符串除了多了一个 u 之外,与普通字符串没啥区别,转义字符和多行表示法仍然有效。
  • 如果中文字符串在Python环境下遇到 UnicodeDecodeError,这是因为.py文件保存的格式有问题。可以在第一行添加注释

    1
    # -*- coding: utf-8 -*-

    目的是告诉Python解释器,用UTF-8编码读取源代码。然后用编辑器另存为… 并选择UTF-8格式保存。

运算

与C语言相同,整形与整形运算结果还是整形,但是整形与浮点型混合运算结果为浮点型。

Python学习笔记(二)——数据类型和print语句

发表于 2016-06-30 | 分类于 Python |

学习来源

本笔记的学习资源是慕课网。

数据类型

计算机顾名思义就是可以做数学计算的机器,因此,计算机程序理所当然地可以处理各种数值。但是,计算机能处理的远不止数值,还可以处理文本、图形、音频、视频
等各种各样的数据,不同的数据,需要定义不同的数据类型。在Python中,能够直接处理的数据类型有以下几种:

一、整数

Python可以处理任意大小的整数,当然包括负整数,在Python程序中,整数的表示方法和数学上的写法一模一样,例如:1,100,-8080,0,等等。
计算机由于使用二进制,所以,有时候用十六进制表示整数比较方便,十六进制用0x前缀和0-9,a-f表示,例如:0xff00,0xa5b4c3d2,等等。

二、浮点数

浮点数也就是小数,之所以称为浮点数,是因为按照科学记数法表示时,一个浮点数的小数点位置是可变的,比如,1.23x10^9和12.3x10^8是相等的。浮点数可以用数学写法,如1.23,3.14,-9.01等等。但是对于很大或很小的浮点数,就必须用科学计数法表示,把10用e替代,1.23x10^9就是1.23e9,或者12.3e8,0.000012可以写成1.2e-5,等等。

整数和浮点数在计算机内部存储的方式是不同的,整数运算永远是精确的(除法难道也是精确的?是的!),而浮点数运算则可能会有四舍五入的误差。

三、字符串

字符串是以’’或””括起来的任意文本,比如'abc',"xyz"等等。请注意,’’或””本身只是一种表示方式,不是字符串的一部分,因此,字符串'abc'只有a,b,c这3个字符。

四、布尔值

布尔值和布尔代数的表示完全一致,一个布尔值只有True、False两种值,要么是True,要么是False,在Python中,可以直接用True、False表示布尔值(请注意大小写),也可以通过布尔运算计算出来。

布尔值可以用and、or和not运算。

and运算是与运算,只有所有都为 True,and运算结果才是 True。

or运算是或运算,只要其中有一个为 True,or 运算结果就是 True。

not运算是非运算,它是一个单目运算符,把 True 变成 False,False 变成 True。

五、空值

空值是Python里一个特殊的值,用None表示。None不能理解为0,因为0是有意义的,而None是一个特殊的空值。

六、print语句

print语句可以向屏幕上输出指定的文字。比如输出’hello, world’,用代码实现如下:

1
print 'hello, world'

注意:

  • 当我们在Python交互式环境下编写代码时,>>>是Python解释器的提示符,不是代码的一部分。

  • 当我们在文本编辑器中编写代码时,千万不要自己添加 >>>。

print语句也可以跟上多个字符串,用逗号“,”隔开,就可以连成一串输出:

1
2
print 'The quick brown fox', 'jumps over', 'the lazy dog'
The quick brown fox jumps over the lazy dog

print会依次打印每个字符串,遇到逗号“,”会输出一个空格。

print也可以打印整数,或者计算结果:

1
2
3
4
>>>print 300
300 #运行结果
>>>print 100 + 200
300 #运行结果

因此,我们可以把计算100 + 200的结果打印得更漂亮一点:

1
2
print '100 + 200 =', 100 + 200
100 + 200 = 300 #运行结果

注意: 对于100 + 200,Python解释器自动计算出结果300,但是,’100 + 200 =’是字符串而非数学公式,Python把它视为字符串。

Python学习笔记(一)——初识Python

发表于 2016-06-30 | 分类于 Python |

学习来源

本笔记的学习资源是慕课网。

Python起源

龟叔Guido van Rossum(荷兰)于1989年为了打发无聊的圣诞节而开发的编程语言。

Python的特点

  • 优雅
  • 明确
  • 简单

Python适合的领域

  • Web网站和各种网络服务
  • 系统工具和脚本
  • 作为“胶水”语言把其他语言开发的模块包装起来方便使用

Python不适合的领域

  • 贴近硬件的代码(首选C)
  • 移动开发:IOS/Android有各自的开发语言(Objc,Swift、java)
  • 游戏开发:C/C++(需高速渲染)

Python和其他语言对比

语言 类型 运行速度 代码量
C 编译为机器码 非常快 非常多
Java 编译为字节码 快 多
Python 解释执行 慢 少
  • 缺点一:速度慢
  • 缺点二:源码不能加密

Hello World!

在命令行中输入python,进入python编辑器,输入以下代码

1
print 'Hello World!'

成功输出Hello World!
然后输入

1
exit()

退出python编辑器。

PHP实现哈希表和快速排序

发表于 2016-06-28 | 分类于 PHP |

介绍:

本文用PHP封装了一个哈希表结构,通过拉链法解决哈希冲突,封装的快速排序与本哈希表相适应,可通过不同的键值进行排序。

代码如下:

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
<?php
class hashNode{
public $key;
public $val;
public $nextNode;

/**
* Description:构造函数
* @param $key
* @param $value
* @param $nextNode
*/
public function __construct($key,$val,$nextNode=null){
$this->key = $key;
$this->val = $val;
$this->nextNode = $nextNode;
}
}
class hashTable{
private $collection;
public $size = 20;

/**
* Description:初始化哈希表
* @param $size
*/
public function __construct($size=''){
if(is_int($size)){
$bucketsSize = $size;
$this->size = $size;
}else{
$bucketsSize = $this->size;
}
$this->collection = new SplFixedArray($bucketsSize);
}

/**
* Description:哈希算法,生成散列值,作为存储数据的下标
* @param $key
* @return int
*/
private function _hashAlgorithm($key){
$length = strlen($key);
$hashValue = 0;
for($i=0;$i<$length;$i++){
$hashValue += ord($key[$i]);//ord函数获得字符的ASCII码
}
return ($hashValue%($this->size));
}

/**
* Description:在相应的位置存储对应的值
* @param $key
* @param $val
*/
public function set($key,$val){
$index = $this->_hashAlgorithm($key);
if(isset($this->collection[$index])){
$newNode = new hashNode($key,$val,$this->collection[$index]);
}else{
$newNode = new hashNode($key,$val,null);
}
$this->collection[$index] = $newNode;
}

/**
* Description:根据key生成的散列值,找到对应的值
* @param $key
* @return hashNode
*/
public function get($key){
$index = $this->_hashAlgorithm($key);
$current = $this->collection[$index];
while(!empty($current)){
if($current->key == $key){
return $current->val;
}
$current = $current->nextNode;
}
return null;
}

/**
* Description:设置哈希表的大小
* @param $size
*/
public function editSize($size){
$this->size = $size;
$this->collection->setSize($size);
}

/**
* Description:删除某个值,成功返回1,失败返回0
* @param $key
* @return bool
*/
public function del($key)
{
return 0;
}

/**
* Description:判断某个值是否存在,存在则返回1,不存在返回0
* @param $key
* @return bool
*/
public function exist($key){
$index = $this->_hashAlgorithm($key);
$current = $this->collection[$index];
while(!empty($current)){
if($current->key == $key){
return 1;
}
}
return 0;
}

/**
* Description:返回存储元素的个数
* @return int
*/
public function size(){
$size = 0;
$length = $this->size;
for($i=0;$i<$length;$i++){
$current = $this->collection[$i];
while(!empty($current)){
$size++;
$current = $current->nextNode;
}
}
return $size;
}

/**
* Description:列出哈希表内保存的值
* @return SplFixedArray
*/
public function getList(){
return $this->collection;
}

/**
* Description:根据hashTable数组的某一个key进行排序
* @param $hashArr
* @param $key
* @return array:排序后的数组
*/
public static function qsort($hashArr,$key){
//先判断是否需要继续进行
$length = count($hashArr);
if($length <= 1) {
return $hashArr;
}
$base_num = $hashArr[0]; //选择标尺
//遍历 除了标尺外的所有元素,按照大小关系放入两个数组内
$left_array = array();//小于标尺的
$right_array = array();//大于标尺的
for($i=1; $i<$length; $i++) {
if($base_num->get($key) > $hashArr[$i]->get($key)) {
$left_array[] = $hashArr[$i];//放入左边数组
} else {
$right_array[] = $hashArr[$i];//放入右边数组
}
}
/*再分别对左边和右边的数组进行相同的排序处理方式
递归调用这个函数,并记录结果*/
$left_array = self::qsort($left_array,$key);
$right_array = self::qsort($right_array,$key);
//合并左边 标尺 右边

return array_merge($left_array, array($base_num), $right_array);
}
}

后记:

PHP自带的数组array就有哈希表的功能,所以本文其实并没有什么实用价值,但是可以较容易的理解哈希表结构和快速排序算法。至于我为什么要自己封装……课程所逼 = =。

HashSet是如何做到无序的

发表于 2016-05-19 | 分类于 JAVA |

参考资料:

jzhf2012的专栏,这位大神对源码的分析十分详尽,但是也比较长,我在此处总结题目中的问题。

问题引入:

执行如下JAVA程序测试HashSet的存储顺序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package learnCollection;

import java.util.HashSet;
import java.util.Iterator;

public class Main {

public static void main(String[] args) {
HashSet<Character> hs = new HashSet<Character>(11);
hs.add('a');
hs.add('b');
hs.add('1');
hs.add('5');
hs.add('4');
hs.add('e');
System.out.println(hs);//输出hs的元素
Iterator<Character> it = hs.iterator();
while(it.hasNext()){
System.out.print(it.next().hashCode()+" ");//输出各元素的hashCode
}
System.out.println();
}
}

输出结果如下:

1
2
[1, e, b, 5, 4, a]
49 101 98 53 52 97

可见是完全乱序的,就算是从hashCode()可看不出任何规律。

源码分析:

在Eclipse下按住Control键鼠标左键单击add()方法进入HashSet的源码,发现add()方法看似十分简洁:

1
2
3
public boolean add(E e) {
return map.put(e, PRESENT)==null;//将要存储的元素当作键,一个Object对象当作值存入一个HashMap
}

怎么有个map?继续点进put()的源码,发现进入了HashMap的类文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public V put(K key, V value) {
if (table == EMPTY_TABLE) {
inflateTable(threshold);
}
if (key == null)
return putForNullKey(value);//以上代码是边界判断
int hash = hash(key);//获得传入值的哈希值
int i = indexFor(hash, table.length);//获得哈希表中的下标
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}//如果键已经存在,则更新对应值
modCount++;
addEntry(hash, key, value, i);//添加到表中
return null;
}

原来HashSet的存储是基于HashMap的,所以也就不难理解它的乱序了。HashMap通过键值对来存储数据,所以要理解HashSet的乱序,只要分析HashMap的存储方式就OK了,当然,存储方式是哈希表。

其中hash()函数和indexFor()函数都定义在HashMap中,在理解了它们的源码后可以写个测试程序对存储结果进行验证,源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
final int hash(Object k) {
int h = hashSeed;//此常数默认是零,老版本中没有此定义,老版本此函数直接传入k的hashCode
if (0 != h && k instanceof String) {
return sun.misc.Hashing.stringHash32((String) k);
}

h ^= k.hashCode();//0与k.hashCode()进行异或结果还是k.hashCode()

// This function ensures that hashCodes that differ only by
// constant multiples at each bit position have a bounded
// number of collisions (approximately 8 at default load factor).
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);//这两句对h通过移位进行优化,减少哈希值重复
}

static int indexFor(int h, int length) {
// assert Integer.bitCount(length) == 1 : "length must be a non-zero power of 2";
return h & (length-1);//lentgh是HashMap当前的容量,默认为16
}

综合上述分析,可以写个简单的函数对我们的测试结果进行验证,图省事用python脚本写个函数:

1
2
3
4
5
def i(h):
h = h^(h>>20)^(h>>12)
h = h^(h>>7)^(h>>4)
h = h&15
return h

对前面的输出结果进行验证

1
2
[1, e, b, 5, 4, a]
49 101 98 53 52 97

1
2
3
4
5
6
7
8
9
10
11
12
>>> i(49)
2
>>> i(101)
3
>>> i(98)
4
>>> i(53)
6
>>> i(52)
7
>>> i(97)
7

发现通过传入hashCode值得到的下标跟输出的顺序非常符合,两个下标7当然会进行哈希再探测,至此HashSet的无序存储的疑惑就解决了。

2013: Lost connection to MySQL server during query的解决办法

发表于 2016-05-15 | 分类于 MySQL |

修改配置

MySQL有一个默认的配置叫做max_allowed_packet,它的默认值是1M,

当我们导入的SQL文件超过1M,就会出现题目中所说的

[Err] 2013 - Lost connection to MySQL server during query,

所以要导入大型的SQL文件时,要对上述参数进行配置。

在MySQL的配置文件my.ini中的mysqld下添加一行

max_allowed_packet=100M

这样就可以导入小于等于100M的SQL文件了。

不修改

如果不配置的话,实测Navicat for MySQL会出现上述问题,

而MySQL Workbench不会。

1…67
孔天逸

孔天逸

67 日志
18 分类
32 标签
GitHub E-Mail CSDN
© 2016 — 2021 孔天逸
由 Hexo 强力驱动
|
主题 — NexT.Gemini v5.1.4
已有 位大佬知道这儿有个菜鸡了 已被公开处刑 次