Python 学习笔记
来源:互联网 发布:啊哈算法pdf百度云 编辑:程序博客网 时间:2024/06/15 15:01
使用“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)]
列表推倒式(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,)
为了引发异常,可以使用一个类或者实例参数调用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 += 1enumerate 版本比左边的版本短得多也简单得多,而且也更加易读易理解。
下面这个例子展现 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.参数默认值
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__' 守护起来。
- 【python】:python学习笔记
- Python学习笔记-Python起步
- Python学习笔记-Python基础
- Python学习笔记-Python对象
- Python基本概念--Python学习笔记
- Python学习笔记:Python函数
- python学习笔记-python安装
- Python学习笔记--Python基础
- 【Python】python基础学习笔记
- python学习笔记3
- Python学习笔记
- Boost.Python学习笔记
- python学习笔记1
- python学习笔记2
- python学习笔记(2)
- Python学习笔记 Module
- Python学习笔记.
- python学习笔记(1)
- C++中:类数据成员的内存布局
- chukwa安装
- 延迟标记思想精讲
- 一个看似简单的数组地址问题
- 如何挑选鼠标
- Python 学习笔记
- jsp、servlet、javabean中如何分别设置session的过期时间
- ASP.Net简单页面方法加载顺序
- java封装类(一)
- spi(2)pxe8311+spi-altera+m25p驱动设计
- SVN linux 命令
- GeoServer源码解析和扩展 (二)注册服务
- org.eclipse.jdt.internal.core.JavaProject编辑器无法识别该类
- 调用相机拍照后返回照片过小的问题