更加抽象

# coding:utf-8程序员


#--------------------------------------------------  对象魔力  -----------------------------------------express


#多态app


#多态方法dom

print 'abc'.count('a')ide

#1函数

print [1, 2, 'a'].count('a')工具

#1spa

#不用关心count('a')里面是什么类型数据,只要知道count方法,能够返回a出现多少次,就好了,这就是多态方法设计

#choice函数,能够从序列中随机选出元素。对象

from random import choice

x = choice(['Hello, world!', [1, 2, 'e', 'e', 4]])

#x多是Hello,world字符串,多是[1, 2, 'e', 'e', 4]列表,不用关心究竟是哪一个类型,只要关心变量x中字符e出现了多少次。无论x是字符串仍是列表,均可以使用count函数。

print x.count('e')

#2              #本例中,看来列表胜出了。

#多态多种形式

#当面对对象不知道是什么类型,但又要对对象作些何时,就会用到多态

#这不只限于方法,不少内建运算符和函数都有多态的性质。好比:

print 1 + 2

#3

print 'Fish' + 'license'

#Fishlicense

#这里的加运算符对于数字和字符串都能起做用。

#为说明这一点,假设有个叫作add的函数,它能够将两个对象相加。能够直接将其定义成上面的形式。

def add(x, y):

   return x+y

#对于不少类型的参数均可以用:

print add(1, 2)

#3

print add('Fish', 'license')

#Fishlicense

#若是须要编写打印对象长度消息的函数,只需对象具备长度(len函数可用)便可。

def length_message(x):

   print "The length of", repr(x), "is", len(x)

#能够看到,函数中还使用了repr函数,repr函数是多态特性。

length_message('Fnord')

#The length of 'Fnord' is 5

length_message([1, 2, 3])

#The length of [1, 2, 3] is 3

#不少函数和运算符都是多态的---你写的绝多数程序可能都是,即使你并不是有意这样。只要使用多态函数和运算符,就会与“多态”发生关联。

#事实上,惟一能毁掉多态的就是使用函数检查类型,好比type,isinstance以及issubclass函数等。

#若是可能的话,应该尽力避免使用这些毁掉多态的方式。真正重要的是如何让对象按照你所但愿的方式工做,无论它是不是正确的类型(或者类)。


#封装

#封装是指向程序中的其余部分隐藏对象的具体实现细节原则。

#接下面再论私有化进行详细解释


#继承

#就是函数,类等调用,相同代码不想重复写,直接调用给其余代码,就是继承。


#--------------------------------------------  类和类型 ------------------------------------------


#建立类

__metaclass__ = type           #肯定使用新式类,一种写法格式,建立类写上便可

class Person:

   def setName(self, name):

       self.name = name

   def getName(self):

       return self.name

   def greet(self):

       print "Hello, world! I'm %s." % self.name

#这个例子包含3个方法定义,除了它们是写在class语句里,一切都像是函数定义。Person是类的名字。class语句会在函数定义的地方建立本身的命名空间。

#self参数看起来有点奇怪,它是对于对象自身的引用。那么它是什么对象?建立一些实例看看:

foo = Person()

bar = Person()

foo.setName('Luke Skywalker')               #foo将本身为第一个参数传入到self里

bar.setName('Anakin Skywalker')

foo.greet()

#Hello, world! I'm Luke Skywalker.

bar.greet()

#Hello, world! I'm Anakin Skywalker.

#在调用foo的setName和greet函数时,foo自动将本身做为第一个参数传入函数中---所以形象地命名为self。对于这个变量,每一个人可能都会有本身的叫法,可是由于它老是对象本身,因此习惯上老是叫作self

#显然这就是self的用处和存在的必要性。没有它的话,成员方法就无法访问它们要对其特性进行操做的对象自己了。

#特性能够在外部访问:

#就是setName函数里的self.name = name

print foo.name

#Luke Skywalker

bar.name = 'Yoda'

bar.greet()

#Hello, world! I'm Yoda.

#若是知道foo是Person的实例的话,那么能够把foo.greet()写成:

Person.greet(foo)           #方便的简写

#Hello, world! I'm Luke Skywalker.


#特性,函数,方法

__metaclass__ = type

class Class:

   def method(self):

       print 'I have a self!'

def function():

       print "I don't..."

instance = Class()              #调用类

instance.method()               #instance是实例,method是方法,有self参数

#I have a self!

instance.method = function      #绑定到一个普通函数上,没有self参数

instance.method()

#I don't...

__metaclass__ = type

class Bird:

   song = 'Squaawk!'

   def sing(self):

       print self.song

bird = Bird()

bird.sing()

#Squaawk!

birdsong = bird.sing

birdsong()              #调用方法和函数十分类似,但变量绑定方法bird.sing仍是会对self参数进行访问

#Squaawk!


#再论私有化,接上面的封装

#使用上面类的例子:

__metaclass__ = type

class Person:

   def setName(self, name):

       self.name = name

   def getName(self):

       return self.name

   def greet(self):

       print "Hello, world! I'm %s." % self.name

o = Person()            #调用类

o.setName('Sir Lancelot')

print o.getName()

#Sir Lancelot

#变量o绑定到对象(Person类)上,可使用setName和getName方法。一切看起来很完美。可是假设变量o将它的名字存储在全局变量globalName中:

#但假设变量o将它的名字存储在全局变量globalName中:

#globalName

#'Sir Lancelot'

#这意味着在使用OpenObject类的实例时候,不得不关心globalName的内容。实际上要确保不会对它进行任何更改:

#globalName = 'Sir Gumby'

#o.getName()

#'Sir Gumby'

#若是建立了多个OpenObject实例的话就会出现问题,由于变量相同,因此可能会混淆:

#o1 = OpenObject()

#o2 = OpenObject()

#o1.setName('Robin Hood')

#o2.getName()

#'Robin Hood'

#设定一个名字后,其余名字也自动设定了。

#为了让方法或者特性变成私有(外部没法访问),只要在它的名字前面加上双下划线便可。

__metaclass__ = type

class Secretive:

   def __inaccessible(self):            #让方法变成私有化(外部没法访问),只要在它的名字前面加上双下划线便可

       print "Bet you can`t see me..."

   def accessible(self):

       print "The secret message is:"

       self.__inaccessible()           #内部调用

s = Secretive()

# s.__inaccessible()              #报错没法调用

s.accessible()                  #内部能够调用

#The secret message is:

#Bet you can`t see me...

s._Secretive__inaccessible()       #也有外部调用方法,但不该该这么作

#Bet you can`t see me...


#类的命名空间

__metaclass__ = type

class MemberCounter:

   members = 0

   def init(self):

       MemberCounter.members += 1

#上面代码中,在类做用域内定义了一个可供全部成员(实例)访问的变量(members),用来计算类的成员数量。注意init用来初始化全部实例。

m1 = MemberCounter()        #调用类

m1.init()

print MemberCounter.members

#1

m2 = MemberCounter()

m2.init()

print MemberCounter.members

#2

#类做用域内的变量也能够被全部实例访问:

print m1.members

#2

print m2.members

#2

m1.members = 'Two'              #新的numbers值被写到了m1特性中,屏蔽了类范围内的变量。这跟函数内的局部和全局变量的行为十分相似。

print m1.members

#Two

print m2.members

#2


#指定超类

__metaclass__ = type

class Filter:           #写一个过滤做用的类(超类)

   def init(self):

       self.blocked = []

   def filter(self, sequence):

       return [x for x in sequence if x not in self.blocked]  # 如何理解这句话,同等于下面注释

#        l = []

#        for x in sequence:

#            if x not in self.blocked:

#                l.append(x)

#        return l

#Filter是个用于过滤序列的通用类,事实上它自身不能过滤任何东西

f = Filter()

f.init()

print f.filter([1, 2, 3])

#[1, 2, 3]

#Filter类的用处在于它能够用做其余类的(基类)超类,好比下面SPAMFilter类,能够将序列中的'SPAM'过滤出去。

class SPAMFilter(Filter):               #继承上面的类,能够不用写一大堆过滤的类,从上面继承更加方便。SPAMFilter是Filter的子类,Filter是SPAMFilter的超类

   def init(self):                     #重写超类Filter中的init方法

       self.blocked = ['SPAM']         #原本过滤关键字没写,如今写入SPAM

s = SPAMFilter()

s.init()

print s.filter(['SPAM','SPAM','SPAM','eggs','bacon','SPAM'])

#['eggs', 'bacon']


#检查继承

#若是想要查看一个类是不是另一个的子类,可使用内建的issubclass的函数:

print issubclass(SPAMFilter, Filter)        #查看SPAMFilter是不是Failter的子类

#True

print issubclass(Filter, SPAMFilter)

#False

#若是想要知道已知类的基类(们)(注意下节解释),可使用特殊特性__bases__:

print SPAMFilter.__bases__       #已知类的基类,使用__bases__

#(<class '__main__.Filter'>,)

print Filter.__bases__

#(<type 'object'>,)

#使用isinstance方法检查一个对象是不是一个类的实例:

s = SPAMFilter()

print isinstance(s, SPAMFilter)

#True

print isinstance(s, Filter)

#True

print isinstance(s, str)

#False

#想知道一个对象属于哪一个类,可使用__class__特性

print s.__class__

#<class '__main__.SPAMFilter'>


#多个超类

#上节提到一个类的基类(们),也就暗示它的基类可能会多于一个。事实上就是这样,创建几个新类来试试:

class Calculator:

   def calculate(self,expression):

       self.value = eval(expression)

class Talker:

   def talk(self):

       print 'Hi, my value is', self.value

class TalkingCalculator(Calculator, Talker):

   pass

#子类(TalkingCalculator)本身不作任何事,它从本身的超类继承全部的行为。它从Calculator类那里继承calculate方法,从Talker类那里继承talk方法,这样它就成了会说话的计算器。

tc = TalkingCalculator()

tc.calculate('1+2*3')

tc.talk()

#Hi, my value is 7

#这种行为称为多重继承,是个很是有用的工具。但除非特别熟悉多重继承,不然应该尽可能避免使用,由于有些时候会出现不可预见的麻烦。

#须要注意是若是一个方法从多个超类继承(也就是说有两个具备相同名字的不一样方法),那么必须注意下超类的顺序(在class语句中):先继承的类中的方法会重写后继承的类中的方法。

#若是前例中Calculator:类也有个叫talk方法(函数),那么它会覆盖Talker的talk方法(使其没法访问)。若是把它们顺序掉过来,像下面这样:

#class TalkingCalculator(Talker, Calculator): pass

#就会让Talker的talk方法可用了。


#接口和内省

#能够查看方法是否存在(接口)

print hasattr(tc, 'talk')

#True

print hasattr(tc, 'fnord')

#False


#小结

#对象

#对象包括特性和方法。特性只是做为对象的一部分的变量,方法则是存储在对象内的函数。(绑定)方法和其余函数的区别在于方法老是将对象做为本身的第一个参数,这个参数通常称为self。

#类

#类表明对象的集合(或一类对象),每一个对象(实例)都有一个类。类的主要任务是定义它的实例会用到方法。

#多态

#多态是实现将不一样类型和类的对象进行一样对待的特性---不须要知道对象属于哪一个类就能调用的方法。

#封装

#对象能够将它们的内部状态隐藏(或封装)起来。在一些语言中,这意味着对象的状态(特性)只对本身的方法可用。在Python中,全部的特性都是公开可用的,可是程序员应该在直接访问对象状态时谨慎行事,由于他们可能无心中使得这些特性在某些方面不一致。

#继承

#一个类能够是一个或者多个类的子类。子类从超类继承全部方法。可使用多个超类,这个特性能够用来组成功能的正交部分(没有任何联系)。普通的实现方式是使用核心的超类和一个或者多个混合的超类。

#接口和内省

#通常来讲,对于对象不用探讨过深。程序猿能够靠多态调用本身须要的方法。不过若是想要知道对象到底有什么方法和特性,有些函数能够帮助完成这项工做。

#面向对象设计

#关于如何(或者说是否应该进行)面向对象设计有不少的观点。无论你持什么观点,彻底理解这个问题,而且建立容易理解的设计是很重要的。

相关文章
相关标签/搜索