一、类和实例
类
是抽象的模板
实例
是根据类创建出来的一个个具体的“
对象
”,每个对象都拥有相同的方法,但各自的数据可能不同
在
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
()
可
用来
做类型比较:
![](https://i-blog.csdnimg.cn/blog_migrate/9176eff44aa52ae56c3a47f0155d913c.png)
type()
可用来做函数对象判断:
![](https://i-blog.csdnimg.cn/blog_migrate/69a5d8ecc677a2341ae287a147b3a074.png)
对于
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__:
类的所有父类构成元素(包含了一个由所有父类组成的元组)