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__()方法被自动调用,我们就能在此为每个实例都统一加上以下属性:

  1. class Person(object):
  2. def __init__(self, name, gender, birth):
  3. self.name = name
  4. self.gender = gender
  5. self.birth = birth

7. 访问限制

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

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

  1. class Person(object):
  2. def __init__(self, name):
  3. self.name = name
  4. self._title = 'Mr'
  5. self.__job = 'Student'
  6. p = Person('Bob')
  7. print p.name
  8. # => Bob
  9. print p._title
  10. # => Mr
  11. print p.__job
  12. # => Error
  13. Traceback (most recent call last):
  14. File "<stdin>", line 1, in <module>
  15. AttributeError: 'Person' object has no attribute '__job'

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

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

8. 创建类属性

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

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

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

结果如下:

  1. Person.address = Earth
  2. p1.address = China
  3. Person.address = Earth
  4. 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'了:

  1. del p1.address
  2. print p1.address
  3. # => 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 的定义及继承关系如下:

  1. class Person(object):
  2. def __init__(self, name, gender):
  3. self.name = name
  4. self.gender = gender
  5.  
  6. class Student(Person):
  7. def __init__(self, name, gender, score):
  8. super(Student, self).__init__(name, gender)
  9. self.score = score
  10.  
  11. class Teacher(Person):
  12. def __init__(self, name, gender, course):
  13. super(Teacher, self).__init__(name, gender)
  14. self.course = course
  15.  
  16. p = Person('Tim', 'Male')
  17. s = Student('Bob', 'Male', 88)
  18. t = Teacher('Alice', 'Female', 'English')

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

  1. >>> isinstance(p, Person)
  2. True # p是Person类型
  3. >>> isinstance(p, Student)
  4. False # p不是Student类型
  5. >>> isinstance(p, Teacher)
  6. False # p不是Teacher类型

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

我们再考察 s :

  1. >>> isinstance(s, Person)
  2. True # s是Person类型
  3. >>> isinstance(s, Student)
  4. True # s是Student类型
  5. >>> isinstance(s, Teacher)
  6. False # s不是Teacher类型

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

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

10. python 类型继承之多态

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

  1. class Person(object):
  2. def __init__(self, name, gender):
  3. self.name = name
  4. self.gender = gender
  5. def whoAmI(self):
  6. return 'I am a Person, my name is %s' % self.name
  7.  
  8. class Student(Person):
  9. def __init__(self, name, gender, score):
  10. super(Student, self).__init__(name, gender)
  11. self.score = score
  12. def whoAmI(self):
  13. return 'I am a Student, my name is %s' % self.name
  14.  
  15. class Teacher(Person):
  16. def __init__(self, name, gender, course):
  17. super(Teacher, self).__init__(name, gender)
  18. self.course = course
  19. def whoAmI(self):
  20. return 'I am a Teacher, my name is %s' % self.name

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

  1. def who_am_i(x):
  2. print x.whoAmI()
  3.  
  4. p = Person('Tim', 'Male')
  5. s = Student('Bob', 'Male', 88)
  6. t = Teacher('Alice', 'Female', 'English')
  7.  
  8. who_am_i(p)
  9. who_am_i(s)
  10. who_am_i(t)

运行结果:

  1. I am a Person, my name is Tim
  2. I am a Student, my name is Bob
  3. I am a Teacher, my name is Alice

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

10.1 多重继承

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

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

  1. class A(object):
  2. def __init__(self, a):
  3. print 'init A...'
  4. self.a = a
  5.  
  6. class B(A):
  7. def __init__(self, a):
  8. super(B, self).__init__(a)
  9. print 'init B...'
  10.  
  11. class C(A):
  12. def __init__(self, a):
  13. super(C, self).__init__(a)
  14. print 'init C...'
  15.  
  16. class D(B, C):
  17. def __init__(self, a):
  18. super(D, self).__init__(a)
  19. print 'init D...'

看下图:

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

  1. >>> d = D('d')
  2. init A...
  3. init C...
  4. init B...
  5. init D...

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

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

要创建多进程模式的 TCPServer

  1. class MyTCPServer(TCPServer, ForkingMixin)
  2. pass

要创建多线程模式的 UDPServer

  1. class MyUDPServer(UDPServer, ThreadingMixin):
  2. pass

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

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

python 面向对象编程学习的更多相关文章

  1. python面向对象编程学习

    python面向对象编程 基本概念理解 面向对象编程--Object Oriented Programming,简称OOP,是一种程序设计思想.OOP把对象作为程序的基本单元,一个对象包含了数据和操作 ...

  2. python 面向对象编程学习总结

    面向对象是个抽象的东西,概念比较多,下面会一一介绍. 一.类和实例 类(Class)和实例(Instance)是面向对象最重要的概念. 类是指抽象出的模板.实例则是根据类创建出来的具体的“对象”,每个 ...

  3. Python面向对象编程指南

    Python面向对象编程指南(高清版)PDF 百度网盘 链接:https://pan.baidu.com/s/1SbD4gum4yGcUruH9icTPCQ 提取码:fzk5 复制这段内容后打开百度网 ...

  4. Python 面向对象编程 继承 和多态

    Python 面向对象编程 继承 和多态 一:多继承性 对于java我们熟悉的是一个类只能继承一个父类:但是对于C++ 一个子类可以有多个父亲,同样对于 Python一个类也可以有多个父亲 格式: c ...

  5. 图解python | 面向对象编程

    作者:韩信子@ShowMeAI 教程地址:http://www.showmeai.tech/tutorials/56 本文地址:http://www.showmeai.tech/article-det ...

  6. python 面向对象编程(一)

    一.如何定义一个类 在进行python面向对象编程之前,先来了解几个术语:类,类对象,实例对象,属性,函数和方法. 类是对现实世界中一些事物的封装,定义一个类可以采用下面的方式来定义: class c ...

  7. python面向对象编程进阶

    python面向对象编程进阶 一.isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的对象 1 ...

  8. Python面向对象编程(下)

    本文主要通过几个实例介绍Python面向对象编程中的封装.继承.多态三大特性. 封装性 我们还是继续来看下上文中的例子,使用Student类创建一个对象,并修改对象的属性.代码如下: #-*- cod ...

  9. Python 面向对象编程——访问限制

    <无访问限制的对象> 在Class内部,可以有属性和方法,而外部代码可以通过直接调用实例变量的方法来操作数据,这样,就隐藏了内部的复杂逻辑.但是,从前面Student类的定义来看(见:Py ...

随机推荐

  1. Java 中如何原样输出转义符号

    Java 中的转义字符有好几种,常见的有: 八进制转义字符,格式:\ + 1到3位八进制数字,如\1, \20,范围为 \0 ~ \377,即最大值为255. Unicode转义字符,格式:\u + ...

  2. 在后台启动受管服务器经常报错:Server may already be running

    报错如下: 1. Unable to obtain lock on /usr/local/odrive/odrive_chen/Middleware/user_projects/domains/oim ...

  3. table中的th td margin不生效

    margin-top,margin-left,margin-right,margin-bottom 是body中的属性th,td 是表格的元素与之对应的是padding-top,padding-lef ...

  4. mysql授权

    grant all privileges on testdb to userA@'%' 然而通过userA登录查看存储过程时仍然无权限查看,通过jdbc连接程序也报错, 之前mysql在windows ...

  5. myeclipse下构建maven web项目

    首先创建一个Maven的Project如下图 我们勾选上Create a simple project (不使用骨架) 这里的Packing 选择 war的形式 由于packing是war包,那么下面 ...

  6. merge into在oracle10g和oracle 11g中的使用差别一

    oracle10g上的代码 MERGE INTO TCGGYSGHCP CP    USING (SELECT *             FROM (SELECT QD.LIFNR,         ...

  7. UI测试 错题分析

    从服务器端获取的json对象,可以直接访问对象中的属性 该属性的作用就是C text属性显示节点文本,state属性默认为open 看错行  不能用 ' ' 包裹 state:节点状态,'open' ...

  8. thinkPHP的用法之M

    M方法 //添加 $res = M('comment')->add($data); //成功返回新增ID,失败返回false //删除 M('myop_myinvite')->where( ...

  9. Winform 文本框多线程赋值

    delegate void SetTextCallback(string text); private void showClientMsg(string text) { // InvokeRequi ...

  10. ASP.NET 教程(一)

    ASP.NET 是一个开发框架,用于通过 HTML.CSS.JavaScript 以及服务器脚本来构建网页和网站. ASP.NET 支持三种开发模式: Web Pages.MVC (Model Vie ...