Python入门教程--类和对象(二)

来源:互联网 发布:如何发布php网站 编辑:程序博客网 时间:2024/05/19 02:27

         Python其实也被称为面向对象的预研,和C++/Java一样,具有面向对象预研的多态、封装、方法和特性等概念。关乎面向对象的概念这里不讲述,就看看Python里的类和对象的定义和使用相关的知识。

        1)定义类

        类的定义很简单,下面代码定义一个person 类:

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)
      类的定义与C++/Java类似,只是在每个类的方法的参数列表里都有一个self参数,它是对象本身,类似C++的this,调用实例:

>>> Jane = Person()>>> Lucy = Person()>>> Lucy.setName("Lucy God")>>> Jane.setName("Jane God")>>> Jane.greet()Hello, world!, I'am Jane God.>>> Lucy.greet()Hello, world!, I'am Lucy God.>>> 
        我们也可以直接对属性进行操作:

>>> Jane.name ="Michle">>> Jane.greet()Hello, world!, I'am Michle.>>> 
         通过上面的例子,我们发现如果不对方法和属性加以限制的话,默认是对外公开的,也即类似是C++/Java的public成员变量或方法,与C++里的struct类似默认情况下,Python程序可以从外部防伪一个对象的属性。而面向对象语言的一大特征是封装和信息隐蔽,因此我们接下来看看Python是如何做的。

         2)属性、方法私有化
         Python并不直接支持私有化,而是靠程序员自己把握在外部进行特性修改的时机,可以靠一些小技巧达到私有化的效果。为了让方法或属性变为私有的(外部无法访问),只要在它的名字前面加上双下划线即可,如:

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()Traceback (most recent call last):  File "<pyshell#2>", line 1, in <module>    s.__inaccessible()AttributeError: 'Secretive' object has no attribute '__inaccessible'>>> s.accessible()The secret message is:Bet you can't see me.>>> 
        通过上面我们可以看到“双下划线”达到了私有化的效果,尽管双下划线有些奇怪。类的内部定义中,所有以双下划线开始的名字都被“翻译”成前面加上单下划线和类名的形式。了解了这些幕后事情后,实际上还是能在类外部访问这些私有化方法(但不建议这么做),如:

>>> s._Secretive__inaccessible()Bet you can't see me.
       简而言之,要想其他人不能防伪对象的方法和属性是不可能的。如果不需要使用这种方法但是又想让其他对象不要访问内部数据,那么就可以使用单下划线,这不过是个习惯,但的确有效果。例如,但有下划线名字的函数在imports语句时就不会被导入。

        3)类的命名空间

        定义类时,同样的事情也会发生,所有位于class语句中的代码都在特殊的命名空间中执行——类命名空间(class namespace),这个命名空间可由类内的所有成员访问。但是并不是所有的Python程序员都知道类的定义其实就是执行代码块,比如,在类的定义区域并不只限使用def语句:

class MemberCounter:    members = 0    def init(self):        MemberCounter.members +=1
调用该类,

>>> m1 = MemberCounter()>>> m1.init()>>> MemberCounter.members1>>> m2 = MemberCounter()>>> m2.init()>>> MemberCounter.members2>>> m1.members2>>> m2.members2>>> 
在上面代码中,类的作用域内定义了一个可供所有成员(包括实例)访问的变量,用来计算类的成员数量。通过上面的代码,可以发现members属性与C++的static成员变量有点类似(C++static变量只能类访问,实例访问不了)。

        4)类的继承(超类)

        Python定义继承实现很简单,只需要将父类的类名写在class类后哦的圆括号内就行,如:

class Filter:    def init(self):        self.blocked =[]    def filter(self, sequence):        return [x for x in sequence if x not in self.blocked]class SPAMFilter(Filter): #SPAMFilter是Filter的子类    def init(self):        self.blocked =['SPAM']  #重写超类Filter中的init方法
 Filter是个用于过滤序列的通用类,事实上它不能过滤任何东西,主要作用是它可以作为其他类的基类(超类),比如SPAMFilter类,就可以将“SPAM”过滤出去,如:
>>> f = Filter()>>> f.init()>>> f.filter([1,2,3])[1, 2, 3]>>> s = SPAMFilter()>>> s.init()>>> s.filter(['SPAM','SPAM','SPAM','Filter','Bacon','Beaf','Peer'])['Filter', 'Bacon', 'Beaf', 'Peer']>>> 
注意SPAMFilter定义的两个要点:
1)这里提供新定义的方式重写了Filter的init方法
2)filter方法的定义是从Filter类中继承来的,所以不用重新定义
         通过内建的issubclass函数查看一个类是否是另一个类的子类,而通过__bases__特殊属性可以查看一个已知类的基类,通过isinstance方法检查一个对象是否是一个类的实例,如:

>>> issubclass(SPAMFilter, Filter)True>>> issubclass(Filter,SPAMFilter)False>>> SPAMFilter.__bases__(<class '__main__.Filter'>,)>>> isinstance(s,SPAMFilter)True>>> isinstance(s,Filter)True>>> isinstance(s,str)False>>> 
如果只想知道一个对象属于哪个类,则可以使用__class__属性,当然也可以通过type( )查看,如:

>>> s.__class__<class '__main__.SPAMFilter'>>>> type(s)<class '__main__.SPAMFilter'>>>> 
        5)多重继承

        Python支持多重继承,其实从刚才上面的代码中用”__bases__“就可以知一二。看一个例子(说话计算器):

class Calculator:    def calculate(self, expression):        self.value = eval(expression)class Talker:    def talk(self):        print("Hi, my value is %s" %self.value)class TalkingCalculator(Calculator, Talker):    pass
实例化TalkingCalculator类就可以调用Talker和Calculator的方法,如:

>>> tc = TalkingCalculator()>>> tc.calculate('1+2+3*4')>>> tc.talk()Hi, my value is 15>>> 
       注意:如果子类一个方法从多个父类继承时(也就是说有2个具有相同名字的不同方法),那么:先继承类中的方法会重写后继承类中的方法

0 0
原创粉丝点击