python基础之更加抽象

1.对象的魔力

在面向对象程序设计中,术语对象(object)基本上可以看做数据以及一些列可以存取、操作这些数据的方法所组成的集合。对象的有点包括以下几个方面:

  • 多态(Polymorphism):意味着可以对不同类的对象使用同样的操作,他们会像被“施了魔法一般”工作
  • 封装(Encapsulation):对外部隐藏工作细节
  • 集成(Inheritance):以通用的类为基础建立专门的类对象

(1)多态

多态是面向对象语言的一个基本特性,多态意味着变量并不知道引用的对象是什么,根据引用对象的不同表现不同的行为方式。程序接收到一个对象的时候,不需要考虑它的状态,只需直接对其经行操作:

def add(x,y):

    return x+y

这个例子中我们其实并不需要考虑x和y的类型,只要x和y是可以相加的类型,程序就会根据类型做出相应的处理,这就是多态。

(2)封装

封装是指向程序中的其他部分隐藏对象的具体实现细节的原则。封装可以不用关心对象是如何构建的而直接进行使用的。假设我们有个叫做OpenObject的类:

>>>o=OpenObject()

>>>o.setName('sun')

>>>o.getName()

sun

创建了一个对象,通过像调用函数一样调用类后,变量o绑定到了该对象上。可以使用setName和getName方法。一切看起来很完美,但是如果将它的名字存储在一个全局变量globalname内的话,就不得不关心这个全局变量了,如果创建多个OpenObject的话就会出问题了,因为变量相同,可能会混淆:

>>>o1=OpenObject()

>>>o1.setName='hou'

>>>o1.getName()

hou

>>>o2=OpenObject()

>>>o2.getName()

hou

可以看到,设定了一个名字后,其他的名字也就自动设定了,这可不是想要的结果。

基本上,需要将对象经行抽象,调用方法的时候不用关心其他的东西,比如它是否干扰了全局变量。所以可以将名字“封装”在对象内吗?没问题,可以将其作为特性(attribute)存储。

这个问题我们会在后面的“再论私有化介绍”

(3)继承

面向对象的编程带来的主要好处之一是代码的重用,实现这种重用的方法之一是通过继承机制。继承完全可以理解成类之间的类型和子类型关系。


何时使用继承:假如我需要定义几个类,而类与类之间有一些公共的属性和方法,这时我就可以把相同的属性和方法作为基类的成员,而特殊的方法及属性则在本类中定义,这样只需要继承基类这个动作,就可以访问到基类的属性和方法了,它提高了代码的可扩展性。

任何事情都有利有弊:继承的一个弱点就是,可能特殊的本类又有其他特殊的地方,又会定义一个类,其下也可能再定义类,这样就会造成继承的那条线越来越长,使用继承的话,任何一点小的变化也需要重新定义一个类,很容易引起类的爆炸式增长,产生一大堆有着细微不同的子类. 所以有个“多用组合少用继承”的原则,(我觉得两者一起使用才是最佳吧*^◎^*)

2.类和类型

类是一种对象,所有的对象都属于某一个类,称为类的实例(instance)。

例如:鸟类是一种类,而鸟类中的百灵鸟类称为鸟类的子类,而鸟类称为百灵鸟类的超类。

在面向对象程序设计中,子类的关系是隐式的,因为一个类的定义取决于它所支持的方法。定义子类只是个定义更多方法的过程。

(1)创建自己的类

下面我们创建了一个类:

__metaclass__=type  #确定使用新式类

class Person:

    def setName(self,name):
        self.name=name
    def getName(self):
        return self.name

    def greet(self):
        print 'Hello,World! I am %s !' % self.name

这个self参数是对这个对象自身的引用,让我们创建一些实例看看:

foo=Person()
bar=Person()
foo.setName('a')
bar.setName('b')
print foo.getName()
print bar.getName()

下面是结果:

a
b

在调用foo的setName()的时候,foo把自己作为了第一个参数传入函数中——因此形象的命名为self。

显然这就是self的用处和存在的必要性。没有它的话,成员方法就没法访问它们要对其特性经行操作的对象本身了。

特性是可以在外部访问的。

foo.name

a


(2)特性、函数和方法

self参数并不依赖于调用方法的方式,前面我们使用的是instance.method(实例.方法)的形式,可以随意使用其他变量引用同一方法:

>>> class Bird:
...     song='hello'
...     def sing(self):
...         print self.song
...
>>> a=Bird()
>>> a.sing()
hello
>>> b=a.sing
>>> b()
hello

再论私有化

如果想要让外部无法访问对象的状态,那么可以使用私有特性,这是外部无法访问,但是对象内部访问器(setName等)可以访问的特性。为了让方法或者特性变为私有,只要在它的名字前加上双下划线就可以了:

class Person:
    def __a(self):
        print 'hello'
    def b(self):
        self.__a

foo=Person()
foo.__a()
Traceback (most recent call last):
  File "./test.py", line 12, in <module>
    foo.__a()
AttributeError: 'Person' object has no attribute '__a'

foo.b()

hello


(3)指定超类

子类可以定义超类,将其他类名写在class语句后的圆括号内疚可以指定超类:

class Filter:
    def init(self):
        self.blocked=[]
    def filter(self):
        return [x for x in sequence if x not in self.blocked]

class SPAMFilter:
    def init(self):#重写filter超类中的init方法
        self.blocked=['SPAM']
f=Filter()
f.init()
print f.filter([1,2,3])
s=SPAMFilter()
s.init
print s.filter(['A','SPAM','B'])

[root@localhost python]# ./test.py
[1, 2, 3]
['A', 'B']

这样,我们就实现了继承。


(4)检查继承

如果想要查看一个类是否有是另外一个类的子类,使用内建的issubclass函数:

print issubclass(SPAMFilter,Filter)
print issubclass(Filter,SPAMFilter)

True
False

如果你想知道已知类的基类,可以直接使用它的特殊特性——__bases__:

print Filter.__bases__
print SPAMFilter.__bases__

(<type 'object'>,)
(<class '__main__.Filter'>,)

还可以用isinstance方法检查一个对象是否是一个类的实例:

f=Filter()
print isinstance(f,Filter)
print isinstance(f,SPAMFilter)

True
False

如果想知道一个对象属于哪个类,可以使用__class__特性:

f=Filter()
print f.__class__

<class '__main__.Filter'>


(5)多个超类

一个子类可以继承多个超类,不过要注意继承的顺寻,如果有同一个名字的不同方法,先继承的超类会重写后继承的超类的方法。


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值