鱼C论坛

 找回密码
 立即注册
查看: 26589|回复: 112

[技术交流] [记录贴]每天的问题和解决方法_正确学习方法

[复制链接]
发表于 2015-3-21 14:28:50 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 lightninng 于 2015-6-12 23:01 编辑

欢迎大家参观和指正。话说。我很多时候用的方法好笨~~
写了几天觉得。大家如果有时间,每天晚上抽半个小时写一写今天学到的东西很有用,会记住更多 ~~

_________________________________________________________________________________________________________
ps:最近有好几个鱼油说我记录的东西比较难,其实记录的东西现在集中在这几个部分

1、checkio,借用网上的介绍
CheckIO是一个Python代码游戏网站,用户可以通过编程来解决游戏中的各种任务,还可以与其他开发者玩编程逻辑游戏进行比赛,来交流编程技能、经验。
d44d79f0-4074-3f59-9d2d-1b649cfb8db8.jpg
如果你是一个Python初学者,CheckIO可以让你学习基础知识,并在解决不同任务的过程中获得丰富的实践经验。如果你是一个有经验的程序员,CheckIO为你提供了一个完善自己技能和学习别人经验的很好的机会。
CheckIO官网:http://www.checkio.org/
注册登录后,你将从HOME处开始,通过解决各式各样的任务,进行探索并发现新的岛屿。另外,在CheckIO中,你不仅可以解决现有的任务,还可以发布自己的任务。
2、python cookbook
简单来说,这书的内容显示了python这门语言的语言特点 ,简单,自带的一些库的强大之处,有一些数据结构基础的鱼油看一下,能帮助掌握python的优良特性,用有些人的话说就叫pythonic
3、贴子的前两页有一些论坛中看到的活动或者鱼油分享的有趣问题,我把自己的解决方法记录下来了,其实最近这方面看的都少了(汗颜~~),主要内容集中在1和2中,

要说的话其实每部分内容都是有简有繁,从简单的开始就好
拿checkio来说,home里的前几道都挺简单的,后面就会越来越复杂,到觉得比较吃力的时候离开home去其它的可以开的基地看一看,挑简单的先做,慢慢增强~~

最后,祝所有的鱼油都能学有所成!!!

评分

参与人数 2荣誉 +10 鱼币 +15 贡献 +5 收起 理由
戴宇轩 + 5 + 5 + 2 感谢楼主无私奉献!
~风介~ + 5 + 10 + 3 支持楼主!

查看全部评分

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2015-3-21 14:42:05 | 显示全部楼层
本帖最后由 lightninng 于 2015-3-21 21:22 编辑

昨天晚上看到某版主之前的一个贴子,讲的是迷宫问题,记得当年在学数据结构的时候好像也有(虽然不是重点没怎么好好看),觉得挺有意思,就想花点时间用python写一下,结果竟然用了一个上午,不得不说,好的编程习惯很重要,注释,调试的时候的方法,慢慢积累吧以下是问题
"""
迷宫没有墙壁,但是每条边的路被坑包围。如果一个玩家掉在坑里的话,他们就丢失了。迷宫是用矩阵来表示(含有列表的列表): 1是坑,0的路径的一部分。 迷宫的大小是12×12,外界都是坑。
玩家在点(1,1)开始。出口是在点(10,10)。 你需要找到通过迷宫的路径。 玩家只能通过四个方向移动 南(下 [1,0]),北(上 [-1,0]), 东(右[0,1]),西(左[0,-1])。这条路线被
描述成由不同的字符组成的字符串:“S”=南,“N”=北,“E”=东,和“W”=西。
"""
maze_one = [
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1],
    [1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1],
    [1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1],
    [1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1],
    [1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1],
    [1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1],
    [1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1],
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
]

maze_two = [
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
    [1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1],
    [1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1],
    [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1],
    [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1],
    [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1],
    [1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1],
    [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1],
    [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1],
    [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1],
    [1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1],
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
]

最终的代码是
def search_out(maze_num):
    """寻找走出迷宫的路径并打印"""
    def check(x, y):
        #返回(x, y)周围除来路之外可走的位置组成的列表
        next_pos = []
        for each in [(x, y+1), (x+1, y), (x, y-1), (x-1, y)]:
            if maze_num[each[0]][each[1]] == 0:
                next_pos.append(each)
        return next_pos  # 用于检查i,j点处可行处有几处

    def path_d(path):
        #按位置路线打印每步所走的方向
        dict_dir = {(0, 1): "东", (1, 0): "南", (0, -1): "西", (-1, 0): "北"}
        length = len(path)
        for k in range(length - 1):
            print(dict_dir[(path[k+1][0] - path[k][0], path[k+1][1] - path[k][1])], "->", end = "")
        print(dict_dir[(10 - path[-1][0], 10 - path[-1][1])])

    i = j = 1
    stack_branch = [[(i, j), check(i, j)]]  # 用于记录岔路口
    stack_path = []  # 用于记录走过的路径
    min_path = []
    count = 0
    while stack_branch:
        maze_num[i][j] = 1
        stack_path.append((i, j))
        (i, j) = (stack_branch[-1][1]).pop()
        if len(stack_branch[-1][1]) == 0:
            stack_branch.pop()
        check_dir = []
        while True:
            check_dir = check(i, j)
            if len(check_dir) != 1 or (i, j) == (10, 10):
                break  # 返回上一个路口
            else:
                stack_path.append((i, j))
                maze_num[i][j] = 1
                [(i, j)] = check_dir  # 继续前进
        if len(check_dir) > 1:
            stack_branch.append([(i, j), check_dir])
        else:
            branch_temp = [each[0] for each in stack_branch]
            if (i, j) == (10, 10):
                #下面的代码改为print(stack_path)就可以打印所有可能的路径
                if len(stack_path) < len(min_path) or len(min_path) == 0:
                    min_path = stack_path[:]
            if len(stack_branch) != 0:
                while (i, j) not in branch_temp:
                    (i, j) = stack_path.pop()
                    maze_num[i][j] = 0
                maze_num[i][j] = 0
    path_d(min_path)
由于想实现所有可能的路径所以用了两个栈一个用来存放岔路,一个用来存放当前路径,中间遇到的问题:
1、每次循环结束要保证所处的条件都一致,这里就是当while stack_branch:循环每一次结束时,要求i,j处在岔路点上,且该岔路点并未标记为已走过
2、在列表拷贝时,min_path = stack_path和min_path =stack_path[:]的区别,用前者时当stack_path改变,min_path也会改变,导致最后stack_path.pop()报错,另外在查这个问题时看到后一种写法当stack_path内元素有列表时,min_path内部的列表会随stack_path内的列表而改变:如
>>> a=[1,[2]]
>>> b=a[:]
>>> b
[1, [2]]
>>> a[1].append(3)
>>> a
[1, [2, 3]]
>>> b
[1, [2, 3]]
解决方法是用copy模块中的deepcopy函数,如下
>>> import copy
>>> a=[1,[2]]
>>> b=copy.deepcopy(a)
>>> b
[1, [2]]
>>> a[1].append(3)
>>> a
[1, [2, 3]]
>>> b
[1, [2]]

-*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--

比较懒,刚看到了[checkio]---找到出现频率最高的字母---这个贴子,自己只是大概想了下没有去实现 ,不过大神的方法记录下,以后说不定有用~~
import string​
def checkio(text):
    text = text.lower()
    return max(string.ascii_lowercase, key=text.count)
key参数:将前面序列中的每个元素带入key参数指向的函数,将返回值最大的那个元素return~~有点绕


-*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--
在用pycharm调试时如果注释或者程序中有中文里要在代码头部加上# -*- coding: utf-8 -*-,不然编译时会出现错误

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-3-22 21:16:06 | 显示全部楼层
本帖最后由 lightninng 于 2015-3-22 23:02 编辑

今天基本上算是休息的比较多,就早上玩了会checkio
检查到了一个Non-unique Elements问题的一个逻辑错误,还是在想过程的时候中间有纰漏你将得到一个含有整数(X)的非空列表。在这个任务里,你应该返回在此列表中的非唯一元素的列表。要做到这一点,你需要删除所有独特的元素(这是包含在一个给定的列表只有一次的元素)。0 < |X| < 1000
from collections import Counter


def checkio(unsolved_list):
    length = len(unsolved_list)
    i = 0
    c = Counter(unsolved_list)
    while i < length:
        if unsolved_list[i] in [key for (key, value) in c.items() if value == 1]:
            unsolved_list.pop(i)
            length -= 1
        else:  # 之前由于这里少了else:导致每次进入if循环之后,i依然后移,少处理一个元
            i += 1
    return unsolved_list

-*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--
然后是中位数问题
中位数是一个可将数值集合划分为相等的上下两部分的一个数值。如果列表数据的个数是奇数,则列表中间那个数据就是列表数据的中位数;如果列表数据的个数是偶数,则列表中间那2个数据的算术平均值就是列表数据的中位数。在这个任务里,你将得到一个含有自然数的非空数组(X)。你必须把它分成上下两部分,找到中位数。
输入: 一个作为数组的整数(int)列表(list)的。
输出: 数组的中位数(int, float).
前提:
1 < len(data) ≤ 1000
all(0 ≤ x < 10 ** 6 for x in data)
def checkio(data):
    length = len(data)
    data.sort()
    if length % 2:
        return data[length//2]
    else:
        return (data[length//2] + data[length//2 - 1])/2
看到一个有意思的把这里的if判断语句换成这样
return (data[length >> 1] + data[(length - 1)>>1])/2
>>2进制向右移一位。在这里length>>1与length//2效果是一样的这样的话疯狂的同学应该就可以把这个代码换成一行了,代价是运行效率会低一些
def checkio(data):
    return (sorted(data)[len(data) >> 1] + sorted(data)[(len(data) - 1)>>1])/2
-*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--

House Passoword问题
斯蒂芬和索菲亚对于一切都使用简单的密码,忘记了安全性。请你帮助尼古拉开发一个密码安全检查模块。如果密码的长度大于或等于10个符号,至少有一个数字,一个大写字母和一个小写字母,该密码将被视为足够强大。密码只包含ASCII拉丁字母或数字。
输入: 密码 (str, unicode)。
输出: 密码的安全与否,作为布尔值(bool),或者任何可以转换和处理为布尔值的数据类型。你会在结果看到转换后的结果(True 或 False)。
def checkio(data):
    # return len(data) >= 10 and any(i.isdigit() for i in data) and any(i.isupper() for i in data) \
       and any(i.islower() for i in data)
    # return not (len(data) < 10 or data.islower() or data.isupper() or data.isalpha() \ 
        or data.isnumeric())
    if len(data) > 9:
        for each in data:
            if each.islower():
                flag_low = 1
            elif each.isupper():
                flag_high = 1
            elif each.isdigit():
                flag_num = 1
    return flag_low and flag_high and flag_num
后面每次看到的一句话版都放在第一行的注释,在密码不长的情况下效率没有区别,一句话版更简洁明了,python还是博大精深


any(iterable):如果iterable的某一元素不为0、''、False、且iterable不为空,刚返回True
all(iterable):如果iterable的所有元素不为0、''、False、且iterable不为空,则返回True
很有用的两个函数
第二种一句话方法展现了强大的逻辑思维能力~~








想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-3-22 21:43:12 | 显示全部楼层
专门开一贴热烈庆祝升级


心情舒畅~
可以加好友啦
可以发短消息啦
关键可以发悬赏啦
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-3-23 13:29:33 | 显示全部楼层

一起学习吧亲。欢迎指正~
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-3-23 22:09:48 | 显示全部楼层
本帖最后由 lightninng 于 2015-6-5 10:22 编辑

今天下午兼职,只有上午学了一会会,主要是想了一些关于论文中数据处理的问题,虽然觉得应该用数据库,但是数据量不算特别大,再加上数据库还要学好久,所以先用字典凑合
在字典中存放数据为,{用户:对应的行为数据集},在读到一条新的行为数据时:如果是新用户就加入字典中,并将该行为数据做为初始值;如果是已有用户就用这条行为数据更新行为数据集
if dic.setdefault(用户, 行为数据初始值) != 行为数据初始值:
    更新行为数据集
另外一种方法是用try捕获KeyError然后做相应的处理
try:
    更新行为数据集
except KeyError:
    dic[用户] = 行为数据初始值
2015.6.5:经过一段时间的学习,偶然又看到这一贴,其实这个问题可以用python cookbook中提到的defaultdict类来实现
from collections import defaultdict

d = defaultdict(list)
d['a'].append(1)
d['a'].append(2)
d['b'].append(4)

d = defaultdict(set)
d['a'].add(1)
d['a'].add(2)
d['b'].add(4)
不用判断是否有该键,而可以直接调用append方法,若键不存在,defaultdict会为你自动 创建该键~
-*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--


晚上看到一个坛友提的问题,把下面这个列表中所有元素出现的次数和位置统计出来,
a = [[1, 2, 7, 6], [2, 3, 8, 7], [3, 4, 9, 8], [4, 5, 10, 9], [6, 7, 12, 11], 
[7, 8, 13, 12], [8, 9, 14, 13], [9, 10, 15, 14], [11, 12, 17, 16], 
[12, 13, 18, 17], [13, 14, 19, 18], [14, 15, 20, 19], [16, 17, 22, 21],
[17, 18, 23, 22], [18, 19, 24, 23], [19, 20, 25, 24]]
正好用到了早上想到的,就顺手实现了
def fun(a):
    dic = {} # 用字典存放出现的数字和它出现的位置{数字:{位置的集合set}}
    for i in range(len(a)):
        for j in range(len(a[i])):
            dic.setdefault(a[i][j], {(i, j)})  # 若出现新的数字就把它加入字典,并设置位置集合为仅包含当前位置的集合
            dic[a[i][j]].add((i, j))  # 把新的位置加入相应的集合中
    for each_item in dic.items():
        print(str(each_item[0]) + ":" + str(len(each_item[1])) + " " + str(list(each_item[1])))  
  # 输出为    数字:出现的次数    位置集合
另外 使用print函数时不小时将int 和str变量相加报错,可以用逗号隔开,但是会留下一个空格,再就是可以用格式化字符串,当时做的时候没想到这么多,写这个贴子的时候想到了,充分说明记录自己每天的工作还是有用的
-*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--

顺带抱怨一下,兼职好累,虽然活比较轻松,但是出去跑一下就是不一样,我难道老了么~~~
咪了一会又做了一关checkio意外 的挺带感 ,我的渣英语 ~~
"""
判断相邻的格子里是否有棋子,5*5的元组组,0表示没该位置没棋子,1表示有,判断一个格子周围8个相邻格子里一共有几个棋子
输入:5*5的元组组,一个行坐标,一个列坐标
输出:相邻的格子中的棋子数
count_neighbours(((1, 0, 0, 1, 0),
                  (0, 1, 0, 0, 0),
                  (0, 0, 1, 0, 1),
                  (1, 0, 0, 0, 0),
                  (0, 0, 1, 0, 0),), 1, 2) == 3
count_neighbours(((1, 0, 0, 1, 0),
                  (0, 1, 0, 0, 0),
                  (0, 0, 1, 0, 1),
                  (1, 0, 0, 0, 0),
                  (0, 0, 1, 0, 0),), 0, 0) == 1
"""

                               
登录/注册后可看大图

def count_neighbours(grad, row, col):
    neighbour = [(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)]
    count = 0
    for (x, y) in neighbour:
        try:
            if row + x >= 0 and col + y >= 0 and grad[row + x][col + y] == 1:
                count += 1
        except:
            pass
    return count
还没有看大神的解法,累了,明天再学习大神,自己做这个的时候出了一些问题
1、傻逼的把if 语言中grad后面的参数写成了[row + x][row + x],错误虽小,不过以后工作的话这种错误会害死人~~
2、越界判断的时候没有考虑到python中是有负数索引的,try机制只能解决越上界的问题,所以if语句后面加上了对row + x和row + y是否为正的判断,那么既然要判断干脆就抛弃try好了,将for循环内的语句换为

if 0 <= (row + x) < len(grad) and 0 <= (col + y) < len(grad) and grad[row + x][col + y] == 1:
            count += 1





想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-3-24 22:59:12 | 显示全部楼层
本帖最后由 lightninng 于 2015-4-1 12:16 编辑

今天依然兼职,上午做了论文相关的东西,由于不用数据库要处理的数据像数据库的表一样分别存放在几个不同的txt文件中,每个文件是一个字典对象,不得不说python确实很强大,pickle模块中的dump方法和load方法可以直接存储和读取对象,但是自己遇到一个问题,当多次调用dump将多个对象顺序存入文件中之后,怎么能方便的将其按顺序load出来,对于普通的txt文件,可以直接用类似for each in fp:这样的语句读取每行数据,但dump的数据不能用这种方法依次获得,不知道有没有什么方法可以作到类似的效果,在网上没查到,最后自己用while循环时发现读到最后一个会引发EOFERROR,于是想到用try-except语句来捕获它完成break,代码如下
with open("1.txt", "wb") as fp:
        while True:
            try:
                temp_list = pickle.load(fp)
                # 对读取的temp_list作相应的操作
            except EOFError:  # 捕获EOFError并跳出循环
                break
            except:  # 其它异常打印other error跳出循环,但是非正常结束
                print("other error")
                break
这里的两个except语句中不论如何必须加入break,不然有可能进入死循环(自己很悲剧的检查了好久~)

-*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--


在去兼职的路上看了看,坛友分享的一个python教程,写的很细致,学到了一些东西,函数里这关于参数检查问题感觉自己可以用上,记录一下http://www.liaoxuefeng.com/wiki/ ... 8f31bdc4db5f6498000,函数开始的部分加入类似这样的代码
if not isinstance(x, (int, float)):  # 传入参数为x,要求为int或float变量
        raise TypeError('bad operand type')  #这里的字符串可以自己定义 
自己的函数中可以加上这样的部分
-*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--
昨天的棋盘问题 的checkio没有学习大神的方法,今天补上
def count_neighbours(grid, row, col, coords=(-1, 0, 1)):
    return sum(grid[row+j][col+i] for i in coords for j in coords if (i or j) and 
               0 <= col+i < len(grid[0]) and 0 <= row+j < len(grid))
1、丧心病狂的为了省一行代码加了一个默认参数coords,其实就是把coords=(-1, 0, 1)这个代码加到参数里了而已~~
2、学了到二层列表每个元素的新的引用方法,列表的推导中for是可以连用的,例如for each in [list[j] for i in range(len(list)) for j in range(len(list))]
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-3-25 20:45:45 | 显示全部楼层
本帖最后由 lightninng 于 2015-5-1 10:09 编辑

早上把所有的数据分别放在了几个不同的文件中,大多数的数据都是用字典的形式,由于自己最开始是学c的,而且考研的时候学了数据结构,对于效率还是有点在意的,之前一直在想关于字典的效率问题,想起了在廖雪峰的python教程中关于字典的说法,字典是一种用空间换时间的做法,将关键字按顺序排好,以提高查找的效率,比如顺序表的二分查找法,这也解释了为什么字典中key的顺序和输入的顺序不同



-*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--


晚上倒腾了一晚上的科学计算模块的东西,python的版本、系统的32和64位的差别、让python的模块下载复杂的不行,我安装的主要模块是4个
Scipy:科学和工程计算工
Python Image Library:python图形处理库
Numpy:高阶大量的矩阵运算
Matplotlib一个Python的图形框架,用来绘制图表
PIL现在还不支持python3,所以用pillow代替,至于两者代替产生的问题看这个贴子http://www.douban.com/group/topic/37715851/
这几个工具中matplotlib找到了相应的64位python3.3的安装包,其它的不小心安了32位的,导致无法使用(什么不是有效的win32程序啥 的)
经过一晚上的折腾,python模块安装方法如下
1、安装easy_install,到这里https://pypi.python.org/pypi/setuptools找一个ez_setup.py的文件下载下来,然后运行
2、运行cmd,输入easy_install pip,安装pip模块
3、到该网站http://www.lfd.uci.edu/~gohlke/pythonlibs/下载你所需要的模块的
对应版本和系统的whl文件,比如 我的就是64位系统,python3.3
4、运行cmd 输入pip whl文件路径,安装该模块
5、运行idle输入import 模块名,检查相应模块是否安装正确,若报错说缺少某某模块,刚运行cmd 输入easy_inatall 模块名


-*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--


看科学计算的书的时候学到的
sys.argv[]是用来获取命令行参数的,sys.argv[0]表示代码本身文件路径,所以参数从1开始
code.py arg1 arg2  # 如你的代码是code.py那么在命令行下输入该命令
["code.py", "arg1", "arg2"]  # sys.arg列表内容为



想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-3-27 00:17:16 | 显示全部楼层
本帖最后由 lightninng 于 2015-3-27 09:29 编辑

今天主要是研究了昨天装的numpy,scipy,matplotlib教材是ivan ldris写的两本,《NumPy攻略:Python科学计算与数据分析》和《python数据分析基础教程:NumPy学习指南》,两本书网上应该都能找到pdf版,我借的学校的
两本书都是基于python2.7的,试了一下这段代码
# -*- coding: utf-8 -*-
import scipy.misc
import sys
import matplotlib.pyplot
import numpy.testing

# 这个脚本用来调整Scipy库中图像Lena的大小

#if len(sys.argv) != 3:
#    print("Usage python %s yfactor xfactor" % (sys.argv[0]))
#    sys.exit()

# 加载图像Lena到一个数组中
lena = scipy.misc.lena()
# 图像lena的规格
LENA_X = 512
LENA_Y = 512
# 检查LENA数组的形状
numpy.testing.assert_equal((LENA_X, LENA_Y), lena.shape)

#获取调整系数
yfactor = 1  # float(sys.argv[1])
xfactor = 2  # float(sys.argv[2])

# 调整数组lena的大小
resized = lena.repeat(yfactor, axis=0).repeat(xfactor, axis=1)

# 检查大小后调整数组的形状
numpy.testing.assert_equal((yfactor * LENA_Y, xfactor * LENA_X), resized.shape)

# 绘制数组lena
matplotlib.pyplot.subplot(211)
matplotlib.pyplot.imshow(lena)

# 绘制大小调整后的数组
matplotlib.pyplot.subplot(212)
matplotlib.pyplot.imshow(resized)
matplotlib.pyplot.show()
matplotlib.pyplot.savefig("1.jpg")
除了刚开始由于 argv的问题之外,没有别的问题,看来python2.7和3.3很多代码是可以兼容的,明天搜一下需要注意的问题由于是在pycharm里运行,于是将传入参数中关于argv的代码注释掉了,而是直接给xfactor,yfactor赋值得到图像 QQ截图20150327001429.jpg
数据处理依然无进展,明天研究pca算法~
进展缓慢,拙计~

在Python中定义函数,可以用必选参数、默认参数、可变参数和关键字参数,这4种参数都可以一起使用,或者只用其中某些,但是请注意,参数定义的顺序必须是:必选参数、默认参数、可变参数和关键字参数。
可变参数:定义为参数前带一个*,也就是甲鱼说的收集参数,python在处理时将参数作为一个tuple传入,也可将已有的tuple或者list前加上*传入函数作为可变参数,如
def test(*args):
    return args
print(test(1, 2, 4))
arg_list = [1, 3, 5]
print(test(*arg_list))
# 输出为
>>> 
(1, 2, 4)
(1, 3, 5)
>>> 
关键字参数:定义为参数前带两个*,和甲鱼说的用关键字调用函数不同,python在处理时将参数作为一个dict传入,同样的,可以将已有的字典前加上**传入函数作为关键字参数,

另外可变参数和关键字参数的惯用定义为*args,*kw
def test(**kw):
    return kw
print(test(kw_1 = 1,kw_2 = 2,kw3 = 4))
kw_dict = {"kw_1": 1,"kw_2": 3,"kw_3": 5}
print(test(**kw_dict))
# 输出为
>>> 
{'kw_1': 1, 'kw_2': 2, 'kw3': 4}
{'kw_1': 1, 'kw_2': 3, 'kw_3': 5}
>>> 


-*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--
关于递归函数,在学习列表和树的遍历问题时,以为自己想的很清楚了,但是真正遇到实际的复杂问题,依然很拙计,记得之前看到坛友问的质因数分解问题,看了很久才看懂,递归问题,对于逻辑思维比较有帮助,比如质因数分解,坛友的思路很清晰,
1从小到大寻找质因数,
2把被分解数除以该质因数再次调用质因数分解函数
3中止条件是,调用函数的被分解数本身是质数
找到每次函数运行过程中的相同步骤,函数递归调用中止条件,两者搞清可写出递归函数

另外一个问题,在廖雪峰的python教程中看到了一个熟悉的名词:尾递归,即在递归调用函数中返回值为递归函数本身(包含表达式的不算),当然每次进行递归时传入参数不同,尾递归的函数,可以在做了尾递归优化的解释器中只占用一个栈帧,从而不会由于递归过深而导致栈的溢出,当然将递归函数改为尾递归也是技术活,先标记,以后研究,另外Python解释器也没有做优化,有一个针对尾递归优化的decorator,可以参考源码:
http://code.activestate.com/recipes/474088-tail-call-optimization-decorator/现在,只需要使用这个@tail_call_optimized,就可以实现尾递归优化(应该是py2.7的)

-*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--
如果要对list实现类似Java那样的下标循环怎么办?Python内置的enumerate函数可以把一个list变成索引-元素对,这样就可以在for循环中同时迭代索引和元素本身,如
for i, value in enumerate(['A', 'B', 'C']):
    print (i, value)
# 输出为
>>> 
0 A
1 B
2 C
>>> 





想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-3-27 12:33:33 | 显示全部楼层
本帖最后由 lightninng 于 2015-3-27 12:50 编辑

早上学了numpy中最基本的ndarray类的一些东西,主要是熟悉ndarray类,以及array函数的一些用法 :
1、ndarray类是一种类似于list的结构,但里面的每个元素都是相同的类型,可用arange函数生成一维的ndarray实例,也可以用array函数将一个list转化为ndarray实例,这里可以实验用不同的类型数据放在同一个list中调用array函数看看会发生什么,我自己实验了不整齐的list调用array函数
>>> from numpy import *
>>> a = numpy.arange(10) ** 2
>>> a
array([ 0,  1,  4,  9, 16, 25, 36, 49, 64, 81])  # 这个list前面的array表明a是一个ndarray类的实例
>>> type(a)
<class 'numpy.ndarray'>
>>> mitx = array([arange(2), arange(2)])
>>> mitx
array([[0, 1],
       [0, 1]])
# 当用array函数定义新的ndarray时,如果传入的是规则的列表(列表内部结构每一维都相等),则把内部的列表也转化为ndarray,否则只是普通的list
>>> a = array([[1, 1, 3],[2, 2]])
>>> a[0]
[1, 1, 3]
>>> a = array([[1, 1, 3],[2, 2, 2]])
>>> a[0]
array([1, 1, 3])
# array函数的传入参数是一个可迭代类型
>>> mitx = array([1,3,5,1],[2,5,1,2])
Traceback (most recent call last):
  File "<pyshell#17>", line 1, in <module>
    mitx = array([1,3,5,1],[2,5,1,2])
TypeError: data type not understood
>>> mitx = array([[1,3,5,1],[2,5,1,2]])
>>> mitx
array([[1, 3, 5, 1],
       [2, 5, 1, 2]])
由于NumPy的大部分代码都是用c语言写成的,所以ndarray的很多相关操作要比Python自带的list效率高很多
2、ndarray中每个元素都是相同的类型,可以调用dtype方法查看元素类型
>>> mitx.dtype  
dtype('int32')
>>> mitx.dtype.itemsize
4
3、ndarray类的实例对内部元素可以用如下方式来引用
>>> mitx[0,1]
1
>>> mitx[0]
array([0, 1, 2, 3, 4])
4、列表可以作为矩阵的一维形式     reshape方法可以将一维矩阵按需要的方式改变为多维的矩阵,     reval方法可以将多维矩阵展平(即转化为一维矩阵),但它返回原矩阵的一个视图(这里不太明白,可能是指改变reval方法得到的矩阵会改变元矩阵)
     flatten方法同reval方法,但是它会申请新的内存,返回存放在新内存中的矩阵(应该是指浅拷贝,未实验)  
     除了调用以上函数可以改变矩阵维度,我们还可以直接ndarray实例的shape属性赋值
 >>> b = arange(20).reshape(2, 3, 4) 
Traceback (most recent call last):
  File "<pyshell#26>", line 1, in <module>
    b = arange(20).reshape(2, 3, 4)
ValueError: total size of new array must be unchanged 
# 20 != 2 * 3 * 4,所以无法分为2 * 3 * 4形状的矩阵 
 
>>> b = arange(24).reshape(2, 3, 4)
>>> 
>>> b
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11]],

       [[12, 13, 14, 15],
        [16, 17, 18, 19],
        [20, 21, 22, 23]]])
>>> b.shape = 24
>>> b
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
       17, 18, 19, 20, 21, 22, 23]) 
>>> b.shape = (4,6)
>>> b
array([[ 0,  1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10, 11],
       [12, 13, 14, 15, 16, 17],
       [18, 19, 20, 21, 22, 23]])
>>> 





想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-3-28 11:44:05 | 显示全部楼层
本帖最后由 lightninng 于 2015-4-2 23:20 编辑

研究别人的代码头昏脑胀,python2 到python3,模块改这么多,直是晕~~
pycharm里面的一个问题

QQ图片20150328114020.jpg

这种情况英语叫作unsolved reference,似乎是pycharm这个idle有关的问题,先记录下来,看看这个request模块能否正常运行
另外,如果request模块可以运行,但是它还被标注出来,在被标注的地方点alt + enter 选择忽略即可注:一天以后我发现了这个问题的来源,因为request是urllib这个模块中的一个模块,所以想用request之中的函数就要
import urllib.request

-*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--
pep8的命名规范,复制过来,方便查阅
1 尽量单独使用小写字母‘l’,大写字母‘O’等容易混淆的字母。
2 模块命名尽量短小,使用全部小写的方式,可以使用下划线。
3 包命名尽量短小,使用全部小写的方式,不可以使用下划线。
4 类的命名使用CapWords的方式,模块内部使用的类采用_CapWords的方式。
5 异常命名使用CapWords+Error后缀的方式。
6 全局变量尽量只在模块内有效,类似C语言中的static。实现方法有两种,一是__all__机制;二是前缀一个下划线。
7 函数命名使用全部小写的方式,可以使用下划线。
8 常量命名使用全部大写的方式,可以使用下划线。
9 类的属性(方法和变量)命名使用全部小写的方式,可以使用下划线。
9 类的属性有3种作用域public、non-public和subclass API,可以理解成C++中的public、private、protected,non-public属性前,前缀一条下划线。
11 类的属性若与关键字名字冲突,后缀一下划线,尽量不要使用缩略等其他方式。
12 为避免与子类属性命名冲突,在类的一些属性前,前缀两条下划线。比如:类Foo中声明__a,访问时,只能通过Foo._Foo__a,避免歧义。如果子类也叫Foo,那就无能为力了。
13 类的方法第一个参数必须是self,而静态方法第一个参数必须是cls。

-*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--

因为要用到百度的Geocoding API,所以研究了一下怎么用,正好见到有用py2.7写的东西,自己拿了改了一改,同时学习一下某些模块的相关函数

1、urlopen()方法
这个方法在py2.x中是在urllib这个模块里的,到了py3.x,url相关的一些模块做了整合,这个方法在urllib中的request模块里,所以使用前需要import urllib.request
urllib.request.urlopen(url[, data[, proxies]]) :创建一个表示远程url的类文件对象,然后像本地文件一样操作这个类文件对象来获取远程数据。
参数url表示远程数据的路径,一般是网址;参数data表示以post方式提交到url的数据(玩过web的人应该知道提交数据的两种方式:post与get。如果你不清楚,也不必太在意,一般情况下很少用到这个参数);
参数proxies用于设置代理。
urlopen返回 一个类文件对象,它提供了如下方法:
read() , readline() , readlines() , fileno() , close() :这些方法的使用方式与文件对象完全一样;
info():返回一个httplib.HTTPMessage 对象,表示远程服务器返回的头信息
getcode():返回Http状态码。如果是http请求,200表示请求成功完成;404表示网址未找到;
geturl():返回请求的url;
2、urlencode()方法
和urlopen的情况一样,在py3.x中它在urllib中的parse模块里,
使用前需要import urllib.parse
urllib.parse.urlencode(dict) :将字典中的key和values以url编码,并返回一个字符串"key1=value1&key2=value2&........."
3、‘module’ object has no attribute’xxx’

上面两个方法如果仅仅import urllib是无法正常引用的,会报错'module' object has no attribute 'xxx',如下
>>> import urllib
>>> urllib.request.urlopen("www.baidu.com")
Traceback (most recent call last):
  File "<pyshell#1>", line 1, in <module>
    urllib.request.urlopen("www.baidu.com")
AttributeError: 'module' object has no attribute 'request'
必须将urllib.request和urllib.parse模块导入才可引用

4、以下是自己写的调用百度geocoding api v2.0 的函数
AK = "你的key"  # 百度geo_coding的开发者key
def get_geo_coordinate(addr):
    """
    获取坐标
    输入:地址(str)
    返回: 纬度,经度(元组),若失败返回-1,baidu_geo_coding返回的status码
    """
    import urllib.request
    import urllib.parse
    import json
    param = {'address': addr, 'output': 'json', 'ak': AK, 'city': "北京市"}
    url_request = "http://api.map.baidu.com/geocoder/v2/?" + urllib.parse.urlencode(param)
    url_fp = urllib.request.urlopen(url_request)
    url_dict = json.loads(url_fp.read().decode('utf-8'))
    if url_dict["status"] == 0:
        return url_dict["result"]["location"]["lat"], url_dict["result"]["location"]["lng"]
    else:
        return -1, url_dict["status"]
百度geo_coding的具体文档请看http://api.map.baidu.com/lbsapi/cloud/webservice-geocoding.htm






想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-3-30 00:00:53 | 显示全部楼层
本帖最后由 lightninng 于 2015-4-2 23:23 编辑

今天几乎是荒废了,没有怎么学,只有晚上搞了一下数据的问题,
1、学习到了两个函数,分别是
正态分布生成一个数和按对数正态分布生成一个数,就是按正态的概率去生成一个数
random.normalvariate(mu, sigma)
random.lognormvariate(mu, sigma)
2、按指定的概率随机获得一个元素
def distribution(value_list, probability_list):
    import random
    x = random.uniform(0, 1)
    cumulative_probability = 0.0
    for item, item_probability in zip(value_list, probability_list):
          cumulative_probability += item_probability
          if x < cumulative_probability:
              return item
如按让取到1的概率为0.2,2的概率为0.3,3的概率为0.5则这样调用函数
distribution([1, 2, 3], [0.2, 0.3, 0.5])





想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-3-31 00:19:39 | 显示全部楼层
本帖最后由 lightninng 于 2015-4-2 23:25 编辑

早上终于把数据弄的差不多了,晚上回来研究了数据库,以前没用过数据库,但是只能硬着头皮上了MySQL是一种小型的关系数据库,不过个人用绰绰有余了,记录一下安装过程
1、MySQL本体:官网下安装包,要下免费的MySQL Community Server,http://dev.mysql.com/downloads/mysql/,记得下载和你的系统对应的版本,这里有zip包和msi文件两种,后一种简单无脑,不过我以前遇到过安装msi文件不成功的情况,所以这次选择的前者,下载好zip文件之后的步骤见这个经验贴http://jingyan.baidu.com/article/f3ad7d0ffc061a09c3345bf0.html
2、更改root用户密码:安装好之后,更改root用户的密码,在有管理员的cmd命令行下输入mysqladmin -u USER -p password PASSWORD,其中USER改为root,password应该为空,PASSWORD为新密码,也就是mysqladmin -u root -p  PASSWORD,这里会让你输入密码,默认是没有密码的,所以直接回车即可,于是root用户的密码改为了PASSWORD,注意听-p后面是两个空格
3、安装可视化的扩展:如果作为一个数据库的初学者,这个东西还是比较有用的,可以直观的看到库中每个表的内容,可视化操作起来也比较方便,当然真正做数据分析的时候这玩意儿就用不大上了。这里可选择的有很多,我自己比较在意的是一款MySQL官方发布的MySQL Workbench(纯E文),和中文简体的Navicat for MySQL,个人选择后者,因为急用,来不及研究e文,同样下载与自己系统应的版本,http://www.navicat.com.cn/download/navicat-for-mysql
4、安装python的mysql模块:似乎在python2.x时代用的比较广泛的是mysqlbd这个,但是python3.x已经没有这个模块了,取而代之的是官方发布的MySQL Connector/python,下载地址http://dev.mysql.com/downloads/mysql/,下好之后开包即可食用
到此安装方面已经完成

-*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--*--*--*--*--*---*--*--*--*--*--*--
mysql connector的一些用法
1、先说一个和mysql connector无关的,创建新的数据库打开Navicat 点左上角的连接,选MySQL,连接名自己定,密码填上你刚改的密码即可,然后在左方列表处双击你刚创建的连接即可连接到MySQL的数据库了,然后在左方列表空白处右键,新建数据库即可
2、用mysql connector操作数据库,基本就是连接数据库,创建游标cursor,然后cursor.execute("mysql 语句"),例如下面两条中的例子
3、新建表
def create_table():
    import mysql.connector
    # 连接数据库
    cnn = None
    config = {'host': '127.0.0.1',  # 默认127.0.0.1
              'user': 'root',  # 连接的用户名
              'password': 'PASSWORD',
              'port': 3306,  # 默认即为3306
              'database': 'my_database',  # 使用的数据库名
              'charset': 'utf8'  # 默认即为utf8
              }
    try:
        cnn = mysql.connector.connect(**config)
    except mysql.connector.Error as e:
        print('connect fails!{}'.format(e))
        import os
        os.system("net start mysql")
    cursor = cnn.cursor()
    # 生成mysql语句存放在sql_create_table变量中
    sql_create_table = 'CREATE TABLE `data` (' \ 
                   '`ID` int(15) NOT NULL AUTO_INCREMENT, ' \
                   '`DATA` varchar(255) DEFAULT NULL, ' \
                   'PRIMARY KEY (`ID`)) ENGINE=MyISAM DEFAULT CHARSET=utf8'
    try:
        cursor.execute(sql_create_table)
    except mysql.connector.Error as e:
        print("create_table orange fails!{}".format(e))
这里说一下似乎每行一个字符串,然后行尾用\的话,可以起到相当于+的效果(请当我是火星人吧),如,下面两种方式statements同样 的被赋值
staements = "test" + "statements"
staements = "test" \
            "statements"
4、向指定表中插入数据如果只想了解mysql connctor 插入数据核心语句的朋友请看函数注释中最后面注的内容
def insert_record(table_name, record_insert, mode='L'):
    """
    :param table_name: 要插入数据的表的名字
    :param record_insert: 要插入的数据,可以是list或者dict格式
    :param mode: 插入模式list方式(mode='L',默认)或dict方式(mode='D')
    :return:无
    注:mysql connctor 插入数据的三种方式
        '第一种:直接字符串插入方式'
            sql_insert1="insert into student (name, age) values ('orange', 20)"
            cursor.execute(sql_insert1)
        '第二种:元组连接插入方式'
            sql_insert2="insert into student (name, age) values (%s, %s)"
            #此处的%s为占位符,而不是格式化字符串,所以age用%s
            data=('shiki',25)
            cursor.execute(sql_insert2,data)
        '第三种:字典连接插入方式'
            sql_insert3="insert into student (name, age) values (%(name)s, %(age)s)"
            data={'name':'mumu','age':30}
            cursor.execute(sql_insert3,data)
    """
    import mysql.connector
    # 连接数据库
    cnn = None
    config = {'host': '127.0.0.1',  # 默认127.0.0.1
              'user': 'root',  # 连接的用户名
              'password': 'PASSWORD',
              'port': 3306,  # 默认即为3306
              'database': 'my_database',  # 使用的数据库名
              'charset': 'utf8'  # 默认即为utf8
              }
    try:
        cnn = mysql.connector.connect(**config)
    except mysql.connector.Error as e:
        print('connect fails!{}'.format(e))
        import os
        os.system("net start mysql")
    cursor = cnn.cursor()
    sql_statements = None  # 用于存储mysql语句
    try:
        if mode == 'L':
            sql_statements = "insert into " + table_name + " values (%s" + ", %s"*(len(record_insert) - 1) + ")"
        elif mode == 'D':
            sql_statements = "insert into " + table_name + " (" + \
                ", ".join(record_insert.keys()) + ") values (" + \
                ", ".join([("%(" + key + ")s") for key in record_insert.keys()]) + ")"
        else:
            print("mode error!")
        cursor.execute(sql_statements, record_insert)
    except mysql.connector.Error as e:
        print('insert_data error!{}'.format(e))
    finally:
        cursor.close()
        cnn.close()






想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-3-31 23:31:23 | 显示全部楼层
今天还是兼职,学习的时间基本都在倒腾数据库,接昨天
1、选择数据库内容并返回引用
# 同样的先连接数据库,创建游标
cnn = None
import mysql.connector
config = {'host': '127.0.0.1',  # 默认127.0.0.1
          'user': 'root',  # 连接的用户名
          'password': 'PASSWORD',
          'port': 3306,  # 默认即为3306
          'database': 'my_database',
          'charset': 'utf8'  # 默认即为utf8
          }
try:
    cnn = mysql.connector.connect(**config)
except mysql.connector.Error as e:
    print('connect fails!{}'.format(e))
    import os
    os.system("net start mysql")
cursor = cnn.cursor()

i = 0
# 同样用一个变量储存SQL语句,然后用cursor.execute()执行
sql_query = "select RECORDID, MERCHID, MERCHANTNAME, ADDRESS, MERCHTYPE,"\
    " TRANDATE, TRANTIME, CARDNO, TRANAMT from origin_data"\
    " where RECORDID >= 100"
cursor.execute(sql_query)
# 用for语句来获取每一条数据
for item in cursor:
    print(item)
2、获取一个表内的数据的条数

MySQL中有一个名为 information_schema 的数据库,在该库中有一个 TABLES 表,这个表主要字段分别是:

TABLE_SCHEMA : 数据库名

TABLE_NAME:表名

ENGINE:所使用的存储引擎

TABLES_ROWS:记录数

DATA_LENGTH:数据大小

INDEX_LENGTH:索引大小

然后你懂的只需要用SQL查询语句查询TABLE_SCHEMA 和 TABLE_NAME对应的TABLES_ROWS即可


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-4-1 09:06:31 | 显示全部楼层
本帖最后由 lightninng 于 2015-4-2 23:26 编辑

和python学习的关系不大的一个东西
MySQL 的数值数据类型可以大致划分为两个类别,一个是整数,另一个是浮点数或小数。许多不同的子类型对这些类别中的每一个都是可用的,每个子类型支持不同大小的数据,并且 MySQL 允许我们指定数值字段中的值是否有正负之分或者用零填补。

表列出了各种数值类型以及它们的允许范围和占用的内存空间。
数字类型
整形
类型大小 范围(有符号) 范围(无符号) 用途
TINYINT 1 字节 (-128127) (0255) 小整数值
SMALLINT 2 字节 (-32 76832 767) (065 535) 大整数值
MEDIUMINT 3 字节 (-8 388 6088 388 607)(016 777 215) 大整数值
INTINTEGER 4 字节 (-2 147483 6482 147 483 647) (04 294 967 295) 大整数值
BIGINT 8 字节 (-9 233 372 036854 775 8089 223 372 036 854 775 807) (018 446 744 073 709551 615) 极大整数值
FLOAT 4 字节 (-3.402 823 466E+381.175 494 351 E-38)0(1.175 494 351 E-383.402 823 466 351 E+38) 0(1.175 494 351 E-383.402 823466 E+38) 单精度
浮点数值
DOUBLE 8 字节 (1.797 693 134 862315 7 E+3082.225 073 858 507 201 4 E-308)0(2.225 073858 507 201 4 E-3081.797 693 134 862 315 7 E+308) 0(2.225 073 858 507201 4 E-3081.797 693 134 862 315 7 E+308) 双精度
浮点数值
DECIMAL DECIMAL(M,D) ,如果M>D,为M+2否则为D+2 依赖于MD的值 依赖于MD的值 小数值

INT 类型
  在 MySQL 中支持的 5 个主要整数类型是 TINYINTSMALLINTMEDIUMINTINT BIGINT。这些类型在很大程度上是相同的,只有它们存储的值的大小是不相同的。

  MySQL 以一个可选的显示宽度指示器的形式对 SQL 标准进行扩展,这样当从数据库检索一个值时,可以把这个值加长到指定的长度。例如,指定一个字段的类型为 INT(6),就可以保证所包含数字少于 6 个的值从数据库中检索出来时能够自动地用空格填充。需要注意的是,使用一个宽度指示器不会影响字段的大小和它可以存储的值的范围。

  万一我们需要对一个字段存储一个超出许可范围的数字,MySQL 会根据允许范围最接近它的一端截短后再进行存储。还有一个比较特别的地方是,MySQL 会在不合规定的值插入表前自动修改为 0

  UNSIGNED 修饰符规定字段只保存正值。因为不需要保存数字的正、负符号,可以在储时节约一个“位”的空间。从而增大这个字段可以存储的值的范围。

  ZEROFILL 修饰符规定 0(不是空格)可以用来真补输出的值。使用这个修饰符可以阻止 MySQL 数据库存储负值。
浮点
FLOATDOUBLE DECIMAL 类型
  MySQL 支持的三个浮点类型是 FLOATDOUBLE DECIMAL 类型。FLOAT 数值类型用于表示单精度浮点数值,而 DOUBLE 数值类型用于表示双精度浮点数值。

  与整数一样,这些类型也带有附加参数:一个显示宽度指示器和一个小数点指示器。比如语句 FLOAT(7,3) 规定显示的值不会超过 7 位数字,小数点后面带有 3 位数字。

  对于小数点后面的位数超过允许范围的值,MySQL 会自动将它四舍五入为最接近它的值,再插入它。

  DECIMAL 数据类型用于精度要求非常高的计算中,这种类型允许指定数值的精度和计数方法作为选择参数。精度在这里指为这个值保存的有效数字的总个数,而计数方法表示小数点后数字的位数。比如语句 DECIMAL(7,3) 规定了存储的值不会超过 7 位数字,并且小数点后不超过 3 位。

  忽略 DECIMAL 数据类型的精度和计数方法修饰符将会使 MySQL 数据库把所有标识为这个数据类型的字段精度设置为 10,计算方法设置为 0
字符串类型
  UNSIGNED ZEROFILL 修饰符也可以被 FLOATDOUBLE DECIMAL 数据类型使用。并且效果与 INT 数据类型相同。

字符串类型
  MySQL 提供了 8 个基本的字符串类型,可以存储的范围从简单的一个字符到巨大的文本块或二进制字符串数据。

类型大小 用途
CHAR 0-255字节 定长字符串
VARCHAR 0-255字节 变长字符串
TINYBLOB 0-255字节 不超过 255 个字符的二进制字符串
TINYTEXT 0-255字节 短文本字符串
BLOB 0-65 535字节 二进制形式的长文本数据
TEXT 0-65 535字节 长文本数据
MEDIUMBLOB 0-16 777 215字节 二进制形式的中等长度文本数据
MEDIUMTEXT 0-16 777 215字节 中等长度文本数据
LOGNGBLOB 0-4 294 967 295字节 二进制形式的极大文本数据
LONGTEXT 0-4 294 967 295字节 极大文本数据

CHAR VARCHAR
  CHAR 类型用于定长字符串,并且必须在圆括号内用一个大小修饰符来定义。这个大小修饰符的范围从 0-255。比指定长度大的值将被截短,而比指定长度小的值将会用空格作填补。

  CHAR 类型可以使用 BINARY 修饰符。当用于比较运算时,这个修饰符使 CHAR 以二进制方式参于运算,而不是以传统的区分大小写的方式。

  CHAR 类型的一个变体是 VARCHAR 类型。它是一种可变长度的字符串类型,并且也必须带有一个范围在 0-255 之间的指示器。CHAR VARCHGAR 不同之处在于 MuSQL 数据库处理这个指示器的方式:CHAR 把这个大小视为值的大小,不长度不足的情况下就用空格补足。而 VARCHAR 类型把它视为最大值并且只使用存储字符串实际需要的长度(增加一个额外字节来存储字符串本身的长度)来存储值。所以短于指示器长度的 VARCHAR 类型不会被空格填补,但长于指示器的值仍然会被截短。

  因为 VARCHAR 类型可以根据实际内容动态改变存储值的长度,所以在不能确定字段需要多少字符时使用 VARCHAR 类型可以大大地节约磁盘空间、提高存储效率。

  VARCHAR 类型在使用 BINARY 修饰符时与 CHAR 类型完全相同。

TEXT BLOB
  对于字段长度要求超过 255 个的情况下,MySQL 提供了 TEXT BLOB 两种类型。根据存储数据的大小,它们都有不同的子类型。这些大型的数据用于存储文本块或图像、声音文件等二进制数据类型。

  TEXT BLOB 类型在分类和比较上存在区别。BLOB 类型区分大小写,而 TEXT 不区分大小写。大小修饰符不用于各种 BLOB TEXT 子类型。比指定类型支持的最大范围大的值将被自动截短。

日期和时间类型
  在处理日期和时间类型的值时,MySQL 带有 5 个不同的数据类型可供选择。它们可以被分成简单的日期、时间类型,和混合日期、时间类型。根据要求的精度,子类型在每个分类型中都可以使用,并且 MySQL 带有内置功能可以把多样化的输入格式变为一个标准格式。

类型大小
(字节) 范围 格式 用途
DATE 3 1000-01-01/9999-12-31 YYYY-MM-DD 日期值
TIME 3 '-838:59:59'/'838:59:59' HH:MM:SS 时间值或持续时间
YEAR 1 1901/2155 YYYY 年份值
DATETIME 8 1000-01-01 00:00:00/9999-12-3123:59:59 YYYY-MM-DD HH:MM:SS 混合日期和时间值
TIMESTAMP 8 1970-01-01 00:00:00/2037 年某时 YYYYMMDDHHMMSS 混合日期和时间值,时间戳

DATETIME TEAR
  MySQL DATE TEAR 类型存储简单的日期值,使用 TIME 类型存储时间值。这些类型可以描述为字符串或不带分隔符的整数序列。如果描述为字符串,DATE 类型的值应该使用连字号作为分隔符分开,而 TIME 类型的值应该使用冒号作为分隔符分开。

  需要注意的是,没有冒号分隔符的 TIME 类型值,将会被 MySQL 理解为持续的时间,而不是时间戳。

  MySQL 还对日期的年份中的两个数字的值,或是 SQL 语句中为 TEAR 类型输入的两个数字进行最大限度的通译。因为所有 TEAR 类型的值必须用 4 个数字存储。MySQL 试图将 2 个数字的年份转换为 4 个数字的值。把在 00-69 范围内的值转换到 2000-2069 范围内。把 70-99 范围内的值转换到 1970-1979 之内。如果 MySQL 自动转换后的值并不符合我们的需要,请输入 4 个数字表示的年份。

DATEYIME TIMESTAMP
  除了日期和时间数据类型,MySQL 还支持 DATEYIME TIMESTAMP 这两种混合类型。它们可以把日期和时间作为单个的值进行存储。这两种类型通常用于自动存储包含当前日期和时间的时间戳,并可在需要执行大量数据库事务和需要建立一个调试和审查用途的审计跟踪的应用程序中发挥良好作用。

  如果我们对 TIMESTAMP 类型的字段没有明确赋值,或是被赋与了 null 值。MySQL 会自动使用系统当前的日期和时间来填充它。

复合类型
  MySQL 还支持两种复合数据类型 ENUM SET,它们扩展了 SQL 规范。虽然这些类型在技术上是字符串类型,但是可以被视为不同的数据类型。一个 ENUM 类型只允许从一个集合中取得一个值;而 SET 类型允许从一个集合中取得任意多个值。

ENUM
  ENUM 类型因为只允许在集合中取得一个值,有点类似于单选项。在处理相互排拆的数据时容易让人理解,比如人类的性别。ENUM 类型字段可以从集合中取得一个值或使用 null 值,除此之外的输入将会使 MySQL 在这个字段中插入一个空字符串。另外如果插入值的大小写与集合中值的大小写不匹配,MySQL 会自动使用插入值的大小写转换成与集合中大小写一致的值。

   ENUM 类型在系统内部可以存储为数字,并且从 1 开始用数字做索引。一个 ENUM 类型最多可以包含 65536 个元素,其中一个元素被 MySQL 保留,用来存储错误信息,这个错误值用索引 0 或者一个空字符串表示。

  MySQL 认为 ENUM 类型集合中出现的值是合法输入,除此之外其它任何输入都将失败。这说明通过搜索包含空字符串或对应数字索引为 0 的行就可以很容易地找到错误记录的位置。

SET
  SET 类型与 ENUM 类型相似但不相同。SET 类型可以从预定义的集合中取得任意数量的值。并且与 ENUM 类型相同的是任何试图在 SET 类型字段中插入非预定义的值都会使 MySQL 插入一个空字符串。如果插入一个即有合法的元素又有非法的元素的记录,MySQL 将会保留合法的元素,除去非法的元素。

  一个 SET 类型最多可以包含 64 项元素。在 SET 元素中值被存储为一个分离的“位”序列,这些“位”表示与它相对应的元素。“位”是创建有序元素集合的一种简单而有效的方式。并且它还去除了重复的元素,所以 SET 类型中不可能包含两个相同的元素。

  希望从 SET 类型字段中找出非法的记录只需查找包含空字符串或二进制值为 0 的行。




想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-4-1 14:53:34 | 显示全部楼层
我想搜藏 该贴,在哪里呢:shock:
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-4-1 23:39:06 | 显示全部楼层
gelebo 发表于 2015-4-1 14:53
我想搜藏 该贴,在哪里呢

111.jpg
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-4-2 23:16:52 | 显示全部楼层
今天的内容记录在PyQt5那个贴子里了,大概明白了PyQt的一些用法的原理,明天继续论文,从百度app查经纬度好几百万条数据。不知得花多少天~~
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-4-3 08:35:45 | 显示全部楼层
非常棒的学习记录贴啊
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-4-3 10:30:10 | 显示全部楼层
要学习 发表于 2015-4-3 08:35
非常棒的学习记录贴啊

谢谢,学习中,多交流感觉学的更快~~:handshake
欢迎吐槽~~
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-24 15:31

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表