首页 > 代码库 > Python的感悟笔记

Python的感悟笔记

杂项

  • Python是强类型的,在python中等号的语意是"绑定"将变量与实际对象
  • 没有++, --
  • 有+=
  • 修改str内容:s = s[:7] + 1 + s[8:] #修改s[7]
  • 成员函数不要忘记加self参数
  • 连接字符串和数字:s + str(1)
  • event.keysym =>得到按键的名称
  • Python中总共有三个“代”,所谓的三"代”就是三个链表,也就是我们上面所提到的可收集对象链表。当各个代中的对象数量达到一定数量时将触发Python的垃圾回收。
  • 分代收集的思想就是活的越久的对象,就越不是垃圾,回收的频率就应该越低。所以当Python发现进过几次垃圾回收该对象都是reachable,就将该对象移到二代中,以此类推。那么Python中又是如何检查各个代是否达到阀值的呢?Python中每次会从三代开始检查,如果三代中的对象大于阀值将同时回收3,2,1代的对象。如果二代的满足,将回收2,1代中的对象。

语法基础部分

字符串
  • 转义符:\
  • 自然字符串:r“…” 没有转义符的字符串
  • unicode字符串:u”..."
  • 字符串连接:’a’ ‘b’ => ‘ab’相邻放着的字符串会连接成一个新字符串
  • 没有char类型
字符串函数
  • s[0:2]截取子串0-1 #也可用于列表,元组
  • s[2]截取index=2的字母
  • s[0:-1]从头到倒数第二个
  • s[:-1]从头开始
  • s[-1:]到末尾
  • s[:]全部
  • s.strip():去除前面和后面的空格,并返回,s并不变
  • s.lstrip(‘,’)/rstrip():去除左边、右边的特定字符
  • 查找:s.index(‘123’,[l],[r])
  • 查找:s.find(‘123’,[l],[r]) 和index的不同:index没找到时会抛出异常,find会返回-1
  • 比较:cmp(s1, s2) :不在string模块中,相等时返回0
  • 共同子串长度:len(s1 and s2)
  • s = "abC ABc"
    print s.lower()
    print s.upper()
    print s.swapcase() #ABc abC
    print s.capitalize() #Abc abc
    print string.capwords(s) #Abc Abc
  • 翻转字符串:s[::-1]
  • 分割字符串:s[s.find(‘,’) + 1 : ]
  • 分割字符串:s.split(‘,’)
  • 连接字符串:delimiter = ‘,‘
    mylist = [‘Brazil‘, ‘Russia‘, ‘India‘, ‘China‘]
    print delimiter.join(mylist)
  • 子串个数:s.count(‘a’,[l],[r])
  • 替换:s.replace(‘a’, ‘b’, [count])
  • s.startswith(‘a’,[l],[r])
  • s.endswith(‘a‘,[l],[r])
  • s.islower()
  • s.isupper()
  • s.isalnum()
  • s.isalpha()
  • s.isdigit()
  • string.atoi(s,[base])
  • string.atol(s,[base])
  • string.atof(s,[base])
  • ‘a’ in s

控制流

  • for...else
for i in range(0,5):
     print (i)
else:
     print (“loop is over")
=>打印0,1,2,3,4,loop is over
range(l,r)不包含r,即代表[l,r)
  • while…else:和for...else类似
while True:
     if …:
          break
else:
     print (“loop is over”)
  • else语句总会执行,在for/while条件问False时执行且执行一次
运算符
  • **
  • // 取整除
  • 三段式表达式: val1 if con else val2
如果con为True:返回val1
如果con为False:返回val2
  • 类似的还有:con and val1 or val2
注意,如果val1为False时表达式不成立=》将val封装在list中
(con and [val1] or [val2] )[0]
  • list comprehension列表推导式:可以快速遍历列表
[函数(i) for i in 某个list]
[函数(i) for i in 某个list if cond(i)]
  • assert condition
  • repr:取得对象的字符串的规范表示,一般来说eval(repr(obj)) == obj

函数部分

  • 所有参数都是按值传递
def change1(x):
    x += 10

def change2(l):
    l.append([1,2,3,4]);
   
l = [10,20,30];
change2( mylist );
print my list  #[10, 20, 30, [1,2,3,4]]

x=1
change1(x)
print x #1
上l改变而x没变的原因是:
l是非内置类型,可以理解为指针,所以通过l的复制品l’,仍然指向相同的list
x是内置类型,所以按值传递的x’改变后,原x还是1
  • 作用域:规则和C一样
  • global x==>全局域中有x,则可以访问该x,否则因为作用域的原因,会创建函数作用域内的x
  • nonlocal x 类似,一般用于嵌套函数中
  • 默认参数值:规则和C一样
def fun(x, y=0, z=1): ...
  • 不定长参数:用*表示 | 用**表示
def varl(x, *listparam):
传入方法:     varf(x, 10, 20) #listparam=[10,20]
def vard(x, **dicparam)
 传入方法:      varf(x, y=1, z=2)#dicparam={y:1, z:2}
  • 关键参数:可以使用名字来规定某个默认参数的值
fun(1, z=3) #跳过某个参数
fun(z=3, x=1) #乱序传参数
  • 返回值:规则和C一样
  • docString:类似文档的作用
def docf():
     ‘’ this is docf’‘
printdocf.__doc__#this is doc注意,没有调用函数,而是直接写函数名
  • 匿名函数
sum =lambdaarg1, arg2: arg1 + arg2;#只能是一个表达式,不能访问global,不能包含多个表达式,不能print
print sum(1,2)
  • 嵌套函数
def f1():
     def f2(): ...
     f2()
f2可以访问f1的变量,修改=>记得作用域、内置类型、非内置类型
可以在f2中用nonlocal x声明f1中的内置类型变量x
  • 闭包
嵌套函数,并且外部函数返回嵌套函数
def f1(a3):
   a1 = 1
   a2 = [1]
   def inf():
      #nonlocal a1, a2
      a1 += 2 #报错
      a3 += 2 #报错
      a2[0] += 2
      return a1, a2, a3
   return inf
a3 = 2
a = f1(a3)
t = a()
注意:1. 对f1中的非内置类型,在f2中直接修改
           2. 对f1中内置类型,需要加上nonlocal才能在f2中修改
  • 迭代器,生成器和yield
  • 迭代器:实现迭代器接口的可以用for循环读取内容
  • 生成器:包含yield语句的函数会被编译成生成器,不像一般的函数会生成值后退出,生成器函数在生成值后会自动挂起并暂停他们的执行和状态,他的本地变量将保存状态信息,这些信息在函数恢复时将再度有效
def gen(n):
     for i in range(n):
          yield i * 2
for i in gen(3):
     print i
也可以通过 i = gen(3)=>i.next()访问下一个内容
gen.close()提前关闭生成器
def gen2():
     val = yield 1
     print val #content
     val = yield 2
     print val #nothing
g = gen2()
print g.next()#1
print g.send(‘content‘)#2
通过g.send(…)传给生成器一个值,注意第一次必须用next
  • 内置函数http://jianfeihit.iteye.com/blog/1835272

模块部分

  • 每个Python模块都有它的__name__,如果它是‘__main__‘,这说明这个模块被用户单独运行,我们可以进行相应的恰当操作。
xx.py:
if __name__ == ‘__main__‘:
    print ‘This program is being run by itself’ #python xx.py
else:
    print ‘I am being imported from another module’ #import xx
  • 当Python遇到导入语句时,首先检查某块是否已经导入(sys.moudles),如果已经导入就直接使用,如果没有,那么:
0. 创建一个新的空模块对象(其实是个字典);
1. 将这个对象加入sys.modules字典中;
2. 载入模块的代码对象(如果必要会进行编译);
3. 在新的模块命名空间中执行代码并分配到相应的模块对象上;
4. 如果将模块当做脚本来运行,将会在__main__之后载入模块。
  • 内置模块、标准模块:安装完Python便有的
  • 扩展模块:自定义或者外部安装的模块

面向对象部分

  • Python中所有类成员都是公共的,所有方法都是有效的
  • 成员名字加__,如__xx则为私有:访问会报错
  • __del__:析构
  • __init__:构造
  • __str__:在我们对对象使用print语句或是使用str()的时候调用
  • __lt__(self, other): 当使用 小于 运算符(<)的时候调用。类似地,对于所有的运算符(+,>等等)都有特殊的方法
  • __getitem__(self,key): 使用x[key]索引操作符的时候调用
  • __len__:对序列对象使用内建的len()函数的时候调用
  • 调用父函数:super
还记得之前的体系吗
class Derived(Base):
     def __init__(self):
          Base.__init__()
通过这种方法调用Base的函数,缺点是如果Base改名了,所有继承自Base的类都需要改
现在可以通过super(Derived, self).__init__()调用了,但是有以下注意点
1. Base必须继承自object,否则报错
2. 所有继承体系中必须都用super()否则会出问题
3. super会保证存在多继承時所有構造函数调用一次且只一次,按照拓扑排序顺序调用
4. super并不是一个函数,是一个类名,形如super(B, self)事实上调用了super类的初始化函数,产生了一个super对象
  • 类属性:
class A:
     i = 0
i为A的类属性,可以通过A.i的方式访问i
class A:
    i = 0
    def __init__(self, c):
        self.i = c
print A.i #0
a = A(1)
print A.i #0
print a.i #1
这是因为self.i生成了一个非static的同名的i
那如何才能改A.i那?相信大家已经猜到了,将self.i改为A.i即可
此时打印的结果为0 1 1
  • property =>提供getter和setter
class A(object):
    def __init__(self):
        self.__x=None
    @property
    def x(self):
        return self.__x
    @x.setter
    def x(self,value):
        self.__x=value
    @x.deleter
    def x(self):
        del self.__x
注意:
1. A需要继承自object
2. @property相当于getter
  • 类方法:
@classmethod
def classf(cls):...
调用时可以通过类的实例.classf()
或者通过类.classf()均可,不需要参数
可以访问类属性,不能访问实例属性
  • 静态方法:
@staticmethod
 def staticmd():...
静态方法:无法访问类属性、实例属性,相当于一个相对独立的方法,跟类其实没什么关系。
  • 命名空间
python搜索一个标识符的顺序是"LEGB"
L(local):表示在一个函数定义中,而且在这个函数里面没有再包含函数的定义。
E(enclosing function):表示在一个函数定义中,但这个函数里面还包含有函数的定义,其实L层和E层只是相对的。
G(global):是指一个模块的命名空间,也就是说在一个.py文件中定义的标识符,但不在一个函数中。
B(builtin):是指python解释器启动时就已经具有的命名空间,之所以叫builtin是因为在python解释器启动时会自动载入__builtin__模块,这个模块中的list、str等内置函数的就处于B层的命名空间中。
对于Python built-in names组成的命名空间,它在Python解释器启动的时候被创建,在解释器退出的时候才被删除;
对于一个Python模块的global namespace,它在这个module被import的时候创建,在解释器退出的时候退出;
对于一个函数的local namespace,它在函数每次被调用的时候创建,函数返回的时候被删除。
这里需要注意的一点是,nonlocal和global是不一样的
nonlocal会从里向外找
global会直接定位于模块命名空间内
  • 方法和函数的区别:(来源http://www.v2ex.com/t/38692)
方法是一种特殊的函数。
python中,函数(方法)并不是依附与类才能存在。函数并不只是在类中定义。这种直接在模块中而不是类中定义的函数(方法),叫做函数。
方法(method),是依附于类的,他们定义在类中,是属于类的,但是他们本质上,还是一个函数。方法的第一个参数不一定必须是self。
这么说吧,凡是def foo()这种,都是函数,在类中定义的函数,就是方法。
总结:
方法:类内普通方法,类方法
函数:普通函数,类内的静态方法
  • 多态性:和C++的多态性不一样
C++是静态语,在编译时绑定,多态是指运行时多态,即使用指向子类的父类指针,可以调用子类函数
Python是动态语言,在运行时绑定,它的多态是指随时可以通过setattr这样的方法添加属性,方法,类似反射?(http://www.cnblogs.com/brucejia/archive/2013/05/16/3082112.html)

异常部分

  • 捕捉异常:
try: ….
except xxException / (exception1, exception2):
     处理特定错误的逻辑
except:
     处理其他错误的逻辑
[else:]
[finally:]
  • 引发异常:
raise xxException
在except语句中添加raise传递异常
  • 自定义异常:
class myException(Exception):
     ...
使用时 raise myException(参数…)
            try:...
            except myException, e: e.xxx  #自定义属性


Python的感悟笔记