Python学习 (五 面向对象编程)
2016-05-25 10:25
423 查看
前言:面向对象编程——Object Oriented Programing,简称OOP。在Python中,所有数据类型都可以视为对象,当然也可以自定义对象。自定义的对象数据类型就是面向对象中的类(Class)
的概念。对象拥有属性(property)
,调用对象的对应的关联函数,称之为对象的方法(method)
。数据封装、继承和多态是面向对象的三大特点。
5.1 类和实例
牢记类(Class)和实例(instance)的概念,实例就是类的具象化,类是实例的模版。在Python中,定义类通过关键字class,之后紧接类名,通常是大写开头的单词,再是
(object),object是所有类都会继承的类。
>>> class Student(object): ... def __int__(self,name,score): #绑定属性必须用__int__,第一个属性必须是self ... self.name = name #给实例绑定属性 ... self.socre = score ... >>> elite = Student() # elite就是一个实例 >>> elite <__main__.Student object at 0x02C08370> >>> Student <class '__main__.Student'> >>> elite.name = "Peter" # 然而在这个时候对未定义属性进行赋值,依旧成立 = = >>> elite.score = 100 >>> elite.name 'Peter' >>> elite.score 100
数据封装
>>> 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) ... >>> elite = Student('Peter',100) #必须以这样的形式对elite进行实例化,传入具体参数 >>> elite.print_score() Peter: 100 #可以紧接着添加新的方法 ... def get_grade(self): ... if self.score > 90: ... print 'A' ... elif self.score >= 60: ... print 'B' ... else: ... print 'C' ... >>> elite = Student('Peter',100) >>> elite.get_grade() A
注意的地方:
类是创建实例的模板,而实例则是一个一个具体的对象,各个实例拥有的数据都互相独立,互不影响
方法就是与实例绑定的函数,和普通函数不同,方法可以直接访问实例的数据
通过在实例上调用方法,我们就直接操作了对象内部的数据,但无需知道方法内部的实现细节
Python允许对实例变量绑定任何数据,比如
elite.gender = 'male'
5.2 访问限制
外部代码可以随意修改实例中的数据,如果要让内部属性不被外部访问,可以在属性名称前面加两个下划线__,在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) ... >>> elite = Student('Peter',100) >>> elite.__name Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'Student' object has no attribute '__name' #无法访问 >>> elite._Student__name # 然而。。。 'Peter'
假装没看见
然而,那如何获取成为私有变量的值呢?可以继续添加方法(method)。
>>> class Student(object): ... def __init__(self,name,score): ... self.__name = name ... self.__score = score ... def get_score(self): ... return self.__score ... def set_score(self,score): ... if 0 <= score <= 100: ... self.__score = score ... else: ... raise ValueError('bad score') ... >>> elite = Student('Peter',100) >>> elite.get_score() 100 >>> elite.set_score('A') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 11, in set_score ValueError: bad score >>> elite.set_score(98) >>> elite.get_score() 98
需要注意的是,在Python中,变量名类似
__xxx__的,也就是以双下划线开头,并且以双下划线结尾的,是特殊变量,特殊变量是可以直接访问的,不是private变量,所以,不能用
__name__、
__score__这样的变量名。后面会讲到如果用
dir()方法会出现类似的变量名。需要强调的是Python本身没有任何机制阻止你干坏事,一切全靠自觉。
5.3 继承和多态
在OOP程序设计中,当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类、父类或超类(Base class、Super class)。继承有什么好处?最大的好处是子类获得了父类的全部功能。
>>> class Animal(object): ... def run(self): ... print 'Animal is running' ... >>> class Dog(Animal): ... pass ... >>> dog = Dog() >>> dog.run() Animal is running
也可以对子类增加一些方法,但是如果方法名称一样,那就会被覆盖。
>>> class Dog(Animal): ... def run(self): ... print 'Dog is running' ... >>> dog = Dog() >>> dog.run() Dog is running
定义了class,其实也就是定义了一个数据类型,和str ,int,list和dict没甚区别。判断一个变量是否为某种类型可以用
isinstance(),要注意和
type()的区别。而继承的类型可以满足集中类,也就是子类中的实例肯定满足子类,但是也会满足父类。
继承可以把父类的所有功能都直接拿过来,这样就不必重零做起,子类只需要新增自己特有的方法,也可以把父类不适合的方法覆盖重写
有了继承,才能有多态。在调用类实例方法的时候,尽量把变量视作父类类型,这样,所有子类类型都可以正常被接收
5.4 获取对象信息
使用type()
用法如下:>>> import types >>> type('aa')==types.StringType True >>> type(int)==type(str)==types.TypeType True
使用isinstance()
可以用type()判断的都能用
isinstance()判断,后者应该是多了对变量的支持。
使用dir()
可以获取一个对象的所有属性和方法,简称attribute?
>>> dir('abc') ['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__gt__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__mo d__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_formatter_field_name_split', '_formatter_parser', 'capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'index', 'isalnum', 'isalpha', 'isdigit', 'isl ower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition', 'replace', 'rfind', 'rindex', ' rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate' , 'upper', 'zfill']
带双下划线的都是特殊用途的,例如
__len__,代表返回长度,其实在使用
len()函数时,它是自动调用的
__len__()方法。。。。
>>> len('abc') 3 >>> 'abc'.__len__() 3
仅仅把属性和方法列出来是不够的,配合
getattr()、
setattr()以及
hasattr(),我们可以直接操作一个对象的状态,分别是得到,设置和是否拥有属性和方法。
相关文章推荐
- leetcode 35. Search Insert Position-二分查找|递归|非递归
- Python 面向对象 —— __slots__ 与 @property(python 下的 getter、setter 方法)
- python 爬虫登陆学校教务系统
- Python Machine Learning---scikit-learn
- 350. Intersection of Two Arrays II [easy] (Python)
- 你可能不知道的30个Python语言的特点技巧
- python中的model模板中的数据类型
- python玩转大数据-(一)
- Python+Scrapy安装
- Python参数传递 - 引用传递&值传递
- 利用python快速实现不同机器间文件夹共享
- python packages
- python np.linspace
- 一台电脑同时安装不同的python、django版本
- Python学习笔记-day0
- python实例
- Python的re模块正则表达式操作
- python learning_curve函数
- 调整python默认递归深度
- python 检测代码性能