概要:
一、创建类
二、特性、函数和方法
三、类的命名空间
四、指定超类
五、调查继承
六、多个超类
七、接口和内省
一、创建类:
1 >>> __metaclass__ = type #确定使用新式类 2 >>> class Person: 3 4 def setName(self,name): 5 self.name = name 6 def getName(self,name): 7 return self.name 8 def greet(self): 9 print"Hello world ! I'm %s." % self.name
self参数是对于对象自身的引用。
【注意】新式类的语法中,需要在模块或者脚本开始的地方放置赋值语句__metaclass__ = type。此外,也可以继承新式类(比如object)。
创建实例看看:
1 >>> tom = Person() 2 >>> john = Person() 3 >>> tom.setName('Tom') 4 >>> john.setName('John') 5 >>> tom.greet() 6 Hello world ! I'm Tom. 7 >>> john.greet() 8 Hello world ! I'm John.
【提示】tom 是 Person 的实例的话,那么还可以把 tom.greet() 看做 Person.greet(tom)方便的简写。
二、特性、函数和方法
self 参数事实上正是方法和函数的区别。
方法:(更专业一点可以称为绑定方法)将它们的第一个参数绑定到所属的实例上,因此这个参数可以不必提供。
可以将特性绑定到一个普通函数上,这样就不会有特色的self参数了:
1 >>> class myclass: 2 def mymethod(self): #这个是类的 方法 3 print' method() from a class must take arguments (1 given)!!' 4 5 6 >>> instance = myclass() 7 >>> instance.mymethod() 8 mymethod() must take arguments (1 given)!! 9 >>> 10 >>> def function(): #这个是普通函数 11 print 'now NOT belong to a class and no self argument' 12 13 14 >>> f = function() 15 now NOT belong to a class and no self argument
注意:self参数并不取决于调用方法的方式,可以如上的实例调用,也可以随意使用引用同一个方法的其他变量:
1 >>> instance = myclass() 2 >>> instance.mymethod() #实例调用 3 mymethod() must take arguments (1 given)!!
4 >>> mymd = instance.mymethod #也可以随意使用引用同一个方法的其他变量 5 >>> mymd() 6 mymethod() must take arguments (1 given)!!
上面的第二个方法调用,变量mymd 引用instance.mymethod这个绑定方法,也就意味着这还是对self参数的访问(也就是还是那个 instance,它仍旧绑定到类的相同实例上)。
程序可以从外部访问一个对象的特性。
私有特性,外部对象无法访问,但getName和setName等访问器(accessor)能够访问。
Python并不直接支持私有方式。
让方法或者属性变为私有(从外部无法访问),只要在它的名字前面加上双划线即可:
>>> class Person: def __say(self): print'I love you.' def accessiable(self): print'what he want to say is :' self.__say() >>> tom = Person() >>> tom.accessiable() what he want to say is : I love you.
类的内部定义中,所有以双划线开始的名字都被“翻译”成前面加上单下划线和类名的形式:
>>> Person._Person__say <unbound method Person.__say>
实际上还是能在类外访问这些私有方法,尽管不应该这么做:
>>> tom._Person__say()
I love you.
哈哈,不过是个“名称变化术”!
Python并没有真正的私有化支持。
如果不需要使用这种方法,但又想让其他对象不要访问内部数据,可以使用单下划线。
这不过是个习惯,但有效哦。例如,前面有下划线的名字都不会被带星号的imports语句(from module import *)导入。
三、类的命名空间
定义类时,所有位于class语句中的代码都在特殊的命名空间中执行--类命名空间(class namespace)。这个命名空间可由类内所有成员访问。
通俗点:比如一个类里面定义了一个变量(像java里的成员变量),或者方法,它就可以被所有实例访问。
重绑定后的特性值会屏蔽掉类范围类的变量值,但是其他没有重绑定该特性的实例不受影响。
类的定义其实就是执行代码块。
四、指定超类
超类:其实就像C++里的父类。
指定超类的方法:将其他类名写在class语句后的圆括号内。这样子类可以扩展超类的定义啦!
122页有关过滤类的代码可以看看。
1 >>> class Father: 2 def init(self): 3 print'This is Father class.' 4 5 6 >>> class Son(Father): 7 def say(self): 8 print'This is son speaking' 9 10 11 >>> tom = Son() 12 >>> tom.init() 13 This is Father class. 14 >>> tom.say() 15 This is son speaking
五、调查继承
查看一个类是否是另一个类的子类,可以使用内建的issubclass函数:
>>> issubclass(Son,Father)
True
查看已知类的基类(们),可以直接使用它的特殊特性__bases__:
>>> Son.__bases__ (<class __main__.Father at 0x01617260>,) >>> Father.__bases__ ()
检查一个对象是否是一个类的实例,使用 isinstance函数:
>>> isinstance(tom,Son) True >>> isinstance('d',str) True
检查一个对象属于哪个类,可以使用__class__特性:
>>> tom.__class__ <class __main__.Son at 0x01C89DF8>
【注意】如果使用__metaclass__ = type 或者从object继承的方式来定义新式类,那么可以使用type(tom)查看实例的类。
六、多个超类
子类自己可以不做任何事,从自己的超类继承所有行为:
>>> class Father: def init(self): print'This is Father class.' >>> class Mother: def sing(self): print'I can sing a song !' >>> class Girl(Father,Mother): pass >>> juni = Girl() >>> juni.init() This is Father class. >>> juni.sing() I can sing a song !
这也称为多重继承,除非特别熟悉,否则避免使用。
先继承的类中的方法,会重写后继承的类中、具有相同名字的不同方法。
七、接口和内省
检查所需方法是否已经存在:
>>> hasattr(juni,'run') False >>> hasattr(juni,'sing') True
【注意】callable函数在Python3.0不再用,可以使用hasattr(x,'__call__')代替。
检查特性(方法吧)是否可调用:
>>> callable(getattr(juni,'sing',None)) True >>> callable(getattr(juni,'run',None)) False
这里使用 getattr 函数 ,该函数允许提供默认值(本例中为None),以便在特性不存在时使用。那就无需if 一下hasattr()一下判断了,直接getattr啦!
与getattr 相对应的函数是setattr,可以用来设置对象的特性:
>>> setattr(juni,'name','Juniffer') >>> juni.name 'Juniffer'
小结:
对象:包括特性和方法。
类:每个对象都有一个类。类的主要任务是定义它的实例会用到的方法。
多态:对不同类型和类的对象进行同样对待的特性--不需要知道对象属于哪个类就能调用方法。(区别java反射机制里是如何调用一个对象的方法的)
封装:对象可以将它们内部状态隐藏(或封装)起来。虽然Python所有特性都是公开可用的。
继承:一个类可以是一个或多个类的子类。
接口和内省:略。
面向对象设计:略。