【python】7 - 第11章 面向对象的编程

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:正确示例

 

正文:

-------------------------------------------------------------

11  面向对象的编程

http://linux.chinaitlab.com/manual/Python_chinese/ch11.html

1,重要概念:

类:物以类聚,具有相同属性的对象就叫类!

对象/实例:万物皆对象

2,通过例子观察类的定义

#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明白呼?

 

·查看MyClass类的所有属性(即它包含哪些方法)

>>> dir(MyClass)              

 ['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__', 'myVersion', 'showMyVersion']

·显示__dict__方法的功能

>>> MyClass.__dict__             

>>> print MyClass.__dict__

{'__module__': '__main__', 'showMyVersion': , '__dict__': , 'myVersion': '1.1', '__weakref__': , '__doc__': 'MyClass class definition'}

 

3,下面列举一些特殊的类属性

C.__name__             C的名字

C.__doc__                 C的文档字符串

C.__bases__             C的所有父类构成的元组

C.__dict__                 C的属性

C.__module               C定义所在的模块

C.__class__               C对应的类

 

4,几个内置方法的作用

当类被调用,实例化的第一步是创建实例对象,python检查是否实现了__init__()方法;

和上面说的一样__init__()  __new__() 叫做“构造器”__del__() “解构器”

【理解self原理】假如,你有一个类称为MyClass和这个类的一个实例MyObject。当你调用这个对象的方法MyObject.method(arg1, arg2)的时候,这会由Python自动转为MyClass.method(MyObject, arg1, arg2)——这就是self的原理了。self指的就是实例名MyObject明白呼?

 

5,理解self

昨天看不懂的问题,今天一看就看懂了!哈哈

类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称,但是在调用这个方法的时候你不为这个参数赋值,Python会提供这个值。这个特别的变量指对象本身,按照惯例它的名称是self

看看下面这个例子就明白了!

6,【重点!self、类、实例化】创建一个类,看看它是如何工作的

示例1

>>> class firstclass:       //创建一个类 firstclass

...     def setdata(self,value):              //定义setdata方法

...             self.data = value

...     def display(self):                                      //定义display方法

...             print self.data

...

>>> x = firstclass()             //实例化firstclass类, xy是一个到firstclass的链接

>>> y = firstclass()

>>> x.setdata("hello")     //selfx 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类的实例。

 

 

7,使用对象的方法

#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 ?

8__init__方法实验

__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         

9,类与对象的方法

有两种变量,类的变量对象的变量。这也定义了这些变量的有效范围即作用域。

·类的变量由一个类的所有对象(实例)共享使用。只有一个类变量的拷贝,所以当某个对象对类的变量做了改动的时候,这个改动会反映到所有其他的实例上

·对象的变量  不是共享的,只在自己域内改变。

【重点例子:】使用类与对象的变量

#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 > ignored

((bkeep says bye.))

Exception exceptions.AttributeError: "'NoneType' object has no attribute 'population'" in > ignored

 

 

10,【重点】继承(老师和学生的例子)

程序功能:记录学校教师和学生信息

分析:教师的属性(姓名、年龄、工资);学生的属性(姓名、年龄、分数)

设计:准备设计三个类,SchoolMember记录公共属性(姓名、年龄);Teacher类继承/复用SchoolMember类记录教师的所有属性;Student类继承/复用SchoolMember类记录学生的所有属性。

 

#cat inherit.py

#!/usr/bin/python

class SchoolMember:       # 定义一个父类,供其它类来继承。

        '''Represents any school member.'''

        def __init__(self,name,age):   #nameage是公共属性,定义在这里

                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类对nameage变量的定义

                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]       #定义列表其项目便是ts实例

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:错误示例

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

 

3Student.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

 

4class_zbb.py 模块

#!/usr/bin/python

import Teacher

import Student

t = Teacher('Zheng.binbin',40,30000)

s = Student('Zheng.haoyu',15,90)

 

print

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):

 

实验2:正确示例

1SchoolMember.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),

 

2Teacher.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

 

3Student.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

 

4class_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)

 

print

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"

 

你可能感兴趣的:(Python)