您的位置:首页 > 编程语言 > Python开发

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

2015-05-30 16:26 393 查看
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.members
1
>>> m2 = MemberCounter()
>>> m2.init()
>>> MemberCounter.members
2
>>> m1.members
2
>>> m2.members
2
>>>
在上面代码中,类的作用域内定义了一个可供所有成员(包括实例)访问的变量,用来计算类的成员数量。通过上面的代码,可以发现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个具有相同名字的不同方法),那么:先继承类中的方法会重写后继承类中的方法
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: