类和实例

1、类的定义:面向对象最重要的概念就是类(Class) 和实例(Instance),必须牢记 类是抽象的模板,比如Student类,而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,单个字的数据可能不同。

class Student(object):

    pass

class后面紧跟类名,即Student,类名通常是大写开头的单词;则(object)表示该类是从哪个类继承下来的

2、类可以起到模板作用,因此,可以在创建实例的时候,把一些我们认为必须绑定的属性强制填写进去。通过定义一个特殊的_init_方法,在创建实例的时候,就把name、score等属性绑上去:

class Student(object):

  def __init__(self,name,score):

     self.name=name

     self.score=score

注意到_init_方法的第一次参数永远是self,表示创建实例本身,因此,在_init_方法内部,就可以把各种属性绑定到self,self就指向创建的实例本身;有了_init_方法,在创建实例的时候,就不能传入空的参数了,必须传入与_init_方法匹配的参数,但self不需要传,python解释器自己会把实例变量传进去

>>> bart = Student('Bart Simpson', 59)
>>> bart.name
'Bart Simpson'
>>> bart.score
59

和普通的函数相比,在类中定义的函数只有一点不同,就是第一个参数永远是实例变量self,并且,调用时,不用传递该参数。除此之外,类的方法和普通函数没有什么区别,所以,你仍然可以用默认参数、可变参数和关键字参数

3、数据封装:以上例为准,从外部看Student类,就只需知道,创建实例需要给出name、score,而如何打印,都是在Student类的内部定义的,这些数据和逻辑被“封装”起来了。调用起来很容易,但却不用知道内部实现的细节;;封装的另一好处是给Student类增加新的方法。

4、访问限制

  问题引入:在class内部,可以有属性和方法,而外部代码还是可以通过直接调用实例变量的方法来操作数据,这样就隐藏了内部的复杂逻辑;;但是,从前面的Student类的定义来看,外部代码还是可以自由修改一个实例的name、score属性:

>>>bart=Student('zhu',98)

>>>bart.score   输出:89

>>>bart.score=80

>>>bart.score  输出:80

 

若让内部属性不被外部访问,可以把属性的名称前加上两个下划线__ (注:是两个下划线),在python中,实例的变量名如果以 _ 开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问,so,把Student类改一改:

class Student(object):

  def __init__(self,name,score):

     self._name=name

     self._score=score

  def print_score(self):

    print '%s : %s' % (self._name , self._score)

>>>bart=Student('zhu',98)

>>>bart.__name  报错 AttributeError: 'Student' object has no attribute '__name'  因为.__name、.__score都被私有了;确保外部代码不能随意修改对象内部的状态,通过访问限制的保护,代码更加健壮

外部代码获取name、score时,可以给类加get_name、get_score方法;;set_score可以对参数检查,避免传入无效的参数,所以不直接用bart.score=80

class Student(object):

  def __init__(self,name,score):

     self._name=name

     self._score=score

  def print_score(self):

    print '%s : %s' % (self._name , self._score)

  def get_name(self):

    return self._name

  def get_score(self):

    return self._score

  def set_score(self,score):

    if 0<=score<=100:

      self._score=score

    else:

      raise ValueError('bad score')

5、继承:可以把父类的所有功能都直接拿过来,这样就不必重零做起,子类只需要新增自己特有的方法,也可以把父类不合适的方法覆盖重写;;有了继承,才能有多态,在调用类实例方法的时候,尽量把变量视为父类类型,这样,所有子类类型都可以正常被接收

-----------------------------------------------------------

1.单继承
class <类名>(父类名)
2.类的多重继承
class 类名(父类1,父类2,....,父类n)
需要注意圆括号中父类的顺序,若是父类中有相同的方法名,而在子类使用时未指定,python从左至右搜索即方法在子类中未找到时,从左到右查找父类中是否包含方法 

 

原文地址:https://www.cnblogs.com/zzfighting/p/5422522.html