您的位置:首页 > 编程语言 > Python开发

Python学习----面向对象编程

2015-09-07 23:08 405 查看
面向对象编程

一、类和实例

由于类可以起到模板的作用,因此,可以在创建实例的时候,把一些我们认为必须绑定的属性强制填写进去。通过定义一个特殊的
__init__
方法,在创建实例的时候,就把
name
score
等属性绑上去:
class Student(object):

def __init__(self, name, score):
self.name = name
self.score = score


注意到
__init__
方法的第一个参数永远是
self
,表示创建的实例本身,因此,在
__init__
方法内部,就可以把各种属性绑定到
self
,因为
self
就指向创建的实例本身。

有了
__init__
方法,在创建实例的时候,就不能传入空的参数了,必须传入与
__init__
方法匹配的参数,但
self
不需要传,Python解释器自己会把实例变量传进去:
>>> jack = Student('Jack', 89)
>>> jack.name
'Jack'
>>>jack.score
89


和普通的函数相比,在类中定义的函数只有一点不同,就是第一个参数永远是实例变量
self
,并且,调用时,不用传递该参数。除此之外,类的方法和普通函数没有什么区别,所以,你仍然可以用默认参数、可变参数、关键字参数和命名关键字参数。

和静态语言不同,Python允许对实例变量绑定任何数据,也就是说,对于两个实例变量,虽然它们都是同一个类的不同实例,但拥有的变量名称都可能不同:

>>> jack = Student('Jack', 59)
>>> alex = Student('Alex', 87)
>>> jack.age = 8
>>> jack.age
8
>>> alex.age
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'age'

三、继承和多态

class Animal(object):
def run(self):
print('Animal is running...')

class Dog(Animal):

def run(self):
print('Dog is running...')

dog = Dog()
dog.run()

运行结果:

Dog is running...


def run_twice(animal):
animal.run()
animal.run()


当我们传入
Animal
的实例时,
run_twice()
就打印出:
>>> run_twice(Animal())
Animal is running...
Animal is running...


当我们传入
Dog
的实例时,
run_twice()
就打印出:
>>> run_twice(Dog())
Dog is running...
Dog is running...


静态语言 vs 动态语言

对于静态语言(例如Java)来说,如果需要传入
Animal
类型,则传入的对象必须是
Animal
类型或者它的子类,否则,将无法调用
run()
方法。

对于Python这样的动态语言来说,则不一定需要传入
Animal
类型。我们只需要保证传入的对象有一个
run()
方法就可以了:
>>> class Like(object):
...   def run(self):
...     print('Like running...')
...
>>> run_twice(Like())
Like running...
Like running...


这就是动态语言的“鸭子类型”,它并不要求严格的继承体系,一个对象只要“看起来像鸭子,走起路来像鸭子”,那它就可以被看做是鸭子。

Python的“file-like object“就是一种鸭子类型。对真正的文件对象,它有一个
read()
方法,返回其内容。但是,许多对象,只要有
read()
方法,都被视为“file-like
object“。许多函数接收的参数就是“file-like object“,你不一定要传入真正的文件对象,完全可以传入任何实现了
read()
方法的对象。

继承可以把父类的所有功能都直接拿过来,这样就不必重零做起,子类只需要新增自己特有的方法,也可以把父类不适合的方法覆盖重写。

动态语言的鸭子类型特点决定了继承不像静态语言那样是必须的。

五、实例属性和类属性

当我们定义了一个类属性后,这个属性虽然归类所有,但类的所有实例都可以访问到。来测试一下:
>>> class Student(object):
...     name = 'Student'
...
>>> s = Student() # 创建实例s
>>> print(s.name) # 打印name属性,因为实例并没有name属性,所以会继续查找class的name属性
Student
>>> print(Student.name) # 打印类的name属性
Student
>>> s.name = 'Michael' # 给实例绑定name属性
>>> print(s.name) # 由于实例属性优先级比类属性高,因此,它会屏蔽掉类的name属性
Michael
>>> print(Student.name) # 但是类属性并未消失,用Student.name仍然可以访问
Student
>>> del s.name # 如果删除实例的name属性
>>> print(s.name) # 再次调用s.name,由于实例的name属性没有找到,类的name属性就显示出来了
Student


注意:在编写程序的时候,千万不要把实例属性和类属性使用相同的名字,因为相同名称的实例属性将屏蔽掉类属性,但是当你删除实例属性后,再使用相同的名称,访问到的将是类属性。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: