记录我的成长吧~

面向对象

概念

    面向对象编程是一种程序设计范式
    把程序看做不同对象的相互调用
    对现实世界简历对象模型

基本思想:

基本思想:
    类
        定义抽象类型(人)
    实例
        根据类的定义被创建出来(小明、小红)
    在面向对象中,用类和实例来区分类型以及不同的实例变量:
        类:
            class Person(object):
                pass
        实例:类名+类似的函数调用来创建
            xiaoming = Person)()
            xiaohong = Person)()
    数据封装:
        在类中可以把每一个实例的属性封装起来。不同的实例就会拥有相同的数据类型,但也拥有不同的属性。
            class Person:
                def __init__(self,name):
                    self.name = name
                        
            P1 = Person("xiaoming")
            P2 = Person("xiaohong")

定义类并创建实例:

创建类:
    class Person(object):
        pass
    类名以大写字母开头,object 表示该类从哪里个类继承下来的。
创建实例:
    xiaoming = Person()
    xiaohong = Person()

创建实例属性:

xiaoming = Person()
xiaoming.name = "xiaoming"
xiaoming.age = "18"
######################
xiaohong = Person()
xiaohong.name = "xiaohong"
xiaohong.age = "28"
实例的属性可以像普通变量一样进行操作:
    xiaoming.age += 1

初始化实例属性:

创建类:
对于实例具有相同名字的属性,可以在Person类中加入特殊的__init__()方法。
当创建实例时,__init__()方法自动被调用。
    class Person(object):
        def __init__(self,name,age):
            self.name = name #相当于xiaoming = Person()  xiaoming.name = "xiaoming"
            self.age = age
__init__()方法第一个参数必须是self(也可以用别的名字,建议使用习惯用法),后续参数可以自由
指定,和定义函数没有区别。
创建实例:
相应地,创建实例时,就必须提供除self以外的参数:
    xiaoming = Person("xiaoming","18")
    xiaohong = Person("xiaohong","28")
    执行:
        print xingming.name
        #输出:  xiaoming

访问限制:

如果一个属性由双下划线开头(__),该属性就无法被外部访问。
    class Person(object):
        def __init__(self,name):
            self.name = name 
            self.__age = "11" #私有属性
    p1 = Person("abc")
    p1.__age  # 该属性无法被调用
"__xxx__"定义的属性是Python中的特殊属性,通常不要把普通属性用这种方法去定义。

创建类属性:

类是模板,而实例时根据类创建的对象。
绑定在一个实例上的属性不会影响其他实例,但是,类本身也是一个对象,如果在类上绑定一个属性,则
所有实例都可以访问类的属性,并且所有实例访问的类属性都是同一个。即:实例属性每个实例各自拥有,
相互独立,而类属性有且只有一份。
定义类属性:
    class Person(object):
        school = "beida"
        def __init__(self,name):
            self.name = name
    调用类属性时可以直接访问,不需要创建实例。
        print Person.school
        # -->beida
    所有实例都可以访问到类的属性:
        p1 = Person("abc")
        print p1.school
        # --> beida 
    Python是动态语言,类的属性可以动态添加和修改:
        Person.school = "qinghua"
        print p1.school
        # --》 qinghua
        由于类的属性只有一份,所以类的属性一旦改变,实例访问到的也都改变。

###统计实例创建个数
class Person(object):
    count = 0
    def __init__(self,name):
        self.name = name
        Person.count += 1

p1 = Person('Bob')
print Person.count

p2 = Person('Alice')
print Person.count

实例属性名字和类属性名字重名:

当实例属性和类属性重名时,实例属性优先级高,它将屏蔽掉对类属性的访问。
它实际上并没有修改类属性,而是给实例绑定了一个实例属性。
    class Person(object):
        school = "123"
        def __init__(self,name):
            self.name = name
            
    p1 = Person("hah")
    p1.school = "456"
    print p1.school
    del p1.school
    print p1.school
    ## 输出:456   123

定义实例的方法:

实例的私有属性就是以__开头的属性,无法被外部访问,但可以从类内部访问。

实例的方法就是在类中定义的函数,它的第一个参数永远是 self,指向调用该方法的实例本身,其他参数和一个普通函数是完全一样的:
    class Person(object):
        __school = "123"
        def __init__(self,name):#初始化函数
            self.__name = name
            
        def say_name(self):
            return "My name is %s" %self.__name

    p1 = Person("abc")
    print p1.say_name()
    ##输出:My name is abc
在实例方法内部,可以访问所有实例属性,这样,如果外部需要访问私有属性,可以通过方法调用获得,这种数据封装的形式除了能保护内部数据一致性外,还可以简化外部调用的难度

方法也是属性:

我们在 class 中定义的实例方法其实也是属性,它实际上是一个函数对象:
    也就是说,p1.say_name 返回的是一个函数对象,但这个函数是一个绑定到实例的函数,p1.say_name() 才是方法调用
函数变方法:
    因为方法也是一个属性,所以,它也可以动态地添加到实例上,只是需要用 types.MethodType() 把一个函数变为一个方法:
        import types
        def fn_get_grade(self):
            if self.score >= 80:
                return 'A'
            if self.score >= 60:
                return 'B'
            return 'C'

        class Person(object):
            def __init__(self, name, score):
                self.name = name
                self.score = score

        p1 = Person('Bob', 90)
        p1.get_grade = types.MethodType(fn_get_grade, p1, Person)
        print p1.get_grade()
        # => A
        p2 = Person('Alice', 65)
        print p2.get_grade()
        # ERROR: AttributeError: 'Person' object has no attribute 'get_grade'
        # 因为p2实例并没有绑定get_grade
        

定义类方法:

和属性类似,方法也分实例方法和类方法。
在class中定义的全部是实例方法,实例方法第一个参数 self 是实例本身
    class Person(object):

        __count = 0
        @classmethod
        def how_may(cls):
            return cls.__count
            

        def __init__(self,name):
            self.name = name
            Person.__count += 1

    print Person.how_many()
    p1 = Person('Bob')
    print Person.how_many()     
    #输出  0   1

通过标记一个 @classmethod,该方法将绑定到 Person 类上,而非类的实例。类方法的第一个参数将传入类本身, 通常将参数名命名为 cls,上面的 cls.count 实际上相当于 Person.count。

因为是在类上调用,而非实例上调用,因此类方法无法获得任何实例变量,只能获得类的引用。

  

 

 

posted on 2015-12-05 10:48  徐长伟  阅读(138)  评论(0)    收藏  举报