1. 问题:将所有代码放入一个py文件:无法维护

方案:如果将代码才分放到多个py文件,好处:

1. 同一个名字的变量互相不影响

2.易于维护

3.引用模块: import module

2.包:解决可能有同名的py文件存在的情况

p1.util   vs   p2.util

引用的时候必须加上包名

1. 在python 文件中,一个包中间必须有一个__init__.py文件,并且是每一个目录下面必须存在这个文件。(即使该文件为空,也是必须存在的)这个是区分包与普通目录之间的区别

3. python 提供 模块管理工具,用来管理第三方模块

easy_install - pip(已经内置到Python2.7.9)

使用方法: pip install web.py

4. python面向对象编程

基本思想: 类 和 实例 (根据类创建)

重要: 数据封装

class Person:

#构造函数,初始化

def __init__(self,name):

self.name = name;

p1 = Person("Xiao Ming")

p2 = Person("Xiao Hong")

5.构造一个类

class Person(object):

pass

# 创建了一个类 Person ,并且该类继承自object

6. 在定义 Person 类时,可以为Person类添加一个特殊的__init__()方法,当创建实例时,__init__()方法被自动调用,我们就能在此为每个实例都统一加上以下属性:

 class Person(object):
def __init__(self, name, gender, birth):
self.name = name
self.gender = gender
self.birth = birth

7. 访问限制

问题:如果有些属性不希望被外部访问到怎么办?

Python对属性权限的控制是通过属性名来实现的,如果一个属性由双下划线开头(__),该属性就无法被外部访问。看例子:

class Person(object):
def __init__(self, name):
self.name = name
self._title = 'Mr'
self.__job = 'Student'
p = Person('Bob')
print p.name
# => Bob
print p._title
# => Mr
print p.__job
# => Error
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Person' object has no attribute '__job'

可见,只有以双下划线开头的"__job"不能直接被外部访问。

但是,如果一个属性以"__xxx__"的形式定义,那它又可以被外部访问了,以"__xxx__"定义的属性在Python的类中被称为特殊属性,有很多预定义的特殊属性可以使用,通常我们不要把普通属性用"__xxx__"定义。

8. 创建类属性

绑定在一个实例上的属性不会影响其他实例,但是,类本身也是一个对象,如果在类上绑定一个属性,则所有实例都可以访问类的属性,并且,所有实例访问的类属性都是同一个!也就是说,实例属性每个实例各自拥有,互相独立,而类属性有且只有一份。

定义类属性可以直接在 class 中定义:

class Person(object):
address = 'Earth'
def __init__(self, name):
self.name = name
因为类属性是直接绑定在类上的,所以,访问类属性不需要创建实例,就可以直接访问:
print Person.address
# => Earth 对一个实例调用类的属性也是可以访问的,所有实例都可以访问到它所属的类的属性:
p1 = Person('Bob')
p2 = Person('Alice')
print p1.address
# => Earth
print p2.address
# => Earth 由于Python是动态语言,类属性也是可以动态添加和修改的:
Person.address = 'China'
print p1.address
# => 'China'
print p2.address
# => 'China'
因为类属性只有一份,所以,当Person类的address改变时,所有实例访问到的类属性都改变了。
修改类属性会导致所有实例访问到的类属性全部都受影响,但是,如果在实例变量上修改类属性会发生什么问题呢?
class Person(object):
address = 'Earth'
def __init__(self, name):
self.name = name p1 = Person('Bob')
p2 = Person('Alice') print 'Person.address = ' + Person.address p1.address = 'China'
print 'p1.address = ' + p1.address print 'Person.address = ' + Person.address
print 'p2.address = ' + p2.address

结果如下:

Person.address = Earth
p1.address = China
Person.address = Earth
p2.address = Earth

我们发现,在设置了 p1.address = 'China' 后,p1访问 address 确实变成了 'China',但是,Person.address和p2.address仍然是'Earch',怎么回事?

原因是 p1.address = 'China'并没有改变 Person 的 address,而是给 p1这个实例绑定了实例属性address ,对p1来说,它有一个实例属性address(值是'China'),而它所属的类Person也有一个类属性address,所以:

访问 p1.address ,优先查找实例属性,返回'China'。

访问 p2.address ,p2没有实例属性address,但是有类属性address,因此返回'Earth'。

可见,当实例属性和类属性重名时,实例属性优先级高,它将屏蔽掉对类属性的访问。

当我们把 p1 的 address 实例属性删除后,访问 p1.address 就又返回类属性的值 'Earth'了:

del p1.address
print p1.address
# => Earth

可见,千万不要在实例上修改类属性,它实际上并没有修改类属性,而是给实例绑定了一个实例属性。

9. Python 类型继承

基类:

Class Person(object):

def __init__(self,name,gender):

self.name = name

self.gender = gender

继承类 Student

Class Student(Person)

def _init__(self,name,gengder,course):

super(Student,self).__init__(name,gender)

self.course = course

一定要用 super(Student, self).__init__(name, gender) 去初始化父类,否则,继承自 Person 的 Student 将没有 name 和 gender

函数super(Student, self)将返回当前类继承的父类,即 Person ,然后调用__init__()方法,注意self参数已在super()中传入,在__init__()中将隐式传递,不需要写出(也不能写)。

9.1 使用isinstance() 方法来判断对象的类型

函数isinstance()可以判断一个变量的类型,既可以用在Python内置的数据类型如str、list、dict,也可以用在我们自定义的类,它们本质上都是数据类型。

假设有如下的 Person、Student 和 Teacher 的定义及继承关系如下:

class Person(object):
def __init__(self, name, gender):
self.name = name
self.gender = gender class Student(Person):
def __init__(self, name, gender, score):
super(Student, self).__init__(name, gender)
self.score = score class Teacher(Person):
def __init__(self, name, gender, course):
super(Teacher, self).__init__(name, gender)
self.course = course p = Person('Tim', 'Male')
s = Student('Bob', 'Male', 88)
t = Teacher('Alice', 'Female', 'English')

当我们拿到变量 p、s、t 时,可以使用 isinstance 判断类型:

>>> isinstance(p, Person)
True # p是Person类型
>>> isinstance(p, Student)
False # p不是Student类型
>>> isinstance(p, Teacher)
False # p不是Teacher类型

这说明在继承链上,一个父类的实例不能是子类类型,因为子类比父类多了一些属性和方法。

我们再考察 s :

>>> isinstance(s, Person)
True # s是Person类型
>>> isinstance(s, Student)
True # s是Student类型
>>> isinstance(s, Teacher)
False # s不是Teacher类型

s 是Student类型,不是Teacher类型,这很容易理解。但是,s 也是Person类型,因为Student继承自Person,虽然它比Person多了一些属性和方法,但是,把 s 看成Person的实例也是可以的。

这说明在一条继承链上,一个实例可以看成它本身的类型,也可以看成它父类的类型。

10. python 类型继承之多态

类具有继承关系,并且子类类型可以向上转型看做父类类型,如果我们从 Person 派生出 StudentTeacher ,并都写了一个 whoAmI() 方法:

class Person(object):
def __init__(self, name, gender):
self.name = name
self.gender = gender
def whoAmI(self):
return 'I am a Person, my name is %s' % self.name class Student(Person):
def __init__(self, name, gender, score):
super(Student, self).__init__(name, gender)
self.score = score
def whoAmI(self):
return 'I am a Student, my name is %s' % self.name class Teacher(Person):
def __init__(self, name, gender, course):
super(Teacher, self).__init__(name, gender)
self.course = course
def whoAmI(self):
return 'I am a Teacher, my name is %s' % self.name

在一个函数中,如果我们接收一个变量 x,则无论该  Person、Student还是 Teacher,都可以正确打印出结果:

def who_am_i(x):
print x.whoAmI() p = Person('Tim', 'Male')
s = Student('Bob', 'Male', 88)
t = Teacher('Alice', 'Female', 'English') who_am_i(p)
who_am_i(s)
who_am_i(t)

运行结果:

I am a Person, my name is Tim
I am a Student, my name is Bob
I am a Teacher, my name is Alice

这种行为称为多态。也就是说,方法调用将作用在 x 的实际类型上。s 是Student类型,它实际上拥有自己的 whoAmI()方法以及从 Person继承的 whoAmI方法,但调用 s.whoAmI()总是先查找它自身的定义,如果没有定义,则顺着继承链向上查找,直到在某个父类中找到为止。

10.1 多重继承

除了从一个父类继承外,Python允许从多个父类继承,称为多重继承。

多重继承的继承链就不是一棵树了,它像这样:

class A(object):
def __init__(self, a):
print 'init A...'
self.a = a class B(A):
def __init__(self, a):
super(B, self).__init__(a)
print 'init B...' class C(A):
def __init__(self, a):
super(C, self).__init__(a)
print 'init C...' class D(B, C):
def __init__(self, a):
super(D, self).__init__(a)
print 'init D...'

看下图:

像这样,同时继承自 B 和 C,也就是 D 拥有了 A、B、C 的全部功能。多重继承通过 super()调用__init__()方法时,A 虽然被继承了两次,但__init__()只调用一次:

>>> d = D('d')
init A...
init C...
init B...
init D...

多重继承的目的是从两种继承树中分别选择并继承出子类,以便组合功能使用。

举个例子,Python的网络服务器有TCPServer、UDPServer、UnixStreamServer、UnixDatagramServer,而服务器运行模式有 多进程ForkingMixin 和 多线程ThreadingMixin两种。

要创建多进程模式的 TCPServer

class MyTCPServer(TCPServer, ForkingMixin)
pass

要创建多线程模式的 UDPServer

class MyUDPServer(UDPServer, ThreadingMixin):
pass

如果没有多重继承,要实现上述所有可能的组合需要 4x2=8 个子类。

未完待续//////////

最新文章

  1. 3.密码pasuwado————记第一次超越Candy?
  2. 《SharePoint 2013 应用开发实战》目录
  3. Dynamics AX 2012 R2 Business Connector Error
  4. Obj格式解析以及在Unity3D下导入测试
  5. Array操作方法和String操作方法比较
  6. php 格式化数字 位数不足前面加0补足
  7. JavaScript下拉框去除重复内容
  8. iOS 两种方法实现左右滑动出现侧边菜单栏 slide view
  9. iOS 多线程编程之Grand Central Dispatch(GCD)
  10. Java 之 Servlet介绍(Java之负基础实战)
  11. asp.net在类库中使用EF 6.0时的相关配置
  12. linux 上安装多个不同版本的mysql 踩的坑
  13. 记忆(缓存)函数返回值:Python 实现
  14. 『转载』判断一个正整数是不是素数,时间复杂度为O(根号n)
  15. layui使用记录
  16. VA_X安装
  17. jquery改变元素上下排列的顺序
  18. 《转载》Tomcat内存设置详解
  19. sql笔试练习
  20. 原生Js弹窗插件|web弹出层组件|对话框

热门文章

  1. 命名空间$.fn
  2. windows界面库种类
  3. JQuery筛选器全系列介绍
  4. 搭建nginx+tomcat+Java的负载均衡环境
  5. null
  6. mybatis入门总结
  7. 批量转换编码 (gbk -&gt; utf8)
  8. 【原作】关于Dynpro中的红绿灯显示
  9. Javascript学习笔记2.2 Javascript与DOM选项卡(滑动门)案例详解
  10. MT5:放大市场价格指标