Python学习笔记(面向对象编程)

面向对象编程
1、类和实例
     类是模板,实例是根据类创建的具体对象, 类中的函数可以在对象中调用,称为对象的方法(Method)。
     例子,Student类:
class Student(object):
    pass
     Student是类名,object是继承的类,如果没有合适的继承类,就使用object类,这是所有类最终都会继承的类
     实例通过类名+()创建,可以通过实例.属性的方式为实例绑定属性,也可以用特殊的方法__init__()在创建实例的时候,直接为实例绑定属性。
     例子:
class Student(object):

    def __init__(self, name, score):  '''第一个参数永远是self,调用时不用传递,表示实例本身'''
        self.name = name

        self.score = score
>>> bart = Student('Bart Simpson', 59)'''self参数不用传入,传入了name和score'''
>>> bart.name
'Bart Simpson'
>>> bart.score
59
    使用类的函数来调用类内部的数据,这种相当于把类内部的数据封装起来,可以调用但是不知道类的内部细节。还可以方便的给类增加新的方法。

2、访问限制
     如果要让Class内部属性不被外部访问,可以把属性的名称前加上两个下划线__,在Python中,实例的变量名如果以__开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问。
     如果外部想要获取私有变量,可以给类设计方法函数去调用私有变量,在外部调用相应的方法函数从而取得私有变量。
     例子:
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):#取得__name
        return self.__name
    def get_score(self):#取得__score
        return self.__score
    def set_score(self, score):#改变__score
        self.__score = score

3、继承和多态
     定义一个class的时候可以从现有的class继承,新的class是子类,被继承的是父类。子类拥有父类的全部方法,在子类中不重新定义父类的方法时,调用的时父类的方法,重新定义后调用的是子类的方法。
     例子:
class Animal(object):
    def run(self):
        print('Animal is running...')
        
class Dog(Animal):
    def run(self):  #对父类的同名方法进行重新定义
        print('Dog is running...')
>>>dog = Dog()
>>>dog.run()

Dog is running...
     子类的数据类型和父类一样,如上例中,dog不但是Dog类型还是Animal类型,这样当函数的参数是Animal类型时也可以传入Dog类型的参数,按照Animal类型操作,因为Dog是Animal的子类,反之不行。这就是多态。
     例子:
def run_twice(animal):
    animal.run()
    animal.run()

>>> run_twice(Animal())
Animal is running...
Animal is running...

>>> run_twice(Dog())#Dog也是Animal类型
Dog is running...

Dog is running...
    静态语言VS动态语言
    对于静态语言上例的函数run_twice必须传输Animal类和子类,例如java。
    对于动态语言python,只要保证传入的对象有run()方法就行,不一定非得是Animal类或子类。
    
    使用super(a_type, obj)子类可以调用父类的方法。
    例子:
    class A(object):
       def add(self, m):
             print('self is {0} @A.add'.format(self))
             self.n += m
    class B(A):
        def add(self, x):
             super(B, self).add(x) #调用了A.add(),但是调用时self依然指向B
 
4、获取对象信息
    type(),判断基本数据类型可以直接写int,str等,但如果要判断一个对象是否是函数可以使用types模块中定义的常量。
    例子:
>>> type(123)==type(456)
True
>>> type(123)==int
True
>>> type('abc')==type('123')
True
>>> type('abc')==str
True
>>> type('abc')==type(123)
False

>>> import types
>>> def fn():
...     pass
...
>>> type(fn)==types.FunctionType
True
>>> type(abs)==types.BuiltinFunctionType
True
>>> type(lambda x: x)==types.LambdaType
True
>>> type((x for x in range(10)))==types.GeneratorType
True
      能用type()判断的,也能用isinstance()判断,还可以判断一个变量是否是某些类型中的一种。
      例子:
>>> isinstance([1, 2, 3], (list, tuple))#判断是否是list或tuple
True
      使用dir()可以得一个对象的所有属性和方法。
      使用内置函数getattr()、setattr()以及hasattr()可以获取,设置和判断对象是否含有某属性。
      getattr(object, name[, default])  #返回对象属性值。
object -- 对象。
name -- 字符串,对象属性。

default -- 默认返回值,如果不提供该参数,在没有对应属性时,将触发 AttributeError。
      setattr(object, name, value)     #用于设置属性值,该属性不一定是存在的。如果属性不存在,会创建一个新的属性
object -- 对象。
name -- 字符串,对象属性。
value -- 属性值。
       hasattr(object, name)     #如果对象有该属性返回 True,否则返回 False。
object -- 对象。

name -- 字符串,属性名。
      例子:
>>> getattr(obj, 'z', 404) # 获取属性'z',如果不存在,返回默认值404
404
>>> fn = getattr(obj, 'power') # 获取属性'power'并赋值到变量fn
>>> fn # fn指向obj.power
<bound method MyObject.power of <__main__.MyObject object at 0x10077a6a0>>
>>> fn() # 调用fn()与调用obj.power()是一样的
81
   
5、实例属性和类属性
     在class中定义的属性,归类所有,但是类的所有实例都能访问到。如果实例的属性和class的属性同名,实例的属性将屏蔽class的属性。
     class的属性在定义class的时候被创建,之后在创建class的实例时不会反复创建。
     例子:
class Student(object):
  count = 0 
  print('class')
  def __init__(self,name):
    self.__name=name
    Student.count = Student.count+1 #每次创建实例时将类中的count+1

评论