class面向对象编程学习笔记

1、__ intit__(self,x,xx,xxx,...)
  采用__ init__(self,,xx,xxx,xxxx,...)方法在创建实例时就把属性绑上去,第一个参数一定是self,self指向创建的实例本身
  和普通的函数相比,在类中定义的函数只有一点不同,就是第一个参数永远是实例变量self,其他并没有什么差别。但是采用对象编程的一个特点就是数据封装
  和静态语言不同,python允许对实例变量绑定任何数据,比如原本Student类中只有name,score两个属性,但是bart.age=18,可以得到一个新的age属性,但是也只是这个实例有这个属性,Student类中的其他实例并不会有这个age属性。

 

2、访问限制
  私有变量:在属性前面加两个下划线,如 _ _ name
  特殊变量:属性名称前后都加两个下划线,如 _ _ name _ _ ,特殊变量在外部可以直接访问,不是私有变量
  私有变量是习惯默认外部不能访问,但是python中在外部其实是可以访问的,但是python解释器会改变名称,如 _ _ name,python会改成_ class名__name(不同解释器的名字可能会不同,所以最好不要在外部直接访问)
  如果想在外部访问私有变量,可以采用下面这种方法:

 

class Student(object):
  pass...

  def get_name(self):
    return self.__name

  def get_score(self):
    return self.__score

  如果允许外部修改,可以采用下面方法:

class Student(object):
  ...
  def set_score(self, score):
    self.__score = score

  虽然当取消私有变量时可以直接修改,但是采用这种方法可以对参数进行检查,防止传入无效参数,比如上面的例子,可以在set_score函数里面判断分数是否在0——100。

class Student(object):
  def __init__(self,name,score):
    self.__name=name    #加__就把变量变为私有的了,外部不能访问
    self.__score=score
  def print_score(self):
    if self.__score>=90:
      print(self.__name,self.__score,'A')
    elif self.__score>=60:
      print('%s:%s %s' % (self.__name,self.__score,'B'))
    else:
      print('%s:%s %s'%(self.__name,self.__score,'C'))
      
bart = Student('bart',99)
lisa=Student('lisa',20)
lili=Student('lili',66)
bart.print_score()
lisa.print_score()
lili.print_score()

print(bart._Student__name)  #私有变量其实在外部是可以访问到的,只是python解释器自动改成了_Stident__name,但是最好不要这样做,因为不同版本的python解释器可能会把__name改成不同的名字

bart.__name='new name'
print(bart.__name)        #因为python解释器把__name改了名字,所以其实这里的bart.__name其实是一个新的变量,原来的bart.__name现在叫做bart._Student__name
print(bart._Student__name)  

 

结果如下:

 

 

3、继承和多态

    所有的类最终都会继承object类,所以,没有直接继承的类时,就写class xx(object),有直接继承的类时,括号里面就是父类,如class Dog(Animals) (类的名字一般首字母大写)。

定义一个类就相当于定义了一种数据类型,如:

a = list() # a是list类型
b = Animal() # b是Animal类型
c = Dog() # c是Dog类型


#判断变量是否是某个类型,可以用 isinstance

>>> isinstance(a, list)
True
>>> isinstance(b, Animal)
True
>>> isinstance(c, Dog)
True

但是由于Dog是Animals的子类,所以c也是Animals类型:

>>> isinstance(c, Animal)
True

    所以当参数是Animals的函数,传入参数为Animals子类的实例时,也是可以运行的,体现了多态性,即当参数为Animals或子类时,实际调用是看当前的具体对象,调用相应的函数或方法,如下例,函数run_twice是以Animals为参数,但是run_twice(Dog()),run_twice(Tortoise())都可以运行,并且是他们对应的run函数:

class Animal(object):
def run(self):
print('Animal is running...')

class Dog(Animal):
def run(self):
print('Dog is running...')

class Tortoise(Animal):
def run(self):
print('Tortoise is running slowly...')


def run_twice(Animal): #其实在python中,这里的参数不一定为Animals类型(鸭子类型),只要有run函数,不管参数是什么,都可以调用,不过具体调用还是看当前对象及相应方法
Animal.run()
Animal.run()

>>> run_twice(Animal())
Animal is running...
Animal is running...
>>> run_twice(Dog())
Dog is running...
Dog is running...
>>> run_twice(Tortoise())
Tortoise is running slowly...
Tortoise is running slowly...

 

但是对于python这样的动态语言来说,继承并没有静态语言严格,即如果不是Animals的子类,只要其中含有run方法,则也可调用run_twice函数:

 

posted @ 2017-12-10 14:57  一枚小菜鸟  阅读(805)  评论(0编辑  收藏  举报