第24章 高级模块话题
在模块中隐藏数据
最小化from * 的破坏:_X和__all__
from *语句只会把列在__all__列表中的这些变量名复制出来。如果没有定义__all__,from *就会复制出开头没有下划线的所有变量名。
_X __all__列表只对from *语句这种形式有效。
混和用法模式:__name__ 和 __main__
如果文件以顶层程序文件执行,在启动时,__name__就会设置成字符串”__main__”。
如果文件被导入,__name__就会改设成客户端了解的模块名。
__name__充当一个使用模式标志,允许它编写成一个可导入的库和一个顶层脚本。
以__name__进行单元测试
在__name__检查区块内封装了自我测试的调用,使其在文件作为顶层脚本执行时才会启动,而导入则不会。
使用带有__name__的命令行参数
import sys
sys.argv 字符串列表包含了命令行参数,第一项总是将要运行的脚本的名称。
修改模块的搜索路径
import sys
sys.path 在程序启动时就会初始化,如果修改,只在修改的python会话或程序中才会存续,在Python结束后,不会保留下来。PYTHONPATH和.pth文件路径配置是保存在操作系统中,而不是执行中的python程序。
Import语句和from语句的as扩展
import nodulemane as name
相当于:
import modulename
name = modulename
del modulename
from modulename import attrname as name
用名称字符串导入模块
modname = “string”
import modname #err
string = __import__(modname)
模块设计理念
需要思考哪些函数要放进模块、模块通信机制等。当开始编写较大的Python系统时,就会变得明朗起来。
模块陷阱
顶层代码的语句次序的重要性
在导入时,模块文件顶层的程序代码一旦python运行到时,就会立刻执行。因此,该语句不能引用文件后面的变量名。
位于函数主体内的代码直到函数被调用到后才会运行。因为函数内的变量名在函数实际执行前都不会解析,通常可以引用文件内任意地方的变量。
from复制变量名,而不是连接
from *会让变量语义模糊
在from 语句中明确列出想要的属性,如果使用import而不是from,也可以避开这个问题。
reload不会影响from导入,且最佳原则就是不要将它们结合起来使用。使用reload和import
第25章 OOP:宏伟蓝图
在Python中,OOP完全是可选的,在初级阶段不需要使用类。简单的脚本代码,可以做很多事。^_^
做长期python产品开发的人对类更感兴趣一些。
为何使用类
大的用处:
继承、组合
用类建立新对象:
多重实例、通过继承进行定制、运算符重载
概览OOP
属性的继承搜索
python中大多OOP的用法,都可以简化成object.attribute。用类对象调用这个表达式读取属性或调用对象的方法时,python启动搜索。搜索对象连接的树,来寻找attribute首次出现的对象。由下向上,由左到右。
类:类是实例工厂,类的属性提供了行为,所有从类产生的实例都继承该类的属性。
实例:代表程序领域中具体的元素。实例属性记录数据,而每个特定对象的数据都不同。
类方法调用
I2.w() 调用映射为C3.w(I2), Python把隐含的实例传进方法中的第一个特殊的参数,习惯上将其称为self.
编写类树
每个class语句会生成一个新的类对象。
每次类调用,就会生成一个新的实例对象。
实例自动连接到创建了这些实例的类。
类连接至其超类的方式是,将超类列在类头部的括号内从左到右的顺序会决定树中的次序。
__init__构造函数
OOP是为了代码重用
大体而言,OOP就是在树中搜索属性。
事实上,应用领域中所谓的软件框架,就是把常见程序设计任务实现成类,可以让你在应用程序中混合。利用软件框架,只需编写子类,填入所需的一两个方法。
第26章 类代码编写基础
类对象提供默认行为
class语句创建类对象并将其赋值给变量名,就像def应用,class语句一般是在其所在文件导入时执行的。
class语句内的赋值语句会创建类的属性。
类属性提供对象的状态和行为。类对象的属性可由类所创建的所有实例共享。
实例对象是具体的元素
像函数那样调用类对象会创建新的实例对象。
每个实例对象继承类的属性并获得了自己的命名空间。
在类方法内对self属性做赋值运算会产生每个实例自己的属性。
类通过继承经行定制
超类列在了类开头的括号中。
类从其超类中继承了属性。
实例会继承所有可以读取的类的属性。
每个object.attribute都会开启新的独立搜索。
逻辑的修改是通过创建子类,而不是修改超类。
树中较低发生的重新定义的,取代属性的动作称为覆盖。
类是模块内的属性
类可以获取python运算符
运算符可以让类与Python的对象模型相集成。重载类型运算时,以类实现的用户定义对象的行为就会像内置对象一样。因此,提供了一致性,以及与预期接口的兼容性。
第27章 更多实例
步骤1:创建实例
在Python中,模块使用小写字母开头,类名使用一个大写字母开头。
编写构造函数
实例对象的属性,它们通过给类方法函数中的self属性赋值来创造。在__init__构造函数方法中将它们赋值给self,在每次创建一个实例时,Python会自动运行__init__代码。
在进行中测试
在进行中测试比编写大量代码后再一次性测试要更自然。类似UT。
以两种方式使用代码,以免import时运行不必要的测试代码
class Person: def __init__(self,name,job=None,pay=0): self.name = name self.job = job self.pay = pay if __name__ == ‘__main__’: #self-test code |
步骤2:添加行为方法
编写方法
步骤3:运算符重载
例子,提供打印显示
步骤4:通过子类定制行为
编写子类
扩展方法
继续、定制和扩展
步骤5:定制构造函数
person.py
from classtools import AttrDisplay class Person(AttrDisplay): “”” Create and process person record “”” def __init__(self,name,job=None,pay=0): self.name = name self.job = job self.pay = pay def lastName(self): return self.name.split()[-1] def giveRaise(self,percent): self.pay = int(self.pay * (1+percent)) class Manager(Person): “”” A customized Person with special requirements “”” def __init__(self, name, pay): Person.__init__(self, name, ‘mgr’, pay) def giveRaise(self, percent, bonus = 0.1) Person.giveRaise(self, percent + bonus) if __name__ == ‘__main__’: #test-code bob = Person(‘Bob Smith’) print(bob) |