现在的位置: 首页 > 综合 > 正文

Python读书笔记第十章:面向对象的编程

2014年07月05日 ⁄ 综合 ⁄ 共 4294字 ⁄ 字号 评论关闭

1.self

self这个变量是指对象本身,但是在调用它的时候不用它赋值,Python会提供这个值,相当于C++中的self指针和Java、C#中的this参考。

假如有一个MyClass的类和这个类的一个实例Myobject。当你调用这个对象的方法Myobject.method(arg1, arg2)的时候,这会由Python自动转为Myclass.method(myobject, arg1, arg2)。这也意味着如果你有一个不需要参数的方法,还是得给这个方法定义一个self参数。

2.类

#!/usr/bin/python
# Filename: simplestclass.py

class Person:
    pass # An empty block

p = Person()
print p

输出:

$ python simplestclass.py
<__main__.Person instance at 0xf6fcb18c>

class语句后跟类名,创建一个新的类。

使用类名后跟一对圆括号创建一个对象/实例,为了验证,我们简单打印了这个变量的类型,它告诉我们在_main_模块已经有一个Person类的实例,而且还打印了存储对象的计算机内存地址。

3.对象的方法

#!/usr/bin/python
# Filename: method.py

class Person:
    def sayHi(self):
        print 'Hello, how are you?'

p = Person()
p.sayHi()

# This short example can also be written as Person().sayHi()

输出:

$ python method.py
Hello, how are you?

这里可以看到self的用法,即使sayHi方法没有任何参数,但仍然在函数定义时有self。

4._init_方法

__init__方法在类的一个对象被建立时,马上运行。这个方法可以用来作初始化,类似于C++的constructor。注意这个名称的开始和结尾都是双下划线。

#!/usr/bin/python
# Filename: class_init.py

class Person:
    def __init__(self, name):
        self.name = name
    def sayHi(self):
        print 'Hello, my name is', self.name

p = Person('Swaroop')
p.sayHi()

# This short example can also be written as Person('Swaroop').sayHi()

输出:

$ python class_init.py
Hello, my name is Swaroop

在__init__里,我们创建了一个新的域name,而且没有专门调用__init__方法,只是在创建一个新类时,自动调用。

5.类与对象的方法

有两种类型的域:类的变量和对象的变量,类的变量由一个类的所有对象(实例)共享使用(像C++中的static变量?)。只有一个类变量的拷贝,所以当某个对象对类的对象做了改动,这个改动会反映到所有其他的实例上。而对象的变量由类的每个对象/实例拥有。因此每个对象有自己的对这个域的一份拷贝,它们不是共享的,每个对象的变量是互不相关的。

#!/usr/bin/python
# Filename: objvar.py

class Person:
    '''Represents a person.'''
    population = 0

    def __init__(self, name):
        '''Initializes the person's data.'''
        self.name = name
        print '(Initializing %s)' % self.name

        # When this person is created, he/she
        # adds to the population
        Person.population += 1

    def __del__(self):
        '''I am dying.'''
        print '%s says bye.' % self.name

        Person.population -= 1

        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

    def howMany(self):
        '''Prints the current population.'''
        if Person.population == 1:
            print 'I am the only person here.'
        else:
            print 'We have %d persons here.' % Person.population

swaroop = Person('Swaroop')
swaroop.sayHi()
swaroop.howMany()

kalam = Person('Abdul Kalam')
kalam.sayHi()
kalam.howMany()

swaroop.sayHi()
swaroop.howMany()

输出:

$ python objvar.py
(Initializing Swaroop)
Hi, my name is Swaroop.
I am the only person here.
(Initializing Abdul Kalam)
Hi, my name is Abdul Kalam.
We have 2 persons here.
Hi, my name is Swaroop.
We have 2 persons here.
Abdul Kalam says bye.
There are still 1 people left.
Swaroop says bye.
I am the last one.

population属于Person类,因此是一个类的变量,name属于对象(使用self赋值),因此是对象的变量。只能使用self变量来参考同一个对象的变量和方法,这称为属性参考。

__del__也是一个特殊的方法,它在对象消逝的时候被调用,相当于C++中的destructor。当你想指明不再使用该对象时,就得使用del语句,这时系统回收它所占用内存,同时调用__del__。

Python的所有类成员,包括数据成员都是公共的,所有的方法都是有效的。只有当你在数据成员加上双下划线前缀,如__privatevar,这样Python的名称管理体系就会把它当作私有变量。一个惯例是,如果某个变量只想在类或对象中使用,就应该以单下划线前缀,而其他的名称都将作为公共的,可以被其他类/对象使用。

4.继承

面向对象的编程带来的主要好处之一是代码的重用,实现这一重用的一种方法是继承。一个子类型在任何需要父类型的场合可以被替换成付类型,即对象可以被视为父类的实例,这种现象被称为多态。

#!/usr/bin/python
# Filename: inherit.py

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):
        '''Tell my details.'''
        print 'Name:"%s" Age:"%s"' % (self.name, self.age),

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

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('Mrs. Shrividya', 40, 30000)
s = Student('Swaroop', 22, 75)

print # prints a blank line

members = [t, s]
for member in members:
    member.tell() # works for both Teachers and Students

输出:

$ python inherit.py
(Initialized SchoolMember: Mrs. Shrividya)
(Initialized Teacher: Mrs. Shrividya)
(Initialized SchoolMember: Swaroop)
(Initialized Student: Swaroop)

Name:"Mrs. Shrividya" Age:"40" Salary: "30000"
Name:"Swaroop" Age:"22" Marks: "75"

使用继承时,把基本类(父类)的名称作为一个元组跟在定义类时的类名称之后。子类不会自动调用基本类的__init__,所以在子类的__init__得亲自专门去调用它,调用之前加上类名称前缀,然后把self变量及其他参数传递给它。

在使用SchoolMember类的tell方法时,我们把Teacher和Student的实例仅仅作为SchoolMember的实例。

另外,在这个例子中还调用了子类型的tell方法,而不是SchoolMember类的tell方法。Python总是先查找对应类的方法,如果不能在子类中找到对应的方法,它才开始到基本类中查找。

如果在继承元组中列了一个以上的类,那么它就称作多重继承。

抱歉!评论已关闭.