python核心编程第二版

来源:互联网 发布:linux netstat命令详解 编辑:程序博客网 时间:2024/05/29 23:45

第三章 python基础

模块结构布局

起始行
模块文档
模块倒入
变量定义
类定义
函数定义
主程序

main是放置测试代码的好地方

垃圾收集

python解释器会负责跟踪对象的引用计数,当引用计数为0时,垃圾收集器会负责释放内存。垃圾收集器也会负责清理那些虽然引用计数大于0,但也应该被销毁的对象

第四章 python对象

type()的返回值是对象,事实上,type类型是python所有类型的根,也是所有python标准类的元类


用户创建的类实例如果定义了nonzero(nonzero())或length(len())且值为0,那么它们的布尔值就是false

>>> class A(object):    def __len__(ob):        return 0>>> a = A()>>> bool(a)False

int和str类型是不可改变的,所以python会缓存常用的int类型,当我们试图创建a,b两个值为1的对象时,其实对象并没有被创建,只是引用了已缓存的对象这时候a is b或者id(a)==id(b)的值都是True

第五章 数字

所谓工厂函数是指:这些内建函数都是类对象,当你调用它们时,实际上是创建了一个类实例

第六章 序列:字符串,列表和元组

切片操作:第三个参数是步长,list1[::-1] 视为翻转操作

python默认所有的编码都是ASCII,可以通过在字符串前面加u前缀的方式声明inicode字符串。如果一个unicode字符串被当做参数传给str()函数,那么这个unicode会先被转换成ASCII字符串再交给str()函数,如果该unicode字符串中有不被ASCII支持的字符,会导致异常。而新的内建函数unicode()和unichar()可以看做unicode版本的str()和char(),它们会把python的任何数据类型转换为一个unicode字符串。

unicode和utf-8关系:unicode每个字符要占用两个字节,utf-8是为解决unicode占用空间较大的一种编码方式,utf-8变长编码的,当字符在ASCII码的范围时,就用一个字节表示,保留了ASCII字符一个字节的编码做为它的一部分,注意的是unicode一个中文字符占2个字节,而UTF-8一个中文字符占3个字节)。从unicode到uft-8并不是直接的对应,而是要过一些算法和规则来转换 (https://www.zhihu.com/question/23374078)

unicode字符串处理原则
程序中出现字符串时在前面加u
不要使用str()函数,使用unicode()
不到必要时不使用encode和decode,除非在读写文件或数据库时
pickle模块对unicode的支持很差
当使用%s时,会把字符串中的unicode对象执行str(默认编码)
举例

>>> u'%s %s' %(u'a', 'a')u'a a'>>> a = u'%s' %('哈哈'.decode('gbk'))>>> au'\u54c8\u54c8'>>> print a哈哈>>> u'哈哈'u'\xb9\xfe\xb9\xfe'      # gbk编码>>> '哈哈''\xb9\xfe\xb9\xfe'>>> '哈哈'.decode('gbk')u'\u54c8\u54c8'          # unicode编码

对list使用 + 会新建一个list,而extend()方法是把新列表加到了原有列表里面

浅拷贝和深拷贝

浅拷贝只是拷贝了对象的引用实现:(1)切片 [:]  (2)工厂函数  list()  dict()(3)copy.copy()深拷贝copy.deepcopy()

第八章 条件和循环

条件表达式(三元操作符): x if y else z

迭代器

迭代器是一种支持next()操作的对象。它包含一组元素,当执行next()操作时,返回其中一个元素;当所有元素都被返回后,生成一个StopIteration异常。生成器是一种迭代器,是一种特殊的函数,使用yield操作将函数构造成迭代器。普通的函数有一个入口,有一个返回值;当函数被调用时,从入口开始执行,结束时返回相应的返回值。生成器定义的函数,有多个入口和多个返回值;对生成器执行next()操作,进行生成器的入口开始执行代码,yield操作向调用者返回一个值,并将函数挂起;挂起时,函数执行的环境和参数被保存下来;对生成器执行另一个next()操作时,参数从挂起状态被重新调用,进入上次挂起的执行环境继续下面的操作,到下一个yield操作时重复上面的过程。迭代器不能向后移动,不能回到开始,也不能复制  reversed()函数会返回一个反序访问的迭代器,enumerate()也会返回一个迭代器创建迭代器list_a = [1,2,3]i = iter(list_a)i.next()对字典创建迭代器myDict.iterkeys()  myDict.itervalues()  myDict.iteritems()对文件创建迭代器f = open('file', 'r')for eachline in f:        print eachline    # 这样会自动调用readline()方法

列表解析

在一定程度上,列表解析可以取代map()和lambda,而且效率更高[x ** 2 for x in range(10) if x % 2][(x, y) for x in range(10) for y in range(10)]

生成器表达式

生成器表达式是列表解析的一个扩展,列表解析的一个不足是必须一次创建整个list。生成器表达式的使用方法和列表解析很相似,但是并不真正创建list,而是返回一个生成器。((x, y) for x in range(10) for y in range(10))

第十一章 函数和函数式编程

python中的过程就是函数,因为解释器会隐式的返回None。没有返回值的函数也会隐式返回None

函数式编程
lambda
a = lambda x, y:x + y

filter() 不管他,用列表解析吧
map() 不管他,用列表解析吧
reduce():取出序列的前两个数,返回结果,与第三个数做运算,以此类推
reduce((lambda:x, y:x + y),range(5))

第十二章 模块

名称空间

a.py  www = 'abc'def show():    print wwwb.py  from a import www,showwww = '123'  # 这是不改变a的www的值的show()import aa.www = '123'  # 这是改变a的www的值的a.show()这里所说的改变,指的是模块a的名称空间里www的值,不是a.py文件里www的值


init 里面的 all 指定 from a import * 时会导入的模块

绝对导入:必须使用sys.path中的路径
相对导入:from ..a import b
第一个据点标明是相对导入

from a import * 不会导入以 _ 开始的属性

PYTHONCASEOK环境变量指定不区分大小写的导入

当遇到循环导入的问题时,可以把其中一个导入写到函数的内部,解决导入失败的问题

第十三章 面向对象编程

self参数代表的是实例对象本身,类中的一般方法需要这个参数,而类中的静态方法或类方法不需要  __init__ 方法类似于类构造器,在实例化的过程中,__init__ 方法会被调用  dir(Myclass)返回对象属性的一个名字列表,而Myclass.__dict__返回的是一个字典。vars(Myclass)实现了Myclass.__dict__  类的特殊属性  Myclass.__name__  类名  Myclass.__doc__  文档字符串  Myclass.__bases__  其父类构成的元组  Myclass.__dict__  类的属性  Myclass.__module__  类所在的模块  Myclass.__class__  实例对应的类__new__方法在 __init__方法之前被调用,它比__init__更像一个构造器,暂时没用到  __del__ 解构器,用它干嘛,不用  在类属性中有静态变量的时候,实例会直接访问类的静态变量,在实例中改变这个静态变量的值,会影响到类属性,这个要小心  静态方法,不需要传参数  @staticmethod  def foo():    print 'a'  类方法,传递cls作为参数  @classmethod  def foo(cls):    print 'a'实例方法,传递self作为参数  def foo(self):    print 'a'  class C(P):    def __init__(self):        super(C, self).__init__() # 这样能调用C的父类的__init__  使用__new__方法返回两位小数  class RoundFloat(float):    def __new__(cls, val):        return super(RoundFloat, cls).__new__(cls, round(val, 2))issubclass()  # 判断一个类是否是另一个类的子类isinstance()  # 判断一个对象是否是给定类的实例hasattr() getattr() setattr() delattr()  # *attr系列方法操作给出的对象和属性13.13 用特殊方法定制类简单定制# coding:utf-8class RoundFloatManual(object):    '''    保留两位小数    上面的__new__ 实现保留两位小数的例子,因为继承自float,所以__str__等方法不需要自己去实现,少踩好多坑    '''    def __init__(self, val):        assert isinstance(val, float), "value must be a float"  # 断言,判断输入是否为float类型        self.value = round(val, 2)    # a = RoundFloatManual(2.033),当你实现__str__方法后,print a 显示的是 str(self.value),否则显示的是实例对象    def __str__(self):          return str(self.value)    # a = RoundFloatManual(2.033),当你实现__repr__方法后,RoundFloatManual 显示的是 str(self.value),否则显示的是实例对象    # __repr__ = __str__   这样写的另一个好处是,DRY    __repr__ = __str__  数值定制# coding:utf-8class Time60(object):    '''    操作时间, 精确到小时和分    '''    def __init__(self, hr, min):        self.hr = hr        self.min = min    def __str__(self):        return '%d:%d' %(self.hr, self.min)    __repr__ = __str__    def __add__(self, other):        '''重载运算符 +'''        # self.class 代表实例化的类,调用self.class与调用Time60()是一样的        return self.__class__(self.hr + other.hr, self.min + other.min)    def __iadd__(self, other):        '''重载 += 运算符'''        self.hr += other.hr        self.min += other.min        return self   # 重载 __i*__时必须返回self私有化__  双下划綫开始的属性,在运行时会将类名加到属性前,这更多的是防止同名冲突_   单下划线开始的属性,来防止from a import *,这是基于作用域的,所以也适用于类授权getattr(my_class, "class_function")和my_class.class_function调用的都是 __getattr__方法。授权的关键就是覆盖__getattr__方法。__getattr__的工作方式是:当搜索一个属性时,先搜索局部字典,再搜索类名称空间,如果都没有搜索到,则调用__getattr__方法处理新式类的高级特性isinstance(obj, int)并没有进行严格的匹配,如果obj是一个给定类型的实例或其子类的实例,也会返回True。严格匹配使用is__slots__属性,可以替代__dict__,使用__slots__时用户不能增加__slots__中不存在的属性,并且节约内存__getattribute__,使用这个函数对类的属性做访问,先不管property :更好的控制对实力属性的访问,没找到场景,略元类和__metaclass__元类用来定义某些类是如何创建的在执行类定义时,解释器会去寻找类属性__metaclass__(还有其他步骤,略),将这个属性赋值给此类作为元类元类是为程序员服务的,它可以强制程序员在定义类时做某些操作# coding:utf-8from time import ctime# 一个类的定义过程,其实就是完成某些工作print "start Metac"class MetaC(type):    def __init__(cls, name, bases, attrd):        super(MetaC, cls).__init__(name, bases, attrd)        print "create class %r at: %s" %(name, ctime())print "\tClass Foo next"class Foo(object):    __metaclass__ = MetaC # 在定义类的时候,这里就执行了。__init__需要在实例化的时候才执行    def __init__(self):        print "instantiated class %r at:%s" %(self.__class__.__name__, ctime())print "\tClass Foo instantiation next."f = Foo()print "\tDone"

第十四章 执行环境

call : 在类中实现call方法后,类实力就成为可调用的对象,调用的就是call

callable(a) :判断a是否可以通过函数操作符()调用

compile()  允许在运行时声称函数对象,然后通过eval() , exec()等执行可求值表达式,和eval()一起使用eval_code = compile('100 + 200', '', 'eval')eval(eval_code)单一可执行语句,和exec()一起使用single_code = compile('print "hello"', '', 'single')exec(single_code)可执行语句组,通过exec()执行exec_code = compile('''for i in range(10):    print i''', '', 'exec')exec(exec_code)

第十八章 多线程编程

进程:进程是程序的一次执行,每个进程都有自己的地址空间,内存等,操作系统管理这些进程,为这些进程公平的分配时间

线程:线程运行在一个进程中,共享运行环境,对于单CPU,每个线程也是被安排成执行一小会

对一些例子做的测试和注释

1.基本使用# coding:utf-8import threadingfrom time import sleep, ctimeloops = [4, 2]def loop(nloop, nsec):    print 'start loop', nloop, 'at:', ctime()    sleep(nsec)    print 'loop', nloop, 'done at:', ctime()def main():    print 'starting at:', ctime()    threads = []    nloops = range(len(loops))    for i in nloops:        t = threading.Thread(target=loop, args=(i, loops[i])) # target 函数入口        threads.append(t)    for i in nloops:        threads[i].start()  # 开始线程执行    for i in nloops:        threads[i].join()  # 程序挂起,直到线程结束    print 'all DONE at:', ctime()if __name__ == '__main__':    main()2.传一个实例作为线程启动的时候执行# coding:utf-8import threadingfrom time import sleep, ctimeloops = [4, 2]class ThreadFunc(object):    def __init__(self, func, args, name=''):        self.name = name        self.func = func        self.args = args    def __call__(self):        self.func(*self.args)def loop(nloop, nsec):    print 'start loop', nloop, 'at:', ctime()    sleep(nsec)    print 'loop', nloop, 'done at:', ctime()def main():    print 'starting at:', ctime()    threads = []    nloops = range(len(loops))        for i in nloops:        t = threading.Thread(target=ThreadFunc(loop, (i, loops[i]), loop.__name__))        threads.append(t)    for i in nloops:        threads[i].start()    for i in nloops:        threads[i].join()    print 'all DONE at:', ctime()if __name__ == '__main__':    main()
0 0
原创粉丝点击