您的位置:首页 > 编程语言 > Python开发

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()
,我们可以直接操作一个对象的状态,分别是得到,设置和是否拥有属性和方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: