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教程。

你可能感兴趣的:(Python的OOP面向对象)