python学习11-面向对象

原创 2016年05月31日 21:50:39

面向对象
对象可以看作数据以及由一系列可以存取,操作这些数据的方法所组成的集合。
多态:多态意味着就算不知道变量所引用的对象类型是什么,还是可以对他进行操作,而它也会根据对象类型的不同而表现出不同的行为。例如“+”运算符可以对数字和字符串2进行不同的操作。唯一能毁掉多态的就是使用函数显示地检查类型,比如type,ininstance以及issubclass函数。如果可能的话应尽力避免使用这些毁掉多态的方式。
如何创建一个类:
class MyNewObjectType(bases):
class_suit #类体
bases可以是一个或多个用于继承的父类。创建一个实例的过程称作实例化,过程如下:
myFirstObject = MyNewObjectType()
方法: 方法定义在类定义中,但只能被实例所引用。
class MyDataWithMethod(object):
def printFoo(self):
print ‘You invoked printFoo()!’
self参数在所有的方法声明中都存在。这个参数代表实例对象本身,当你用实例调用方法时,由解释器自动传递给方法,所以,你不需要自己传递self过来。一般的方法会需要这个实例(self),而静态方法或类方法不会,其中类方法需要类而不是实例。
python创建实例后,在实例化过程中,调用init()方法,当一个类被实例化时,就可以定义额外的行为。
类名通常以大写字母打头,这是标准惯例。
类属性仅与其被定义的类相绑定,并且因为实例对象在日常 OOP 中用得最多,实例数据属性是你将会一直用到的主要数据属性。类数据属性仅当需要有更加“静态”数据类型时才变得有用,它和任何实例都无关。
Python 严格要求,没有实例,方法是不能被调用的。这种限制即 Python所描述的绑定概念(binding)。
决定类的属性
要知道一个类有哪些属性,有两种方法。最简单的是使用 dir()内建函数。另外是通过访问类的字典属性dict,这是所有类都具备的特殊属性之一。
特殊类属性
C.name 类C的名字(字符串)
C.doc 类C的文档字符串
C.bases 类C的所有父类构成的元组
C.dict 类C的属性
C.module 类C定义所在的模块(1.5 版本新增)
C.class 实例C对应的类(仅新式类中)
new() “构造器”方法
init()相比,new()方法更像一个真正的构造器。类型和类在版本 2.2 就统一了,Python 用户可以对内建类型进行派生,因此,需要一种途径来实例化不可变对象,比如,派生字符串,数字,等等。在这种情况下,解释器则调用类的new()方法,一个静态方法,并且传入的参数是在类实例化操作时生成的。new()会调用父类的new()来创建对象(向上代理)。为何我们认为new()比init()更像构造器呢?这是因为new()必须返回一个合法的实例,这样解释器在调用init()时,就可以把这个实例作为 self 传给它。调用父类的new()来创建对象,正像其它语言中使用 new 关键字一样。
实例属性
实例仅拥有数据属性(方法严格来说是类属性)
,后者只是与某个类的实例相关联的数据值,并
且可以通过句点属性标识法来访问。这些值独立于其它实例或类。当一个实例被释放后,它的属性同时也被清除了。
能够在“运行时”创建实例属性,是 Python 类的优秀特性之一,Python 不仅是动态类型,而且在运行时,允许这些对象属性的动态创建。
对内建类型也可以使用dir(),与其他对象一样,可以得到一个包含它属性名字的列表。在内建类型中不存在dict这个属性。
类属性仅是与类相关的数据值,和
实例属性不同,类属性和实例无关。这些值像静态成员那样被引用,即使在多次实例化中调用类,它们的值都保持不变。不管如何,静态成员不会因为实例而改变它们的值,除非实例中显式改变它们的值。类和实例都是名字空间。类是类属性的名字空间,实例则是实例属性的。你可采用类来访问类属性,如果实例没有同名的属性的话,你也可以用实例来访问。
使用实例属性来试着修改类属性是很危险的。原因在于实例拥有它们自已的属性集,在 Python 中没有明确的方法来指示你想要修改同名的类属性,比如,没有 global关键字可以用来在一个函数中设置一个全局变量(来代替同名的局部变量)。修改类属性需要使用类名,而不是实例名。
调用非绑定方法
调用非绑定方法并不经常用到。需要调用一个还没有任何实例的类中的方法的一个重要场景是:你在派生一个子类而且你要覆盖父类的方法,这时你需要调用那个父类中想要覆盖掉的方法。
新式类和旧式类
为了确保类是新式类,应该为赋值语句 __metaclass__ = type 放在你的模块的最开始,或者子类化内建类object,考虑下面的两个类:
class NewStyle(object):
….more_code_here
class OldStyle(object):
….more_code_here
在这两个类中,NewStyle是新式类,OldStyle是旧式类。如果文件以__metaclass__ = type开始,那么这两个类都是新式类。
使用super函数:
当前的类和对象可以作为super函数的参数使用,调用函数返回的任何方法都是调用超类的方法,而不是当前类的方法。下面的例子,比较使用super函数和不使用super函数:
class Bird:
….def __init__(self):
……..self.hungry = True
….def eat(self):
……..if self.hungry:
…………print ‘Aaaaah….’
…………self.hungry = False
……..else:
…………print ‘No, thanks!’
不使用super函数,子类调用未绑定的超类方法。
class SongBird(Bird):
….def __inti__(self):
………Bird.__init__(self)
………self.sound = ‘squawk!’
….def sing(self):
………print self.sound
使用super函数,super函数只用在新式类中
class SongBird(Bird):
….def __init__(self):
……..super(SongBird, self).__init__()
……..self.sound = ‘squawk’
….def sing(self):
……..print self.sound
Property函数
通常我们在访问和赋值属性的时候,都是直接和类的__dict__打交道,或者跟函数描述符等在打交道。但是假如我们要规范这些访问和设值方式的话,一种方法是引入复杂的数据描述符机制,另一种恐怕就是轻量级的数据描述符协议函数Property().它的标准定义是:
property(fget = None, fset = None, fdel = None, doc = None)
前面三个参数都是未绑定的方法,所以它们事实上可以是任意的类成员函数。实例如下:
__metaclass__ = type
class Rectange:
….def __init__(self):
……..self.width = 0
……..self.height = 0
….def setSize(self, size):
……..self.width, self.height = size
….def getSize(self):
……..return self.width, self.height
size = property(getSize, setSize)
///r = Rectange()
///r.size
输出:(10, 5)
///r.size = 150, 100
///r.width
输出:150
静态方法和类成员方法
静态方法和类成员方法分别在创建时装入staticmethod类型和classmethod类型的对象中。静态方法的定义没有self参数,且能够被类本身直接调用。类方法在定义时需要名为cls的类似于self的参数,类成员方法可以直接用类的具体对象调用,但cls参数是自动被绑定到类的,示例:
__metaclass__= type
class MyClass:
….def smeth():
……..print ‘This is a static method’
….smeth = staticmethod(smeth)
….def cmeth():
……..print ‘This is a class method of’, cls
….cmeth = classmethod(cmeth)
装饰器 使用@操作符
__metaclass__ = type
class MyClass:
….@staticmethod
….def smeth():
……..print ‘This is a static method’
….@classmethod
….def cmeth():
……..print ‘This is a class method of’, cls
静态方法和类成员方法在python中向来都不是很重要,主要愿意是大部分情况下可以使用函数或者绑定方法代替。
从标准类型派生
不可变类型的例子:
将一个浮点数进行舍入操作保留两位:
class RoundFloat(flat):
….def __new__(cls, val):
……..return float.__new___(cls, round(val, 2))
我们通过调用父类的构造函数来创建真实对象float.__new__()注意所有的new方法都是类方法,我们要显式地传入类作为第一个参数,这类似于常见的方法如 __init__()中的self。通常情况下,最好是使用super()内建函数去捕获对应的父类以调用它的__new__方法。下面是对上面的修改:
class RoundFloat(float):
….def __new__(cls. val):
….return super(RoundFloat,cls).__new__(cls, round(val, 2))
*多重继承*
python允许子类继承多个基类,但最难的工作是如何正确找到没有当前子类定义的属性。当使用多重继承时有两个不同的方面要注意,首先还是要找到合适的属性,另一个是当你重写方法时,如何调用对应父类以发挥它们的作用。
方法调用顺序:
经典类为深度优先,新式类为广度优先。

版权声明:本文为博主原创文章,未经博主允许不得转载。

廖雪峰Python教程 学习笔记11 面向对象高级编程

1,_ slots_ (注意前后各有两个下划线)定义class时,用来限制class实例能添加的属性 class Animal(object): __slots__ = ('n...
  • the4U
  • the4U
  • 2016年10月24日 11:29
  • 207

java学习11-面向对象(overload与overwrite)

成员函数的特点:重载(overload) 特点:在同一个类里面,函数名与返回值相同,参数的类型或者参数的个数不相同。 最有特色的重载函数是:构造函数 例子: // 无参构造方法 public P...

【IOS 开发学习总结-OC-11】★objective-c面向对象之——封装和访问控制符

封装封装的定义面向对象的三大特征(封装,继承,多态)之一。指的是:将对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象内部信息,而是通过该类所提供的方法来实现对内部信息的操作和访问。良好的封装,...

C#/.net学习-11-面向对象多态

1、绝对路径和相对路径 绝对路径:通过给定的这个路径直接能在我的电脑中找到这个文件。 相对路径:文件相对于应用程序的路径。 结论: 我们在开发中应该去尽量的使用相对路径。 2、装箱、...
  • qqWAH
  • qqWAH
  • 2017年02月09日 09:05
  • 100

JavaScript for Kids 学习笔记11. 面向对象

本章讲面向对象。面向对象本身的概念就略过不说了。重要的是,javascript没有class关键字,那么如何创建一个class呢?...

C++学习笔记11-面向对象2

1.  只能初始化直接基类 一个类只能初始化自己的直接基类。直接就是在派生列表中指定的类。如果类C 从类B 派生,类B 从类A 派生,则B 是C 的直接基类。虽然每个C 类对象包含一个A 类部分,但C...
  • wzhiu
  • wzhiu
  • 2014年07月21日 19:03
  • 612

java面向对象 电子书11

  • 2008年01月25日 09:55
  • 9.54MB
  • 下载

python学习笔记1:面向对象的高级特性1__slots__

1.使用slots(第一次写博客下划线打不出来,请看代码): python是一种动态语言,在正常情况下,我们定义一个类,再创建一个类的实例,我们在运行代码的时候,可以通过给这个实例绑定一个属...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:python学习11-面向对象
举报原因:
原因补充:

(最多只允许输入30个字)