Python 学习笔记

来源:互联网 发布:啊哈算法pdf百度云 编辑:程序博客网 时间:2024/06/15 15:01
1.9 模块
    使用“from模块import函数”这种形式的import命令之后,就可以直接使用函数,而不是需要模块作为前缀。
     nan是一特殊值“not a number"的简写
1.11
    值转化为字符串的两种机制:(1)通过str函数,他会把值转化为合理形式的字符串,以便用户理解。(2)repr会创建一个字符串,他以合法的python表达式的形式来表示值。
    input :输入要求的是合法的python表达式,

    raw_input:它会把所有的输入当作原始数据,然后将其放在字符串中。  

name = input("what is your name?")#what is your name?pet#NameError: name 'pet' is not defined    name = raw_input("what is your name?")#what is your name?pet#ok  
如果需要一个非常长的字符串,它需要跨行,可以使用三个引号代替普通引号。
    如果一行之中最后一个字符是反斜线,那么换行符本身就是“转义”了。
    原始字符串不会把"\"当作特殊符号处理。在原始字符串中输入的每个字符都会与书写方式保持一致。原始字符串以r开头。
    不能在原始字符串的结尾输入反斜线。
    python中的普通字符串在内部是以8位的ASCII码形成存储的,而unicode字符串则存储为16位Unicode字符。
2.1
    序列和映射是两类主要的容器,序列中的每个元素都有自己的编号,映射中的每个元素则有一个名字。

2.2.4

   有的时候可能需要一个值来代表空值——意味着没有在里面放置任何元素。这个时候需要使用None。

sequence = [None]*10

2.4.3  元组的意义

由于以下两个原因,元组不可替代:

    元组可以在映射(和集合的成员)中当作键使用——而列表不行。

    元组作为很多内建函数和方法的返回值存在,也就是说必须对元组进行处理。只要不修改元组,那么“处理”元组在绝大多数情况下就是把它们当作列表来进行操作。


5.3 赋值魔法

    序列解包:将多个值的序列解开,然后放到变量的序列中去。

x,y,z = 1,2,3

   链式赋值: x = y = somefunction()

   增量赋值:x += 1

   同一性运算符

>>>x = y = [1,2,3]>>>z = [1,2,3]>>> x == y>>> True>>> x is y>>> True>>> x is z>>> False
   == 运算符用来判定两个对象是否相等,is判定两者是否等同

迭代工具

   并行迭代,zip

>>> names = ['anne','beth','george','damon']>>> ages = [12,45,32,102]>>> zip(names,ages)[('anne', 12), ('beth', 45), ('george', 32), ('damon', 102)]


5.6 列表推倒式

   列表推倒式(list comprehension)是利用其他列表创建新的列表的一种方法,他的工作方法类似于for循环。

>>> [x*x for x in range(10)][0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> [x*x for x in range(10) if x % 3 ==0][0, 9, 36, 81]

5.7 三人行

   pass 有的时候程序什么也不用做,就可以使用pass

   del:删除的只是名称。事实上,在Python中没有办法删除值,也不需要删除值,因为在某个值不再使用的时候,Python解释器会负责内存的回收

>>> x = 1>>> y = x>>> x1>>> y1>>> del x>>> y1
  使用exec和eval.exce会执行一系列的python语句,而eval会计算python表达式的值。

6.3

    记录函数:如果在函数的开头写下字符串,他就会作为函数的一部分进行存储,这称为文档字符串。

>>> def square(x):...     'Caculates the square of the number x.'...     return x*x... 
>>> square.__doc__'Caculates the square of the number x.'

   当两个变量同时引用一个列表的时候,他们的确是同时引用一个列表。如果想避免这种情况,可以复制一个列表的副本。当在序列中做切片的时候,返回的切片总是一个副本。因此,如果你复制了整个列表的切片,将会得到一个副本。

>>> names = ['Mrs Entity','Mrs.Thing']>>> n = names[:]>>> n is namesFalse>>> n == namesTrue>>> n = names>>> n is namesTrue>>> n == namesTrue>>> 
6.4 收集参数

>>> def print_params(*params):...     print params... >>> print_params(1,2,3)(1, 2, 3)>>> 
参数的星号将所有值放置在同一个数组单元中。可以说是将这写值收集起来,然后使用。

>>> def print_params(title,*params):...     print title...     print params... >>> print_params('Params:',1,2,3)Params:(1, 2, 3)>>> 
所以星号的意思是:收集其余的位置参数。但是不能处理关键词参数。

>>> print_params('Hmm...',something=42)Traceback (most recent call last):  File "<stdin>", line 1, in <module>TypeError: print_params() got an unexpected keyword argument 'something'
另外的一个可以处理关键词参数的“收集”操作

>>> def print_params(**params):...     print params... >>> print_params(x=1,y=2,z=3){'y': 2, 'x': 1, 'z': 3}

>>> def print_params(x,y,z=3,*pospar,**params):...     print x,y,z...     print pospar...     print params... >>> print_params(1,2,3,4,5,6,7,foo=1,bar=2)1 2 3(4, 5, 6, 7){'foo': 1, 'bar': 2}
7.1任何不知道对象到底是什么类型,但是又要对对象“做点什么”的时候,就会用到多态。

      唯一能够毁掉多态的就是使用函数显示的检查类型,比如type,isinstance以及issubclass函数等。

    这里的多态也称作是“鸭子模式”

     封装不同与多态,多态可以让用户对于不知道是什么类的对象进行方法调用,而封装是可以不用关心对象是如何构建的而直接进行使用。

7.2 python并不直接支持私有的方式,而要靠程序员自己把握在外部进行特征修改的时机。毕竟在使用对象前应该知道如何使用。但是,可以使用一些小技巧达到私有特性的效果。为了让方法或者特性变为私有(外部无法访问),只要在他的名字前面加上双下划线即可。如果想要知道已知类的基类(们),可以直接使用他的特殊特性__bases__ 。如果只是想知道一个对象属于那个类,可以使用__class__特性

    如果需要查看一个类是否是另一个类的子类,可以使用内建的issubclass函数

In [49]: issubclass(SPAMFilter,Filter)Out[49]: True
In [51]: SPAMFilter.__bases__Out[51]: (__main__.Filter,)


8.1  什么是异常,每个异常都是一些类的实例,这些实例可以被引发,并且可以用很多中方法进行捕捉

    为了引发异常,可以使用一个类或者实例参数调用raise语句。使用类时,程序会自动创建实例。

>>> raise ExceptionTraceback (most recent call last):  File "<stdin>", line 1, in <module>Exception>>> raise Exception('hyperdrive overload')Traceback (most recent call last):  File "<stdin>", line 1, in <module>Exception: hyperdrive overload
    第一个例子raise Exception引发了一个没有任何有关错误信息的普通异常,后一个例子中,则添加了一些hyperdrive overload错误信息。

    异常处理并不复杂。如果知道某段代码可能会导致某种异常,而又不希望程序一堆栈的形式跟踪的形式终止,那么就根据需要添加的try/except或者try/finally语句进行处理。

9.1 python中,有的名称会在前面和后面都加上两个下划线,例如__future__,这种名字组成的集合所包含的方法称为魔法方法。这种方法会在特殊的情况下调用。

    为了确保类是新型的,应该把赋值语句__metaclass__= type 放在你的模块的最开始。

9.2 python中创建一个构造方法很容易,只要吧init方法的名字从简单的init修改成__init__即可。 python中有一个方法叫做析构方法 __del__.

    如果一个方法在B类的一个实例中被调用,但在B类中没有找到该方法,那么就会去它超类A里面找。

    重写是继承机制的一个重要内容,大多数子类不仅要拥有自己的初始化代码,还拥有超类的初始化代码。虽然重写的机制对于所有方法都一样,但是处理构造方法重写时,会遇到一个问题:如果一个类构造方法被重写,那么就需要调用超类的构造方法,否则对象可能不会被正确的初始化。

>>> class Bird:...     def __init__(self):...             self.hungry = True...     def eat(self):...             if self.hungry:...                     print 'Aaah...'...                     self.hungry = False...             else:...                     print 'No,thanks!'... >>> b = Bird()>>> b.eat()Aaah...>>> b.eat()No,thanks!>>> class SongBird(Bird):...     def __init__(self):...             self.sound = 'Squawk!'...     def sing(self):...             print self.sound... >>> sb = SongBird()
>>> sb.sing()Squawk!>>> sb.eat()Traceback (most recent call last):  File "<stdin>", line 1, in <module>  File "<stdin>", line 5, in eatAttributeError: SongBird instance has no attribute 'hungry'>>> 

这里,SongBird没有hungry属性。为了达到与其的效果,SongBird的构造方法必须调用其超类Bird的构造方法来确保进行基本的初始化。有两种方法可以达到这个目的:调用超类构造方法的未绑定版本,或者使用super函数。

调用超类方法的未绑定版本:

>>> class SongBird(Bird):...     def __init__(self):...             Bird.__init__(self)...             self.sound = 'Squawk!'...     def sing(self):...             print self.sound... >>> sb = SongBird()>>> sb.sing()Squawk!>>> sb.eat()Aaah...>>> sb.eat()No,thanks!>>> 
    这样结果的原因:在调用一个实例方法时,该方法的self参数会被自动绑定到实例上,但如果直接调用类的方法(比如Bird.__init__),那么就没有实例会被绑定。这样就可以自由的提供所需要的self参数。这样的方法称为未绑定方法。

    super函数

    当前类和对象可以作为super函数的参数使用,调用函数返回的对象的任何方法都是调用超类的方法,而不是当前类的方法。

#!/usr/bin/python#coding=utf-8__metaclass__ = type # super函数只在新式类中起作用class Bird:        def __init__(self):                self.hungry = True        def eat(self):                if self.hungry:                        print 'Ahhhaa...'                        self.hungry = False                else:                        print 'NO,thanks!'class SongBird(Bird):        def __init__(self):                super(SongBird,self).__init__()                self.sound = 'Squawk!'        def sing(self):                print self.soundsb = SongBird()sb.sing()sb.eat()sb.eat()
Squawk!Ahhhaa...NO,thanks!
</pre><p>代码风格:</p><p>1.python命名:</p><p>函数、方法、属性用小写+下划线(joined_lower)</p><p>常量用小写+下划线形式(joinde_lower)或大写+下划线形式(ALL_CAPS)</p><p>类用首字母大写的方式(StudlyCaps)</p><p>驼峰命名法(camelCase)仅仅用于符合事先存在的约定</p><p>属性:接口(公开属性)interface,内部属性_internal,私有属性__private。尽量避免使用私有属性形式。</p><p>2.长代码&续行</p><p>保持每行长度不超过80个字符。在括号\方括号\大括号里使用隐式续航。</p><p>在最后加上反斜杠显式续航。</p><p>3.字典的 get 方法</p><p>We often have to initialize dictionary entries before use: 通常我们需要在使用之前初始化一个字典。</p><p>这是比较幼稚的做法:</p><p></p><pre code_snippet_id="221079" snippet_file_name="blog_20150205_26_7143387" name="code" class="python">navs = {}for (portfolio, equity, position) in data:    if portfolio not in navs:        navs[portfolio] = 0    navs[portfolio] += position * prices[equity]
dict.get(key, default) 移除了对条件判断的需要:

navs = {}for (portfolio, equity, position) in data:    navs[portfolio] = (navs.get(portfolio, 0)                       + position * prices[equity])

4.真值测试

# 这样做:         # 不要这样做:if x:             if x == True:    pass              pass
这种方法优雅且高效的利用了Python对象内置的真值。
测试一个列表:
# 这样做:         # 不要这样做:if items:         if len(items) != 0:    pass              pass                  # 千万不要这样做:                  if items != []:                      pass

5.索引和项 (2): enumerate

函数 enumerate 接受一个list,并返回 (索引值, 项) 对:
>>> print list(enumerate(items))[(0, 'zero'), (1, 'one'), (2, 'two'), (3, 'three')]
输出结果时,我们得用一个 list 进行一下包装,因为 enumerate 是一个惰性函数: 它仅仅在需要时才一次产生一项,一个索引项对。 for 循环就是一个一次需要一个结果的所在。 enumerate 是 生成器(generator) 的一个例子,我们将会在以后详细的讲解生成器。 print 不是一次拿一个结果 —— 我们需要整个结果,所以我们在打印时, 必须显式的将一个生成器转换为一个list。
我们的循环变得简单多了:

for (index, item) in enumerate(items):    print index, item

# 对比:                 # 对比:index = 0               for i in range(len(items)):for item in items:              print i, items[i]    print index, item    index += 1
enumerate 版本比左边的版本短得多也简单得多,而且也更加易读易理解。

下面这个例子展现 enumerate 函数实际上是如何返回一个迭代器(iterator)的 (生成器就是一种迭代器):

>>> enumerate(items)<enumerate object at 0x011EA1C0>>>> e = enumerate(items)>>> e.next()(0, 'zero')>>> e.next()(1, 'one')>>> e.next()(2, 'two')>>> e.next()(3, 'three')>>> e.next()Traceback (most recent call last):  File "<stdin>", line 1, in ?StopIteration

6.参数默认值

这是一个初学者常见的错误。甚至一些有经验的程序员, 如果他们没有理解Python「名字」,也会犯同样的错误
def bad_append(new_item, a_list=[]):    a_list.append(new_item)    return a_list
问题在于 a_list 的默认值,一个空列表,是在函数定义时被求值的。 所以每次调用这个函数,我们得到的是同一个默认值。试试重复做几次:

>>> print bad_append('one')['one']
>>> print bad_append('two')['one', 'two']

列表是一个可变对象;我们可以改变它们的内容。 得到一个默认列表的正确方法是在运行时创建,在函数内部:

def good_append(new_item, a_list=None):    if a_list is None:        a_list = []    a_list.append(new_item)    return a_list

7.列表推导

列表推导解法:

total = sum([num * num for num in range(1, 101)])

生成器表达式解法:

total = sum(num * num for num in xrange(1, 101))

生成器表达式(Generator expressions) (「genexps」) 跟列表推导很像, 不过列表推导是贪婪的,而生成器表达式是惰性的。列表推导一次性计算出 整个列表的全部结果,并以列表形式返回。生成器表达式只会在需要时一次计算一个数据, 以一个单独的值形式返回。这对于那种对很长的序列求解, 但计算结果只是中间步骤而并非最终结果的情况特别有用。

在上面的例子中,我们只关心求和的结果,我们不需要列表中每个元素平方的中间结果。 基于同样的理由,我们使用了 xrange :它惰性产生结果,每次一个。

8.按键值排序

Python 2.4 为 sort 列表方法引入了一个可选参数,「key」, 用于指定一个单参数函数来返回列表中每个元素用于比较的键值。举例来说:

def my_key(item):    return (item[1], item[3])to_sort.sort(key=my_key)
函数 my_key 会在操作 to_sort 列表每一个项时都调用一次。


You can make your own key function, or use any existing one-argument function if applicable: 你可以实现自己的key函数,或者在可能的情况下使用已经存在的单参数函数:


str.lower 可以用于按忽略大小写的字母顺序排序。
len 可以用于按项的长度排序 (字符串或容器)。

int 或 float 可以用于对那些「数字型字符串」,比如 "2", "123", "35" 之类, 按实际数字大小排序。

9.模块和脚本

想制作一个既是可导入的模块又是可执行的脚本:

if __name__ == '__main__':
    # script code here
当模块被导入时,它的 __name__ 属性被设置成模块的文件名,不含「.py」。 因此上面那段用 if 语句守护着的代码不会在导入时被执行。 当以脚本形式执行的时候, __name__ 属性会被设置称 "__main__", 这段脚本代码 会 运行。




除了一些特殊情况,你不应该在最顶层放置任何重要可执行代码。 将代码放入函数、类、方法,或者用 if __name__ == '__main__' 守护起来。







0 0
原创粉丝点击