一、类和实例
类是抽象的模板
实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,但各自的数据可能不同
在python中定义一个类:
class MyNewClass(bases):
'define MyNewClass'
class_suite#类体
关键字是 class,紧接着是一个类名。随后是定义类的类体代码。这里通常由各种各样的定义和声明组成。
创建一个实例的过程称作实例化,过程如下(注意:没有使用new 关键字):
myFirstObject=MyNewClass()
可以自由地给一个实例变量绑定属性,比如,给实例bart绑定一个name属性:
bart.name= 'bart'
print bart.name
类同时也可以起到模板的作用,在创建一个类时,可以把公共的东西写进类定义中去,在python中通过一个特殊的__init__方法实现:
def __init__(self, name, score):
self.name = name
self.score = score
__init__方法的第一个参数永远都是self,表示创建实例本身,在__init__方法内部,可以把各种属性绑定到self,因为self指向创建的实例本身。
有了__init__方法,在创建实例的时候,就不能传入空的参数了,必须传入与__init__方法匹配的参数,但self不需要传,Python解释器自己会把实例变量传进去。注意:
和静态语言不同,Python允许对实例变量绑定任何数据,也就是说,对于两个实例变量,虽然它们都是同一个类的不同实例,但拥有的变量名称都可能不同:
class Student(object):
def __init__(self, name, score):
self.name = name
self.score = score
bart = Student('bart',99)
bart.age = 15
lisa = Student('lisa',95)
lisa.gender = 'male'
print bart.age
#lisa 实例中没有age 属性
print lisa.age
二、类成员修饰符
1、对于每一个类的成员而言都有两种形式:
1.公有成员,在任何地方都能访问
2.私有成员,只有在类的内部才能方法
3.私有成员和公有成员的定义不同:私有成员命名时,前两个字符是下划线,如__name。(特殊成员除外,例如:__init__、__call__等)
2、私有成员和公有成员的访问限制不同:
静态字段:
1.公有静态字段:类可以访问,类内部可以访问;派生类中可以访问
2.私有静态字段:仅类内部可以访问
普通字段:
1.公有普通字段:对象可以访问;类内部可以访问;派生类中可以访问
2.私有普通字段:仅类内部可以访问
3、注意:
Python中如果变量名以双下划线开头和结尾的,是特殊变量__XXX__。特殊变量是可以直接从类内部访问的,如__init__,__exit__。
以一个下划线开头的实例变量名,比如_name,这样的实例变量外部是可以访问的,但是,按照约定俗成的规定,当看到这样的变量时,意思就是,“虽然我可以被访问,但是,请把”我”视为私有变量,不要随意访问”。
双下划线开头的私有变量是不是一定不能从外部访问呢?其实也不是。不能直接访问__name是因为Python解释器对外把__name变量改成了_class__name,所以,仍然可以通过_ class __name来访问__name变量:
但是强烈建议不要这么做,因为不同版本的Python解释器可能会把__name改成不同的变量名。
最后:Python的访问限制其实并不严格,主要靠自觉 三、封装、继承和多态1、类的封装
面向对象编程的一个重要特点就是数据封装。既然我们创建的实例里有自身的数据,如果想访问这些数据,就没必要从外面的函数去访问,可以在Student类内部去定义这样一个访问数据的函数,这样就把“数据”给封装起来了。这些封装数据的函数和Student类本身关联起来的,我们称之为类的方法。
要定义一个类的方法,除了传入的第一个参数是self外,其它和普通函数一样。如果想调用这个方法,直接在实例变量上调用,除了self不用传递,其余参数正常传入
数据和逻辑都被封装起来,直接调用方法即可,但却可以不用知道内部的细节。
2、继承和多态
当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子(Subclass),而被继承的class称为基类、父类或超类(Base class、Super class)。
子类的的方法如果和父类的方法重名,子类会覆盖掉父类方法进行重写。因为这个特性,就获得了一个继承的好处”多态”。对于静态语言(例如Java)来说,如果需要传入Animal类型,则传入的对象必须是Animal类型或者它的子类,否则,将无法调用run()方法。
对于Python这样的动态语言来说,则不一定需要传入Animal类型。我们只需要保证传入的对象有一个run()方法就可以了。
这就是动态语言的“鸭子类型”,它并不要求严格的继承体系,一个对象只要“看起来像鸭子,走起路来像鸭子”,那它就可以被看做是鸭子。
四、获取对象信息
type() 可以检查类型:
type()可用来做类型比较:

type()可用来做函数对象判断:

对于class的继承关系来说,使用type() 很不方便。
要判断class的类型,可以使用isinstance()函数。isinstance() 可以告诉我们,一个对象是否是某种类型。
如果要获得一个对象的所有属性和方法,可以使用dir() 函数,返回一个包含字符串的 list。
类似__xxx__的属性和方法在Python中都是有特殊用途的,比如__len__方法返回长度。在Python中,如果你调用len()函数试图获取一个对象的长度,实际上,在len()函数内部,它自动去调用该对象的__len__()方法,所以,下面的代码是等价的:
a = 'intersting'
print len(a)
print a.__len__()
五、实例属性和类属性
类属性:类属性是为其实例所共享的,即静态属性。对于公有的类属性,在类外可以通过类对象和实例对象访问。
实例属性:是实例对象特有的,类对象不能拥有。如果在类外修改类属性,必须通过类对象去引用然后进行修改。
class Student(object):
COUNTRY = 'China' #公有的类属性
__address= "your address" #私有的类属性
def __init__(self,name,age,IDNO):#实例属性
self.name = name
self.age = age
self.__ID = IDNO
tom = Student('tom',18,370883199707131967)
tom.gender = 'male'
print tom.name #实例对象访问
print Student.COUNTRY #类对象访问属性
print Student.name #错误:实例属性,不能通过类对象调用
Student.COUNTRY = 'America'
print Student.COUNTRY #类对象访问属性
Python内置类属性
__dict__ : 类的属性(包含一个字典,由类的数据属性组成)
__doc__ :类的文档字符串 ,不可被派生
__name__: 类名
__module__: 类定义所在的模块(类的全名是
‘__main__.className’,如果类位于一个导入模块mymod中, 那么className.__module__ 等于 mymod)
__bases__: 类的所有父类构成元素(包含了一个由所有父类组成的元组)