python面向对象

1、类的定义:

    # _*_ coding:utf-8_*_

    class Student(object):# 继承object类,不写也可以,不写就不能调用object类里面的方法,一般写上
        def __init__(self, name, score):
            self.name = name
            self.score = score

        def print_msg(self): # 没有返回值
            print '姓名:%s ,分数:%s' % (self.name, self.score)

        def return_name(self): # 有返回值
            return '姓名:%s ,分数:%s' % (self.name, self.score)

    if __name__ == "__main__":
        s = Student("zhangsan",60) # 实例化一个对象
        print Student # <class '__main__.Student'>
        print s # <__main__.Student object at 0x0255A9D0>
        print s.print_msg() # 姓名:zhangsan ,分数:60,None;注意还会打出一个None,因为这个方法没有返回值
        print s.return_name() # 姓名:zhangsan ,分数:60,这个就没有None了
注意:
    __init__方法的第一个参数永远是self,表示创建的实例本身,因此,在__init__方法内部,就可以把各种属性绑定到self,因为self就指向创建的实例本身。

2、类的访问限制(加__):

从前面Student类的定义来看,外部代码还是可以自由地修改一个实例的name、score属性
例如我可以 s.name = "lisi"

如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__
在Python中,实例的变量名如果以__开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问。
修改如下:
        class Student(object):# 继承object类,不写也可以,不写就不能调用object类里面的方法,一般写上
            def __init__(self, name, score):
                self.__name = name
                self.__score = score

            def print_msg(self):
                print '姓名:%s ,分数:%s' % (self.__name, self.__score)

            def return_name(self):
                return '姓名:%s ,分数:%s' % (self.__name, self.__score)
        # 这样在外部调用 s.name = "lisi"就无效了,确保了外部代码不能随意修改对象内部的状态,这样通过访问限制的保护,代码更加健壮。
如果外部代码要获取name和score怎么办?可以通过提供get set方法解决
例如:
        class Student(object):# 继承object类,不写也可以,不写就不能调用object类里面的方法,一般写上
            def __init__(self, name, score):
                self.__name = name
                self.__score = score

            def print_msg(self):
                print '姓名:%s ,分数:%s' % (self.__name, self.__score)

            def return_name(self):
                return '姓名:%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')

        #外面可以直接通过get_name() 和 get_score来访问内部数据。
特别注意:
    a.在Python中,变量名类似__xxx__的,也就是以双下划线开头,并且以双下划线结尾的,是特殊变量,特殊变量是可以直接访问的,不是private变量。
        所以,不能用__name__、__score__这样的变量名。
        如果用__score__,在外部是可以通过 s.__score__访问到的。
    b.有些时候,你会看到以一个下划线开头的实例变量名,比如_name,这样的实例变量外部是可以访问的.
        但是,按照约定俗成的规定,当你看到这样的变量时,意思就是,“虽然我可以被访问,但是,请把我视为私有变量,不要随意访问”。
    c.双下划线开头的实例变量是不是一定不能从外部访问呢?
        其实也不是。不能直接访问__name是因为Python解释器对外把__name变量改成了_Student__name,所以,仍然可以通过_Student__name来访
        例如:print s._Student__name # zhangsan

3、继承和多态:

    class Animal(object): # 父类
        def run(self):
            print 'Animal running...'

        def run_1(animal):
            animal.run()

    class Dog(Animal): # 子类
        def run(self): # 重写方法
            print 'Dog running...'

    class Cat(Animal): # 子类
        def run(self):
            print 'Cat running...'

    def test_extend():
        dog = Dog()
        dog.run() # Dog running...
        cat = Cat()
        cat.run() # Cat running...

        # 多态,可以传入不同的对象,会自动调用对应对象的run方法
        Animal.run_1(dog)
        Animal.run_1(cat)

    if __name__ == "__main__":
        test_extend()
继承可以把父类的所有功能都直接拿过来,这样就不必重零做起,子类只需要新增自己特有的方法,也可以把父类不适合的方法覆盖重写;

注意调用父类的方法
        class Dog(Animal):
            def run(self):
                print 'Dog running...'
                super(Dog, self).run() # 通过Dog找到父类Animal,再将self传到父类初始化

4、获取对象的信息

a.type()
    通过type可以判断一个对象的数据类型
        import types
        def test_type():
            print type(123) # <type 'int'>
            print type('str') # <type 'str'>
            print type(None) # <type 'NoneType'>
            print type('abc') == types.StringType # True
b.isinstance()
    对于class的继承关系来说,使用type()就很不方便。我们要判断class的类型,可以使用isinstance()函数。
        dog = Dog()
        print isinstance(dog,Animal) # True

5、@property使用:

a.使用get set的问题?
在绑定属性时,如果我们直接把属性暴露出去,虽然写起来很简单,但是,没办法检查参数,导致可以把成绩随便改
例如:
    s = Student()
    s.score = 9999
为了限制score的范围,可以通过一个set_score()方法来设置成绩,再通过一个get_score()来获取成绩,这样,在set_score()方法里,就可以检查参数
例如:
        class Student(object):
            def get_score(self):
                return self._score
            def set_score(self, value):
                if not isinstance(value, int):
                    raise ValueError('score must be an integer!')
                if value < 0 or value > 100:
                    raise ValueError('score must between 0 ~ 100!')
                self._score = value
    但是,上面的调用方法又略显复杂,没有直接用属性这么直接简单。

b.@property解决方案
    Python内置的@property装饰器就是负责把一个方法变成属性调用的。
    例如:
        class Studentt(object):
            @property #修饰get方法
            def score(self):
                return self.__score

            @score.setter #修饰set方法
            def score(self, value):
                if not isinstance(value, int):
                    raise ValueError('score must be an integer!')
                if value < 0 or value > 100:
                    raise ValueError('score must between 0 ~ 100!')
                self.__score = value
    注意:还可以定义只读属性,只定义getter方法,不定义setter方法就是一个只读属性。
    例如:
        class Studentt(object):
            @property # 只修饰get方法,没有修饰set方法
            def score(self):
                return self.__score

        if __name__ == "__main__":
            s = Studentt()
            s.score = 60
            print s.score

        这样运行会报错,提示没有set属性
            Traceback (most recent call last):
              File "D:/test_class.py", line 96, in <module>
                s.score = 60
            AttributeError: can't set attribute
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值