http://bkeep.blog.163.com/blog/static/12341429020107155719916/
目录:
-------------------------------------------------------------
第11章 面向对象的编程
1,重要概念:
2,通过例子观察类的定义
?查看MyClass类的所有属性(即它包含哪些方法)
?显示__dict__方法的功能
3,下面列举一些特殊的类属性
4,几个内置方法的作用
5,理解self
6,【重点!self、类、实例化】创建一个类,看看它是如何工作的
7,使用对象的方法
8,__init__方法实验
9,类与对象的方法
10,【重点】继承(老师和学生的例子)
实验1:错误示例
实验2:正确示例
正文:
-------------------------------------------------------------
http://linux.chinaitlab.com/manual/Python_chinese/ch11.html
类:物以类聚,具有相同属性的对象就叫类!
对象/实例:万物皆对象
#python
Python 2.4.3 (#1, Sep 17 2008, 16:07:08)
[GCC 4.1.2 20071124 (Red Hat 4.1.2-41)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> class MyClass(object): # 定义一个叫MyClass的类
... 'MyClass class definition' #类定义
... myVersion = '1.1' #静态数据
... def showMyVersion(self): #注意,在类里面不叫函数,叫方法。它不能被直接引用,只能通过类来调用!
... print MyClass.myversion
【理解self原理】假如,你有一个类称为MyClass和这个类的一个实例MyObject。当你调用这个对象的方法MyObject.method(arg1, arg2)的时候,这会由Python自动转为MyClass.method(MyObject, arg1, arg2)——这就是self的原理了。self指的就是实例名MyObject明白呼?
>>> dir(MyClass)
['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__', 'myVersion', 'showMyVersion']
>>> MyClass.__dict__
>>> print MyClass.__dict__
{'__module__': '__main__', 'showMyVersion':
C.__name__ 类C的名字
C.__doc__ 类C的文档字符串
C.__bases__ 类C的所有父类构成的元组
C.__dict__ 类C的属性
C.__module 类C定义所在的模块
C.__class__ 类C对应的类
当类被调用,实例化的第一步是创建实例对象,python检查是否实现了__init__()方法;
和上面说的一样__init__() __new__() 叫做“构造器”,__del__() 叫“解构器”。
【理解self原理】假如,你有一个类称为MyClass和这个类的一个实例MyObject。当你调用这个对象的方法MyObject.method(arg1, arg2)的时候,这会由Python自动转为MyClass.method(MyObject, arg1, arg2)——这就是self的原理了。self指的就是实例名MyObject明白呼?
昨天看不懂的问题,今天一看就看懂了!哈哈
类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称,但是在调用这个方法的时候你不为这个参数赋值,Python会提供这个值。这个特别的变量指对象本身,按照惯例它的名称是self。
看看下面这个例子就明白了!
示例1:
>>> class firstclass: //创建一个类 firstclass
... def setdata(self,value): //定义setdata方法
... self.data = value
... def display(self): //定义display方法
... print self.data
...
>>> x = firstclass() //实例化firstclass类, x,y是一个到firstclass的链接
>>> y = firstclass()
>>> x.setdata("hello") //self为x, firstclass.setdata(x,”hello”), 传递来的变量hello赋给了self.data,也就是x.data=hello
>>> y.setdata("323") //y.data = 323 看到了吧,firstclass就这样被复用了! self指的是类名,并非函数名!切忌!
>>> x.display() //执行的是print x.data 输出当然就是hello 了
hello
>>> y.display() //执行的是print y.data 输出的是 323
323
超类,子类;名字相同则覆盖,没有则继承!
>>> class secondclass(firstclass): //把超类括在括号类
... def display(self): //firstclass中的setdata被继承,display被覆盖!
... print 'current value = %s' % self.data
...
>>> z = secondclass() //实例化secondclass,也就是z到它的链接
>>> z.setdata(88) //用继承的方法赋值,结果为 z.data = 88
>>> z.display() //执行print 'current value = %s' % z.data
current value = 88
示例2:
#cat simplestclass.py
#!/usr/bin/python
class Person: #创建Person类
pass #没有任何动作
p = Person() #创建一个对象/实例,注意格式,把类赋值给变量后面再带个圆括号
print p #打印出这个对象,
运行结果:
#python simplestclass.py
<__main__.Person instance at 0x2b1bf961cef0> #告诉我们在__main__模块总有了一个Person类的实例。
#cat method.py
#!/usr/bin/python
class Person:
def sayHi(self): # 在类里面,这个叫方法,不叫函数!注意,第一个参数必须是self!
print 'Hello,how are U ?'
p = Person()
p.sayHi() #注意,这里没有传递参数,但后面可以打印出来内容,说明它自己调用了一个self参数。
运行结果:
#python method.py
Hello,how are U ?
__init__方法在类的一个对象被建立时,马上运行。这个方法可以用来对你的对象做一些你希望的初始化。
注意,这个名称的开始和结尾都是双下划线。
#cat class_init.py
#!/usr/bin/python
class Person:
def __init__(self,name): #暂时就记住方法第一个变量叫self
self.name = name #要调用方法中的变量,就采用self.name这种方式!
def sayHi(self): #只有一个变量的时候那便是self
print 'Hello,my name is',self.name #上一个方法中的变量被传递过来了?
p = Person('bkeep') #把Person类给实例化了,并且把 ‘bkeep’字符串被传递给name变量
p.sayHi() # 理解一下:我们此时只调用了sayHi方法,但__init__已经默认被执行!
运行结果:
#python class_init.py
Hello,my name is bkeep
有两种变量,类的变量和对象的变量。这也定义了这些变量的有效范围即作用域。
·类的变量由一个类的所有对象(实例)共享使用。只有一个类变量的拷贝,所以当某个对象对类的变量做了改动的时候,这个改动会反映到所有其他的实例上。
·对象的变量 不是共享的,只在自己域内改变。
【重点例子:】使用类与对象的变量
#cat objvar.py
#!/usr/bin/python
class Person:
'''Represents a person.'''
population = 0 # 类的变量,这个类的所有对象共享,谁都可以修改它的值。
def __init__(self,name): # 这个方法在实例化类的时候运行,对象的变量好像只在这里定义!
'''' Initializes the person's data.'''
self.name = name #self.name,后面的方法都这样调用name变量。难道self指的是Person类??
print '(Initializing %s)' % self.name
Person.population += 1 //类的变量 类名.变量名
def __del__(self): #这个方法在该类的实例运行结束时执行!它是最后一个动作。
'''I am dying.'''
print '((%s says bye.))' % self.name
Person.population -= 1 #我们利用__del__方法来修改类变量。
if Person.population == 0:
print '((I am the last one.))'
else:
print '((There are still %d people left.))' % Person.population
def sayHi(self):
'''Greeting by the person.
Really, that's all it does.'''
print 'Hi, my name is %s.' % self.name #self指的是Person类,而不是sayHi方法!
def howMany(self):
'''Prints the curent population.'''
if Person.population == 1:
print 'I am the only person here.'
else:
print 'We have %d persons here.' % Person.population
bkeep = Person('bkeep') //实例化Person类,并传入参数bkeep,同时触发__init__(注意它是在这步触发的)
bkeep.sayHi() //调用sayHi方法
bkeep.howMany() //调用howMany方法.
keke = Person('keke') //实例化Person类,并传入参数keke,同时触发__init__(注意它是在这步触发的)
keke.sayHi() //调用sayHi方法
keke.howMany() //调用howMany方法.
bkeep.sayHi() //这一步没有实例化Person类,所有不触发__init__,故Person.population数值不变!!
bkeep.howMany()
//到这里整个就执行完了,默认执行__del__ ,此时依次清楚keke 和bkeep,并打印出相关信息!(这里是先进先出原则)。这个例子告诉我们__init__, __del__的执行时机,类的全局变量是如何变化的。
输出结果: 这里有些报错。不知道咋回事!!!
#python objvar.py
(Initializing bkeep)
Hi, my name is bkeep.
I am the only person here.
(Initializing keke)
Hi, my name is keke.
We have 2 persons here.
Hi, my name is bkeep.
We have 2 persons here.
((keke says bye.))
Exception exceptions.AttributeError: "'NoneType' object has no attribute 'population'" in
((bkeep says bye.))
Exception exceptions.AttributeError: "'NoneType' object has no attribute 'population'" in
程序功能:记录学校教师和学生信息
分析:教师的属性(姓名、年龄、工资);学生的属性(姓名、年龄、分数)
设计:准备设计三个类,SchoolMember记录公共属性(姓名、年龄);Teacher类继承/复用SchoolMember类记录教师的所有属性;Student类继承/复用SchoolMember类记录学生的所有属性。
#cat inherit.py
#!/usr/bin/python
class SchoolMember: # 定义一个父类,供其它类来继承。
'''Represents any school member.'''
def __init__(self,name,age): #name和age是公共属性,定义在这里
self.name = name #定义调用变量(name)的方法
self.age = age
print '(Initialized SchoolMember:%s)' % self.name #
def tell(self):
''' The my details.'''
print 'Name:"%s" Age:"%s"' % (self.name,self.age), # 这里有个逗号,为了后面继承时显示在同一行!
class Teacher(SchoolMember):
'''Represents a teacher.'''
def __init__(self,name,age,salary): #声明Teacher类中的所有属性
SchoolMember.__init__(self,name,age) #继承SchoolMember类对name和age变量的定义
self.salary = salary # 定义调用salary的方法
print '(Initialized Teacher: %s)' % self.name
def tell(self):
SchoolMember.tell(self) #动作一:执行SchoolMember.tell方法
print 'Salary: "%d"' % self.salary #动作二:打印Salary变量,注意,这里跟上面的输出在同一行。
class Student(SchoolMember):
'''Represents a student.'''
def __init__(self,name,age,marks):
SchoolMember.__init__(self,name,age)
self.marks = marks
print '(Initialized Student: %s)' % self.name
def tell(self):
SchoolMember.tell(self)
print 'Marks:"%d"' % self.marks
t = Teacher('Zheng.binbin',40,30000) #实例化Teacher对象,此时传入相应参数
s = Student('Zheng.haoyu',15,90) #实例化Student对象,此时传入相应参数
print #打印一个空行
members = [t,s] #定义列表其项目便是t和s实例
for member in members:
member.tell() # 哈哈t.tell 和 s.tell,你再想想他们的工作过程,一下子就明白了!
运行结果:
#python inherit.py
(Initialized SchoolMember:Zheng.binbin)
(Initialized Teacher: Zheng.binbin)
(Initialized SchoolMember:Zheng.haoyu)
(Initialized Student: Zheng.haoyu)
Name:"Zheng.binbin" Age:"40" Salary: "30000"
Name:"Zheng.haoyu" Age:"15" Marks:"90"
【重点】【拓展:】上面类之间的调用都在一个模块里面,我们想在多个模块之间继承类的属性怎么办呢?实验1是个错误示例!实验2 才是正确的做法。从中我们理解了文件、模块-à类-à方法之间的关系!
1, SchoolMember.py模块
#!/usr/bin/python
class SchoolMember:
'''Represents any school member.'''
def __init__(self,name,age):
self.name = name
self.age = age
print '(Initialized SchoolMember:%s)' % self.name
def tell(self):
''' The my details.'''
print 'Name:"%s" Age:"%s"' % (self.name,self.age),
2, Teacher.py 模块
#!/usr/bin/python
import SchoolMember
class Teacher(SchoolMember):
'''Represents a teacher.'''
def __init__(self,name,age,salary):
SchoolMember.__init__(self,name,age)
self.salary = salary
print '(Initialized Teacher: %s)' % self.name
def tell(self):
SchoolMember.tell(self)
print 'Salary: "%d"' % self.salary
3,Student.py模块
#!/usr/bin/python
import SchoolMember
class Student(SchoolMember):
'''Represents a student.'''
def __init__(self,name,age,marks):
SchoolMember.__init__(self,name,age)
self.marks = marks
print '(Initialized Student: %s)' % self.name
def tell(self):
SchoolMember.tell(self)
print 'Marks:"%d"' % self.marks
4,class_zbb.py 模块
#!/usr/bin/python
import Teacher
import Student
t = Teacher('Zheng.binbin',40,30000)
s = Student('Zheng.haoyu',15,90)
members = [t,s]
for member in members:
member.tell()
5,#python class_zbb.py 运行结果:
Traceback (most recent call last):
File "class_zbb.py", line 10, in ?
import Teacher
File "/usr/local/bkeep/Teacher.py", line 13
'''Represents a teacher.'''
^
SyntaxError: invalid syntax
看到错误提示1:
class_zbb.py文件里面第10行,执行了一条命令import Teacher。这里又涉及到/usr/local/bkeep/Teacher.py文件,该文件的第13行有语法错误! 呵呵vi Teacher.py +13去看看这行到底啥语法错误!原来是没有定义类!
看到错误提示2:
Traceback (most recent call last):
File "class_zbb.py", line 10, in ?
import Teacher
File "/usr/local/bkeep/Teacher.py", line 12, in ?
class Teacher(SchoolMember):
TypeError: Error when calling the metaclass bases //元类有问题,哈哈SchoolMember是一个模块,不是类!
module.__init__() takes at most 2 arguments (3 given)
修改办法:class Teacher(SchoolMember): --à改为class Teacher(SchoolMember. SchoolMember):
1,SchoolMember.py模块,不做修改
#!/usr/bin/python
class SchoolMember:
'''Represents any school member.'''
def __init__(self,name,age):
self.name = name
self.age = age
print '(Initialized SchoolMember:%s)' % self.name
def tell(self):
''' The my details.'''
print 'Name:"%s" Age:"%s"' % (self.name,self.age),
2,Teacher.py模块
#!/usr/bin/python
import SchoolMember //注意,这里导入的仅仅是模块,即文件!
class Teacher(SchoolMember.SchoolMember): //要继承类,必须给类名前加模块名即模块名.类名
'''Represents a teacher.'''
def __init__(self,name,age,salary):
SchoolMember.SchoolMember.__init__(self,name,age)
self.salary = salary
print '(Initialized Teacher: %s)' % self.name
def tell(self):
SchoolMember.SchoolMember.tell(self)
print 'Salary: "%d"' % self.salary
3,Student.py模块
#!/usr/bin/python
import SchoolMember as s
class Student(s.SchoolMember):
'''Represents a student.'''
def __init__(self,name,age,marks):
s.SchoolMember.__init__(self,name,age)
self.marks = marks
print '(Initialized Student: %s)' % self.name
def tell(self):
s.SchoolMember.tell(self)
print 'Marks:"%d"' % self.marks
4,class_zbb.py 模块
#!/usr/bin/python
import Teacher as te //起个别名,注意这里导入的是模块,也就是文件
import Student as st
t = te.Teacher('Zheng.binbin',40,30000) //要调用Teacher类,必须加上模块名te
s = st.Student('Zheng.haoyu',15,90)
members = [t,s]
for member in members:
member.tell()
5,运行结果:达到预期效果
#python class_zbb.py
(Initialized SchoolMember:Zheng.binbin)
(Initialized Teacher: Zheng.binbin)
(Initialized SchoolMember:Zheng.haoyu)
(Initialized Student: Zheng.haoyu)
Name:"Zheng.binbin" Age:"40" Salary: "30000"
Name:"Zheng.haoyu" Age:"15" Marks:"90"