python oop 继承_Python的OOP面向对象

# OOP 实战通过简单的case 更好的理解OOP思想, 如果使用代码,可以下载附件修改为.py即可

#!/usr/bin/env python

# -*- coding: utf-8 -*-

'''

Created on 2017年3月24日

@author: fWX457893

'''

# 类的封装

class Student(object):

# __ 双下划线可使变量私有变成private,只有在函数每部可以访问,外部不能访问,

def __init__(self, name, score, **kw):

self.__name = name

self.__score = score

self.kw = kw

# 如果还想要让外部访问,可是添加方法 get_name, get_score, get_kw

def get_name(self):

return self.__name

def get_score(self):

return self.__score

# 又要允许外部代码修改score怎么办?可以再给Student类增加set_score方法:

def set_name(self, name):

self.__name = name

def set_score(self, score):

if 0 <= score <= 100:

self.__score = score

else :

raise ValueError('bad score')

def print_score(self):

print('%s: %s \t %s' % (self.__name, self.__score, self.kw))

def get_grade(self):

if self.__score >= 90:

return 'A'

elif self.__score >= 60:

return 'B'

else :

return"C"

bart = Student('fyh', 100, address='bj')

bart.print_score()

bart.set_score(10)

bart.print_score()

grade = bart.get_grade()

print grade

# 表面上看,外部代码“成功”地设置了__name变量,但实际上这个__name变量和class内部的__name变量不是一个变量!

# 内部的__name变量已经被Python解释器自动改成了_Student__name,而外部代码给bart新增了一个__name变量。不信试试:

bart.__name = 'new name'

print bart.__name

bart.print_score()

# -------------------------------------------------------------------------------

# OOP 的 继承和多态

class Animal(object):

def run(self):

print 'Animal is running...'

def eat(self):

print('Eating food...')

class Dog(Animal):

def run(self):

print('Dog is running...')

def eat(self):

print('Dog eating meat...')

class Cat(Animal):

def run(self):

print('Cat is running...')

def eat(self):

print('Cat eating fish...')

ani = Animal()

ani.run()

cat = Cat()

cat.run()

def run_eat(animal):

animal.run()

animal.eat()

run_eat(Animal())

run_eat(Dog())

run_eat(Cat())

'''

对于一个变量,我们只需要知道它是Animal类型,无需确切地知道它的子类型,就可以放心地调用run()方法,

而具体调用的run()方法是作用在Animal、Dog、Cat还是Tortoise对象上,由运行时该对象的确切类型决定,

这就是多态真正的威力:调用方只管调用,不管细节,而当我们新增一种Animal的子类时,

只要确保run()方法编写正确,不用管原来的代码是如何调用的。这就是著名的“开闭”原则:

对扩展开放:允许新增Animal子类;

对修改封闭:不需要修改依赖Animal类型的run_twice()等函数。

继承还可以一级一级地继承下来,就好比从爷爷到爸爸、再到儿子这样的关系。而任何类,最终都可以追溯到根类object,这些继承关系看上去就像一颗倒着的树。

'''

#

'''

静态语言 vs 动态语言

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

对于Python这样的动态语言来说,则不一定需要传入Animal类型。我们只需要保证传入的对象有一个run()方法就可以了:

class Timer(object):

def run(self):

print('Start...')

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

Python的“file-like object“就是一种鸭子类型。对真正的文件对象,它有一个read()方法,返回其内容。但是,许多对象,只要有read()方法,都被视为“file-like object“。

许多函数接收的参数就是“file-like object“,你不一定要传入真正的文件对象,完全可以传入任何实现了read()方法的对象。

'''

class Husky(Dog):

def run(self):

print('Husky is running...')

def eat(self):

print('Husky eating meat...')

# 使用isinstance()

# 对于class的继承关系来说,使用type()就很不方便。我们要判断class的类型,可以使用isinstance()函数。

# object -> Animal -> Dog -> Husky

animal = Animal()

dog = Dog()

husky = Husky()

print isinstance(husky, Husky), isinstance(husky, Dog), isinstance(husky, Animal)

# True True True husky 是husky dog object 但是 dog 不是husky 是dog object

#定义一个父类一个子类

class Province(object):

def __init__(self,proname):

self.proname=proname

def ps(self):

print('I am in %s'%self.proname)

class City(Province):

def __init__(self,proname,cityname):

self.cityname=cityname

Province.__init__(self,proname)

def ps1(self):

print('I\'m in %s-%s' %(self.proname,self.cityname))

#定义一个独立的类

class Timer(object):

def ps(self):

print('我不属于Province类或其子类,但我有ps方法我同样可以被调用')

def ps1(self):

print('我不属于Province类或其子类,但我有ps1方法我同样可以被调用')

#定义一个函数

def func(x):

x.ps()

x.ps1()

#调用部分

func(City('北京','海淀'))

func(Timer())

# 部分参考廖神的python教程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值