Python进阶笔记(4)_ 面向对象编程基础
2016-08-08 13:24
519 查看
根据操作数据的函数或语句块来设计程序的。这被称为面向过程的编程。
还有一种把数据和功能结合起来,用称为对象的东西包裹起来组织程序的方法。这种方法称为面向对象的编程理念。
类和对象是面向对象编程的两个主要方面。类创建一个新类型,而对象是这个类的实例。
对象可以使用属于对象或类的变量存储数据。这样的变量被称为域。因此,域有两种类型——实例属性和类属性,前者属于每个实例/类的对象,后者属于类本身。关于这个知识点,我们将在下文“类属性和实例属性”一节中讲解。
【注】不同文献将属性称为变量,实例称为对象。所以会看到 对象的变量和类的变量等描述。
对象也可以使用属于类的函数来具有功能。这样的函数被称为类的方法。
这些术语帮助我们把它们与孤立的变量和函数区分开来。域和方法可以合称为类的属性。
类使用 class 关键字创建。类的域和方法被列在一个缩进块中。
域
创建一个类
按照 Python 的编程习惯,类名以大写字母开头,紧接着是(object),表示该类是从哪个类继承下来的。类的继承将在后面的章节讲解,现在我们只需要简单地从object类继承。
上例的输出为
可以看到,虽然都是用 People 这个类定义的,但二者并不相同,且存储位置也不同。
创建实例属性
由于Python是动态语言,对每一个实例,都可以直接给他们的属性赋值。而且可以赋予不同内容的属性。
实例的属性可以像普通变量一样进行操作:
初始化实例属性 __int__()
如果,我们希望定义的类都拥有相同的属性内容,可以用 def __int__() 方法来定义初始值。注意,__int__ 这里是两个下划线 + int + 两个下划线。
输出为
访问限制
Python对属性权限的控制是通过属性名来实现的,如果一个属性由双下划线开头__,该属性就无法被外部访问。
类属性和实例属性
我们通过具体例子来认识类属性和实例属性。
输出为
这里, population属于Person类,因此是一个类属性。name变量属于对象
4000
(它使用 self 赋值)因此是实例属性。可以看到,population 是累加的。
绑定在一个实例上的属性不会影响其他实例,但是,类本身也是一个实例,如果在类上绑定一个属性,则所有实例都可以访问类的属性,并且,所有实例访问的类属性都是同一个!也就是说,实例属性每个对象各自拥有,互相独立,而类属性有且只有一份。
好,问题来了,怎么能让两个相同的类具有不同的类属性呢?
看下例就一目了然了。
输出
这里P.address = England 就将 P.address 命令为一个实例属性。这里只改变了 P 的类属性,而Person 的类属性并没有改变。可见,当实例属性和类属性重名时,实例属性优先级高,它将屏蔽掉对类属性访问。
若要消除的实例属性后,再访问P.address 就返回原来 Person 的类属性值了。
方法
定义实例方法
一个实例的私有属性就是以__开头的属性,无法被外部访问,那这些属性定义有什么用?
虽然私有属性无法从外部访问,但是,从类的内部是可以访问的。除了可以定义实例的属性外,还可以定义实例的方法。
实例的方法就是在类中定义的函数,它的第一个参数永远是 self,指向调用该方法的实例本身,其他参数和一个普通函数是完全一样的:
在实例方法内部,可以访问所有实例属性,这样,如果外部需要访问私有属性,可以通过方法调用获得,这种数据封装的形式除了能保护内部数据一致性外,还可以简化外部调用的难度。
将函数定义为方法
我们在 class 中定义的实例方法其实也是属性,它实际上是一个函数对象。因为方法也是一个属性,所以,它也可以动态地添加到实例上,只是需要用 types.MethodType() 把一个函数变为一个方法:
输出为:
出错原因在于 p2 实例并没有绑定 get_grade。
类方法
和属性类似,方法也分实例方法和类方法。
在class中定义的全部是实例方法,实例方法第一个参数 self 是实例本身。
要在class中定义类方法,需要这么写:
通过标记一个 @classmethod,该方法将绑定到 Person 类上,而非类的实例。类方法的第一个参数将传入类本身,通常将参数名命名为 cls,上面的 cls.count 实际上相当于 Person.count。
还有一种把数据和功能结合起来,用称为对象的东西包裹起来组织程序的方法。这种方法称为面向对象的编程理念。
类和对象是面向对象编程的两个主要方面。类创建一个新类型,而对象是这个类的实例。
对象可以使用属于对象或类的变量存储数据。这样的变量被称为域。因此,域有两种类型——实例属性和类属性,前者属于每个实例/类的对象,后者属于类本身。关于这个知识点,我们将在下文“类属性和实例属性”一节中讲解。
【注】不同文献将属性称为变量,实例称为对象。所以会看到 对象的变量和类的变量等描述。
对象也可以使用属于类的函数来具有功能。这样的函数被称为类的方法。
这些术语帮助我们把它们与孤立的变量和函数区分开来。域和方法可以合称为类的属性。
类使用 class 关键字创建。类的域和方法被列在一个缩进块中。
域
创建一个类
按照 Python 的编程习惯,类名以大写字母开头,紧接着是(object),表示该类是从哪个类继承下来的。类的继承将在后面的章节讲解,现在我们只需要简单地从object类继承。
class People(object): pass # An empty block Phoenix = People() Tree = People() print Phoenix print Tree print Phoenix = = Tree
上例的输出为
<__main__.People object at 0x7f771d1414d0> <__main__.People object at 0x7f771d156850> False
可以看到,虽然都是用 People 这个类定义的,但二者并不相同,且存储位置也不同。
创建实例属性
由于Python是动态语言,对每一个实例,都可以直接给他们的属性赋值。而且可以赋予不同内容的属性。
class People(object): pass Phoenix = People() Phoenix .name = 'Phoenix' Phoenix .gender = 'Male' Phoenix .grade = 3 Tree = People() Tree .name = 'Tree' Tree .school = 'No. 2 High School' Tree .grade = 2
实例的属性可以像普通变量一样进行操作:
Phoenix.grade = Tree.grade + 1
初始化实例属性 __int__()
如果,我们希望定义的类都拥有相同的属性内容,可以用 def __int__() 方法来定义初始值。注意,__int__ 这里是两个下划线 + int + 两个下划线。
class People(object): def __init__(self, name, gender, birth, **kw): self.name = name self.gender = gender self.birth = birth for k, v in kw.iteritems(): setattr(self, k, v) Phoenix = People('Phoenix', 'Male', '1995-04-25', job='Student') print Phoenix.name print Phoenix.job
输出为
Phoenix Student这里,我们看到除了接受 name、gender 和 birth 外,还可接受任意关键字参数,比如 job,并把他们都作为属性赋值给实例。
访问限制
Python对属性权限的控制是通过属性名来实现的,如果一个属性由双下划线开头__,该属性就无法被外部访问。
class People(object): def __init__(self, name, score): self.name = name self._gender = 'Male' self.__score = score p = People('Phoenix', 97) print p.name print p._gender print p.__score上例的输出为
Phoenix Male Traceback (most recent call last): File "C:/Users/PhoenixTree/Desktop/test.py", line 9, in <module> print p.__score AttributeError: 'People' object has no attribute '__score'
类属性和实例属性
我们通过具体例子来认识类属性和实例属性。
输出为
这里, population属于Person类,因此是一个类属性。name变量属于对象
4000
(它使用 self 赋值)因此是实例属性。可以看到,population 是累加的。
绑定在一个实例上的属性不会影响其他实例,但是,类本身也是一个实例,如果在类上绑定一个属性,则所有实例都可以访问类的属性,并且,所有实例访问的类属性都是同一个!也就是说,实例属性每个对象各自拥有,互相独立,而类属性有且只有一份。
好,问题来了,怎么能让两个相同的类具有不同的类属性呢?
看下例就一目了然了。
输出
这里P.address = England 就将 P.address 命令为一个实例属性。这里只改变了 P 的类属性,而Person 的类属性并没有改变。可见,当实例属性和类属性重名时,实例属性优先级高,它将屏蔽掉对类属性访问。
若要消除的实例属性后,再访问P.address 就返回原来 Person 的类属性值了。
del P.address print P.address输出 China 。
方法
定义实例方法
一个实例的私有属性就是以__开头的属性,无法被外部访问,那这些属性定义有什么用?
虽然私有属性无法从外部访问,但是,从类的内部是可以访问的。除了可以定义实例的属性外,还可以定义实例的方法。
实例的方法就是在类中定义的函数,它的第一个参数永远是 self,指向调用该方法的实例本身,其他参数和一个普通函数是完全一样的:
class Person(object): def __init__(self, name, score): self.name = name self.__score = score def get_grade(self): if self.__score == 100: print self.name + 'is excellent' elif self.__score > 95: print self.name + 'is good' else: print self.name + 'is need work harder' p1 = Person('Phoenix', 97) p2 = Person('Tree', 100) p3 = Person('Sky', 93) print p1.get_grade() print p2.get_grade() print p3.get_grade()get_score(self) 就是一个实例方法,它的第一个参数是self。__init__(self, name)其实也可看做是一个特殊的实例方法。输出为
Phoenix is good None Tree is excellent None Sky is need work harder None
在实例方法内部,可以访问所有实例属性,这样,如果外部需要访问私有属性,可以通过方法调用获得,这种数据封装的形式除了能保护内部数据一致性外,还可以简化外部调用的难度。
将函数定义为方法
我们在 class 中定义的实例方法其实也是属性,它实际上是一个函数对象。因为方法也是一个属性,所以,它也可以动态地添加到实例上,只是需要用 types.MethodType() 把一个函数变为一个方法:
输出为:
出错原因在于 p2 实例并没有绑定 get_grade。
类方法
和属性类似,方法也分实例方法和类方法。
在class中定义的全部是实例方法,实例方法第一个参数 self 是实例本身。
要在class中定义类方法,需要这么写:
class Person(object): __count = 0 @classmethod def how_many(cls): return cls.__count def __init__(self, name): self.name = name Person.__count = Person.__count + 1 p1 = Person('Phoenix') print Person.how_many() p2 = Person('Tree') print Person.how_many()输出结果为 1 2
通过标记一个 @classmethod,该方法将绑定到 Person 类上,而非类的实例。类方法的第一个参数将传入类本身,通常将参数名命名为 cls,上面的 cls.count 实际上相当于 Person.count。
相关文章推荐
- [Python入门及进阶笔记]Python-基础-元组小结
- [Python入门及进阶笔记]Python-基础-数字小结
- [Python入门及进阶笔记]Python-基础-字符串小结
- 廖雪峰老师——Python进阶( 面向对象编程基础 )
- [Python入门及进阶笔记]Python-基础-元组小结
- [Python入门及进阶笔记]Python-基础-简介/入门
- [Python入门及进阶笔记]Python-基础-文件处理小结
- [Python入门及进阶笔记]Python-基础-内置函数小结
- 学习笔记☞ python 基础(python3)【七】(面向对象编程-3)
- [Python入门及进阶笔记]Python-基础-字典小结
- [Python入门及进阶笔记]Python-基础-集合小结
- [Python入门及进阶笔记]Python-基础-数字处理相关模块
- [Python入门及进阶笔记]Python-基础-内置函数小结
- [Python入门及进阶笔记]Python-基础-列表及列表解析小结
- [Python入门及进阶笔记]Python-基础-数字小结
- [Python入门及进阶笔记]Python-基础-文件处理小结
- [Python入门及进阶笔记]Python-基础-集合小结
- Python基础-第七天-面向对象编程进阶和Socket编程简介
- python基础学习笔记<进阶>
- [Python入门及进阶笔记]Python-基础-函数小结