文档章节

杂记5:Python官网的The Python Tutorial笔记

fzyz_sb
 fzyz_sb
发布于 2015/06/13 08:32
字数 3036
阅读 260
收藏 0

1. Python中列表赋值的问题

    在看官网时候,我个人写了如下的代码练习切割操作:

In[68]: letters
Out[68]: ['a', 'b', 'C', 'D', 'E', 'f', 'g']
In[69]: letters[2:5] = ['c', 'd', 'e']
In[70]: letters
Out[70]: ['a', 'b', 'c', 'd', 'e', 'f', 'g']
In[71]: letters[2:5] = ('C', 'D', 'E')
In[72]: letters
Out[72]: ['a', 'b', 'C', 'D', 'E', 'f', 'g']
    我当时的第一个疑问是:
In[71]: letters[2:5] = ('C', 'D', 'E')
In[72]: letters
Out[72]: ['a', 'b', 'C', 'D', 'E', 'f', 'g']
这里letters为什么不会被修改为:['a', 'b', ('C', 'D', 'E'), 'f', 'g' ].

    然后想明白了对于切割操作,外层的[]是语法糖,代表的里面包含的元素要替换letters中的列表,这时('C', 'D', 'E')实际上被解释为['C', 'D', 'E'],则上述的赋值操作,可以解释如下:

letters = ['a', 'b'] + ['c', 'd', 'e'] + ['f', 'g']
letters[2:5] = ('C', 'D', 'E') ==> ['a', 'b'] + ['C', 'D', 'E'] + ['f', 'g'] ==> ['a', 'b', 'c', 'd', 'e', 'f', 'g']
如果我们非要赋值元祖,可以提供一个列表,里面的数据是元祖即可:
In[74]: letters[2:5] = [('c', 'd', 'e')]
In[75]: letters
Out[75]: ['a', 'b', ('c', 'd', 'e'), 'f', 'g']
    这也解释了为什么我们清空列表可以这样编写:
In[76]: letters[:] = []
In[77]: letters
Out[77]: []


2. for循环的基本使用

    C++的STL支持迭代器,而Python中也直接类似的操作.例如我们遍历一个列表,通常有以下两种方法:

# -*- coding:utf-8 -*-
nums = range(0, 10)
#类似迭代器
for num in nums:
    print num,
print
#使用下标索引
for i in range(0, len(nums)):
    print nums[i],
print
    如果我们想要修改列表,通过索引则可以很简单实现:
#使用索引进行列表的修改
for i in range(0, len(nums)):
    nums[i] += 10
#[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
print nums
    而实际上通过迭代器无法实现,我们可以测试如下:
nums = [1, 2]
#[140520361897032, 140520361897008]
print [id(num) for num in nums]
#使用迭代实现修改元素
#140520361896792 140520361896768
for num in nums:
    num += 10
    print id(num),
print
#[1, 2]
print nums

     for循环中的每个num为数值,是不可改变的,所以每次执行+操作,会新建一个num,然后存储新值.这也是为什么这里的id会完全不同的原因.

    而且使用迭代器操作改变原列表有一个很隐藏的BUG!:

# -*- coding:utf-8 -*-
words = ['a', 'bb', 'ccc']
for w in words:
    print w
    if len(w) > 2:
        words.insert(0, w)

print words
这段代码会死循环直到内存溢出~_~

所以一般我们会修改成:

# -*- coding:utf-8 -*-
words = ['a', 'bb', 'ccc']
for w in words[:]:
    if len(w) > 2:
        words.insert(0, w)
#['ccc', 'a', 'bb', 'ccc']
print words

    for循环还有一个非常好用的属性:判断for循环是否完整运行:

# -*- coding:utf-8 -*-
nums = range(0, 3)
#类似迭代器
for num in nums:
    print num,
else:
    print '完整运行一遍'

for num in nums:
    if num > 1:
        break
else:
    print '这句话不会输出'
    
#输出如下: 0 1 2 完整运行一遍

    在循环中还有两个函数特别有用:enumerate和zip:

In[52]: for i, v in enumerate(['a', 'b', 'c']):
...     print i, v
...     
0 a
1 b
2 c
而zip可以将多个列表进行操作:
In[53]: for key, value in zip([0, 1, 2], ['a', 'b', 'c']):
...     print key, '=>', value
...     
0 => a
1 => b
2 => c


3. 函数的基本使用

    函数传参的基本原则是:传递一个对象,而非副本:

# -*- coding:utf-8 -*-
nums = [1, 2]
def func(nums):
    nums += [11, 12]

func(nums)
#[1, 2, 11, 12]
print nums
    函数名也只是一个对象,所以存在赋值操作:
# -*- coding:utf-8 -*-
def func():
    print 'hello world'

f = func
#hello world
f()
#4408107568
print id(f)
#4408107568
print id(func)
    函数传参时要遵循以下原则:

保证所传递的参数不被函数所修改,被修改的变量当做函数返回值,而非函数的参数.

例如:

# -*- coding:utf-8 -*-
def func(words, nums = []):
    newStr = words + ",".join(nums)
    return newStr

nums = ['1', '2']
newStr = func("hello", nums)
#['1', '2']
print nums
#hello1,2
print newStr
    我之前曾经思考过所传递的参数必须为元祖,例如传递参数时候将列表转换为元祖,在函数内部将元祖再转换为列表等,但是对于字典则很难办,而且代码会非常的繁琐.所以就按照上面的原则进行函数的编写.

    缺省参数的写法可以让我们完成类似C++的重载操作:

# -*- coding:utf-8 -*-
def func(words, nums = []):
    print words
    if nums:
        print nums

#hello
func('hello')
#hello
#[1, 2, 3]
func('hello', [1, 2, 3])


4. 列表的基本使用

1. 基本函数

list.append(x): 向后插入一个元素,等价于:a[len(a):] = [x]

list.extend(L): 通过插入列表L来达到扩展的目的,等价于a[len(a):] = L

list.insert(index, x): 在当前索引index前插入元素x

list.remove(x): 移除元素值等于x的元素.如果此元素不存在,则报错.

list.pop([i]): 移除指定索引的元素并返回删除元素的值.如果不带参数索引,则默认删除最后一个元素并返回它.

list.index(x): 返回值等于x的元素的索引,如果不存在则报错.

list.count(x): 返回x在列表中出现的次数

list.sort(cmp = None, key = None, reverse = False): 排序列表

list.reverse(): 反转列表

# -*- coding:utf-8 -*-
nums = [1, 2]
#[1, 2, 3]
nums.append(3)
#[1, 2, 3, 4, 5]
nums.extend([4, 5])
#[1, 1.11, 2, 3, 4, 5]
nums.insert(1, 1.11)
#[1, 2, 3, 4, 5]
nums.remove(1.11)
#3
print nums.pop(2)
#5
print nums.pop()
#2
print nums.index(4)
#1
print nums.count(1)
nums.reverse()
#[4, 2, 1]
print nums
2. 对列表有用的三个内建函数

filter(function, sequence): 对序列sequence中每个元素item执行function(item),返回为True组合的序列.除了str, unicode和tuple,其余的都返回列表

# -*- coding:utf-8 -*-
#[1, 3, 5, 7, 9]
print filter(lambda x: x % 2, range(0, 10))
#defg
print filter(lambda x: x > 'c', 'abcdefg')
#(4, 5)
print filter(lambda x: x > 3, tuple(range(0, 6)))
map(function, sequence): 与filter类似,但是function需要几个参数,则就需要几个序列
# -*- coding:utf-8 -*-
#[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
print map(lambda x: x * x, range(0, 10))
#[0, 2, 6, 12, 20, 30, 42, 56, 72, 90]
print map(lambda x, y: x * y, range(0, 10), range(1, 11))
reduce(function, sequence): 读取序列的前两个元素进行function,然后生成的结果作为第一个元素,和第三个元素继续组成两个元素,然后继续function.如果提供初始值,则以初始值作为第一个元素:
# -*- coding:utf-8 -*-
def add(x, y):
    return x + y
#55
print reduce(add, range(1, 11))

def mul(x, y):
    return x * y
#240
print reduce(mul, range(1, 5), 10)


5. 推导式的基本使用

    最常用的是列表推导式:

In[35]: [(x + 1) for x in range(0, 10)]
Out[35]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    但是如果一个序列很大,例如我们通过推导式来读取一个文件,则我们需要生成器表达式(个人理解为元祖推导式)来完成:
In[38]: ss = ((x + 1) for x in range(0, 1000))
In[39]: ss
Out[39]: <generator object <genexpr> at 0x108764cd0>
In[40]: for i in ss:
...     if i > 10:
...         break
...     print i,
...     
1 2 3 4 5 6 7 8 9 10
    假设是集合set,那么使用推导式则需要花括号:
In[42]: a = {x for x in 'abracadabra' if x not in 'abc'}
In[43]: a
Out[43]: {'d', 'r'}
In[44]: set(['d', 'r'])
Out[44]: {'d', 'r'}


6. 模块化

    在大型项目中,模块化是非常重要的.但是我们导入模块时候有两种方式,假设我们定义了一个模块文件:

__author__ = 'lgt'

def fib(n):
    a, b = 0, 1
    while b < n:
        print b,
        a, b = b, a + b

def fib2(n):
    result = []
    a, b = 0, 1
    while b < n:
        result.append(b)
        a, b = b, a + b
    return result
一般情况下我们会这样导入:
In[15]: import fibo
In[16]: fibo.fib(100)
1 1 2 3 5 8 13 21 34 55 89
In[17]: fibo.fib2(100)
Out[17]: [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
    但是有时候为了书写方便,我们往往会这样导入:
In[18]: from fibo import fib, fib2
In[19]: from fibo import *
In[20]: fib(100)
1 1 2 3 5 8 13 21 34 55 89
In[21]: fib2(100)
Out[21]: [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
    但是这会隐藏一个BUG.例如我们在另一个文件fibo1.py中定义了相同的fib函数:
__author__ = 'lgt'

def fib(n):
    print 'hello world'
那么那个模块最后导入,就使用那个模块:
In[22]: from fibo import *
In[23]: from fibo1 import *
In[24]: fib(100)
hello world
In[25]: from fibo1 import *
In[26]: from fibo import *
In[27]: fib(100)
1 1 2 3 5 8 13 21 34 55 89
    所以,具体取舍还是得靠程序员自己.

__name__ == '__main__'的妙用

    一般情况下,我们是需要对一个模块进行单元测试的编写的.这时我们往往可以在模块中添加类似如下指令:

if __name__ == '__main__':
    import sys
    fib(int(sys.argv[1]))
因为只有运行当前模块情况下,__name__才会等于'__main__',而如果其它模块调用它,则__name__等于'fibo'.


7. 序列化json

    序列化用代码就可以说明:

# -*- coding:utf-8 -*-
import json
f = open('test.txt', 'w')
json.dump([1, 'simple', 'list'], f)
f.close()

with open('test.txt', 'r') as f:
    for line in f:
        print line
        print type(line)

with open('test.txt', 'r') as f:
    x  = json.load(f)
    print x
    print type(x)
输出:
[1, "simple", "list"]
<type 'str'>
[1, u'simple', u'list']
<type 'list'>


8. 异常处理

    异常通常使用try ... catch 来捕获.而else表示没有产生异常时必须执行的语句,finally表示无论是否发生异常,都会被执行的语句:

# -*- coding:utf-8 -*-
import sys

try:
    a = 1 / 1
except (RuntimeError, TypeError, NameError) as e:
    print 'handler error', e
else:
    print 'no error'
finally:
    print 'finish'

#输出:
#no error
#finish
而产生异常的代码:
# -*- coding:utf-8 -*-
import sys

try:
    a = 1 / 0
except (RuntimeError, TypeError, NameError, ZeroDivisionError) as e:
    print 'handler error', e
else:
    print 'no error'
finally:
    print 'finish'

#输出:
#finish


9. Classes

1. Python的作用域和命名空间

    命名空间就是一堆对象的名字集合,而对象通常具有不同的生命周期.而作用域就是命名空间可以直接访问的文本域,且作用域通常是动态生成的(Python是解释性语言).

例如,我们定义一个函数func,则产生一个作用域:

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

def func():
    x = 1
    del x
    这是,执行x = 1实际上就是将变量x绑定到函数func所产生的作用域中,而del x就是接触绑定.

2. 类对象

    类对象支持两种操作: 属性引用和实例化.假设我们定义一个类:

class MyClass:
    """A simple example class"""
    i = 12345
    def __init__(self, i):
        self.i = i
    def f(self):
        return 'hello world'

属性引用:

print MyClass.i    #12345
MyClass.i = 10000
print MyClass.i    #10000
    而我们一般都使用实例化:
x = MyClass(12345)
print x.f()     #hello world
print x.i       #12345
3. 实例化变量

    类变量针对类而言,而实例化变量针对具体对象而言.假设我们编写如下代码:

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

class Dog:
    kind = 'canine'

    def __init__(self, name):
        self.name = name

d = Dog('Fido')
e = Dog('Buddy')
print d.kind    #canine
print e.kind    #canine
print d.name    #Fido
print e.name    #Buddy
    这里类变量和实例变量互不影响.但假设我们这样编写代码:
# -*- coding:utf-8 -*-

class Dog:
    tricks = []

    def __init__(self, name):
        self.name = name
    def add_trick(self, trick):
        self.tricks.append(trick)

d = Dog('Fido')
e = Dog('Buddy')
d.add_trick('roll over')
e.add_trick('play dead')
print d.tricks  #['roll over', 'play dead']
    这不是新需求,是BUG......

所以我们一般都是这样设计:

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

class Dog:
    def __init__(self, name):
        self.name = name
        self.tricks = []
    def add_trick(self, trick):
        self.tricks.append(trick)

d = Dog('Fido')
e = Dog('Buddy')
d.add_trick('roll over')
e.add_trick('play dead')
print d.tricks  #['roll over']

4. 继承

    Python中的继承机制如C++的虚拟继承,即所有的函数都可以被重写,可直接被调用,或者根本不调用:


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

class BaseClass(object):
    def __init__(self, name):
        self.baseName = name
    def show(self):
        print self.baseName
    def getName(self):
        return self.baseName
    def baseFunc(self):
        print "I'm baseClass"

class SubClass(BaseClass):
    def __init__(self, name, num):
        super(SubClass, self).__init__(name)
        self.subNum = num
    def show(self):
        super(SubClass, self).show()
        print self.subNum
    def getName(self):
        return self.baseName + str(self.subNum)

C = SubClass('lcj', 26)
#继承父函数
C.show()
#调用自身函数
print C.getName()
#调用父函数
C.baseFunc()
输出:



lcj
26
lcj26
I'm baseClass
    而Python中私有变量往往以__(双下划线开头),这在设计类的时候很有用:



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

class Mapping:
    def __init__(self, iterable):
        self.items_list = []
        #私有变量
        self.__update(iterable)
    def update(self, iterable):
        for item in iterable:
            self.items_list.append(item)

    __update = update

class MappingSubclass(Mapping):
    def update(self, keys, values):
        for item in zip(keys, values):
            self.items_list.append(item)

S = MappingSubclass([11, 12])
S.update(['a', 'b'], [1, 2])
#[11, 12, ('a', 1), ('b', 2)]
print S.items_list





© 著作权归作者所有

共有 人打赏支持
fzyz_sb
粉丝 408
博文 209
码字总数 447144
作品 0
武汉
程序员
Python学习日记六(Python连接MySql)

一.准备工作(下载MySQL-python和python安装包 ) Python需要连接mysql,需要下载Python MySQLdb模块,这里提供几个链接地址: MySQL-python官网下载地址 :https://pypi.python.org/pypi/My...

HaleyLiu
04/12
0
0
Eclipse+PyDev+Django+Mysql搭建Python web开发环境

             Eclipse+PyDev+Django+Mysql搭建Python web开发环境   Python的web框架有很多,目前主流的有Django、Tornado、Web.py等,最流行的要属Django了,也是被大家最看...

狼行-狼行
2014/05/05
0
0
RHEL 5下安装Scrapy-0.14.0.2841爬虫框架

Scrapy是一款非常成熟的爬虫框架,可以抓取网页数据并抽取结构化数据,目前已经有很多企业用于生产环境。对于它的更多介绍,可以查阅相关资料(官方网站:www.scrapy.org)。 我们根据官网提...

durban
2012/04/30
0
0
PHP版 RabbitMQ官方中文入门教程

工作中用到 RabbitMQ,但是RabbitMQ官方的 Tutorials 是英文Python和Jave的,官网的教程很好,正好最近业余在撸Python,所以直接来搞个PHP版本的,仅供PHP菜鸟一起来入门学习,如有错误和问题...

Yuansir
2013/06/03
0
0
Python 工具——Anaconda+Pycharm 的安装过程

适用对象:编程完全小白,准备安装 Python 进行学习 本文特点: 十分具体详细,细致到了每一步安装过程的截图,看了此篇,你完全不用看其他教程,给出了软件的百度云以及自己找到的可用的 Py...

xjtuhit
05/07
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

c语言之内存分配笔记

先看一个数组: short array[5] = {1,2} // 这儿定义的一个int类型的数组,数组第1和第2个元素值是1和2.其余后面默认会给值为0; 或者 short array[] = {1,2};//这儿数组第1和第2个元素,数组...

DannyCoder
今天
2
0
Shell | linux安装包不用选择Y/N的方法

apt-get install -y packageOR echo "y" | sudo apt-get install package

云迹
今天
2
0
Hadoop的大数据生态圈

基于Hadoop的大数据的产品圈 大数据产品的一句话概括 Apache Hadoop: 是Apache开源组织的一个分布式计算开源框架,提供了一个分布式文件系统子项目(HDFS)和支持MapReduce分布式计算的软件架...

zimingforever
今天
5
0
八大包装类型的equals方法

先看其中一个源码 结论:八大包装类型的equals方法都是先判断类型是否相同,不相同则是false,相同则判断值是否相等 注意:包装类型不能直接用==来等值比较,否则编译报错,但是数值的基本类型...

xuklc
今天
2
0
NoSQL , Memcached介绍

什么是NoSQL 非关系型数据库就是NoSQL,关系型数据库代表MySQL 对于关系型数据库来说,是需要把数据存储到库、表、行、字段里,查询的时候根据条件一行一行地去匹配,当量非常大的时候就很耗...

TaoXu
昨天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部