Python核心编程笔记 - 第13章 面向对象编程 (一)
来源:互联网 发布:淘宝客服怎么挣钱 编辑:程序博客网 时间:2024/06/14 22:35
Chapter 13. OOP
子类如果不定义自己的构造器(__init__()),基类的构造器就会被调用。然而,子类如果重写基类的构造器,基类的构造器就不会被自动调用了。这样,基类的构造器就必须显式地写出来才会被执行。
类名通常用大写字母打头,这是标准惯例。
Python不支持纯虚函数。
bound method 和 unbound method:
方法必须绑定到一个实例才能被直接调用;非绑定的方法可能可以被调用,但实例对象一定要明确给出,才能保证调用成功。
类的属性
要知道一个类有哪些属性,有2个方法:
- 用内建函数dir()
- 访问类的字典属性__dict__
内建的vars()函数接受类对象作为参数,返回类的__dict__属性的内容。
对于任何类C,其必有的所有特殊属性如下:
- C.__name__ 类C的名字(字符串)
- C.__doc__ 类C的文档字符串(文档字符串不会被派生类继承)
- C.__bases__ 类C的所有父类构成的元组
- C.__dict__ 类C的所有属性
- C.__module__ 类C定义所在的模块
- C.__class__ 实例C所对应的类(仅新式类),如’type’
__init_()_ 和 __new__()
用户可以对内建类型(如字符串、数字)进行派生,因此,需要一种途径来实例化不可变对象,比如派生字符串、派生数字等。在这种情况下,解释器调用类的__new__()方法,一个静态方法,并且传入的参数是类实例化操作时生成的。__new__()会调用父类的__new__()来创建对象(向上代理)。
__new__()必须返回一个合法的实例,这样解释器在调用__init__()时,就可以把这个实例作为self传给它。所以,__new__()的执行是在__init__()之前的。
__del__()
相应的desctructor方法名为__del__(). 由于Python具有垃圾对象回收机制(靠引用计数),这个函数要直到该实例对象所有的引用都被清除掉后才会执行。
关于__del__()的总结:
- 不要忘记首先调用父类的__del__()
- 调用 del x 仅仅表示减少 x 的引用计数,并不会去调用 __del__()
- 一般不要去实现 __del__()
类属性与实例属性
对实例属性的赋值会创建一个实例属性(如果不存在的话),但如果类属性中存在同名属性,就会有副作用。
看下面的代码:
class Foo(object): x = 1.5foo = Foo()print foo.x # 1.5foo.x = 2print foo.x # 2 (实例属性)print Foo.x # 1.5del foo.xprint foo.x # 1.5 (类属性)
再看一段代码,在类属性可变的情况下,就有不同了:
class Foo(object): x = {2003: 'poe2'}foo = Foo()print foo.x # {2003: 'poe2'}foo.x[2004] = 'poe3'print foo.x # {2003: 'poe2', 2004: 'poe3'}print Foo.x # {2003: 'poe2', 2004: 'poe3'} 竟然一样了!del foo.x # 会报AttributeError,因为没有遮蔽掉类属性
绑定和方法调用
方法只有在其所属的类拥有实例的时候,才能被调用。当存在一个实例时,方法才被认为是绑定到那个实例的;没有实例时,方法就是未绑定的。
调用非绑定方法:
需要调用一个还没有任何实例的类中的方法的一个主要场景是:在派生一个子类,而且要覆盖父类的构造方法,这时你需要调用父类中那个想要被覆盖掉的构造方法。
class B(A): def __init__(self, name, phone): A.__init__(self) self.name = name self.phone = phone
所以,典型的非绑定方式调用函数如下:
MyClass.method(instance)
静态方法(staticmethod) 和 类方法(classmethod)
class TestStaticMethod(object): @staticmethod def foo(): print "calling static method foo()"class TestClassMethod(object): @classmethod def foo(cls): print "calling class method foo()" print "foo() is part of class: ", cls.__name__TestStaticMethod.foo()TestClassMethod.foo()
执行效果如下:
>>> execfile("./1.py")calling static method foo()calling class method foo()foo() is part of class: TestClassMethod
方法解释顺序(MRO: Method Resolution Order)
经典类,使用深度优先算法。
新式类,使用新的C3算法,广度优先,子类在前,父类在后。
新式类有一个 __mro__ 属性,告诉你查找顺序是怎样的。
类、实例 和 其他对象的内建函数
issubclass(son, parent)
判断一个类是否是另一个类的子类或子孙类.
从Python2.3开始,issubclass()的第二个参数可以是一个元组(tuple)。这时,只要第一个参数是给定元组中任何一个类的子类,就会返回True.
isinstance(obj, cls)
如果obj是类cls的一个实例,或者是cls的子类的一个实例,就返回True.
isinstance()也可以使用一个元组作为第二个参数。如果第一个参数是第二个参数(元组)中的任何一个类的实例,就返回True.
hasattr(), getattr(), setattr(), delattr()
*attr()系列函数可以在各种对象下工作,不限于类和实例。第一个参数是需要被处理的对象,第二个参数是某属性名字的字符串。
- hasattr(obj, attr): 检查某个对象是否具有某个特定的属性。
- getattr(obj, attr[, default]): 取得某个对象的某属性值。
- setattr(obj, attr, val): 要么加入一个新的属性,要么取代一个已存在的属性。
- delattr(obj, attr): 从一个对象中删除属性。
dir(obj=None)
- dir()作用在实例上(经典类或新式类)时,显示实例变量,还有实例所在的类以及所有它的基类中定义的方法和类属性;
- dir()作用在类上(经典类或新式类)时,则显示类以及它的所有基类的__dict__中的内容;不会显示定义在元类(metaclass)中的类的属性;
- dir()作用在模块上时,显示模块的__dict__的内容;
- dir()不带参数时,显示调用者的局部变量。
super()
另有博文详述。
vars(obj=None)
vars()内建函数与dir()相似,只是给定的对象参数都必须有一个__dict__属性。
vars()返回一个字典,包含了对象存储于其__dict__中的属性(key)和值。
如果vars()不带参数,则显示一个包含本地名字空间的属性(key)及其值的字典,也就是locals().
迭代器 (用类实现)
先看示例代码randSeq.py:
from random import choiceclass RandSeq(object): def __init__(self, seq): self.data = seq def __iter__(self): return self def next(self): return choice(self.data)
以上代码中,重要的是函数__iter__(), 它仅返回self,就正是如何将一个对象声明为迭代器的方式;
最后调用next()来得到迭代器中连续的值。这个迭代器是一个没有终点的迭代器。
__slots__ 类属性
用户可以用__slots__属性代替__dict__.
基本上,__slots__是一个类变量,由一个序列型对象组成,由所有合法标识构成的实例属性的集合来表示。它可以是一个列表、元组或可迭代对象,也可以是标识实例能拥有的唯一的属性的简单字符串。
任何试图创建一个其名不在__slots__中的名字的实例属性都将导致AttributeError异常。
class SlottedClass(object): __slots__ = ('foo', 'bar')>>> c = SlottedClass()>>> c.xxx = "don't think so"Traceback (most recent call last): File "<stdin>", line 1, in ?AttributeError: 'SlottedClass' object has no attribute 'xxx'
这种特性的主要目的是节约内存。其副作用是某种类型的“安全”,它能防止用户随心所欲地动态增加实例的属性。
带__slots__的类定义不会包含__dict__了。
__getattribute__ 特殊方法
- __getattr__(),它仅当属性无法在实例的 __dict__ 或 它的类的__dict__ ,或 祖先类的__dict__中找到时,才被调用。
- __getattribute__ (), 执行对每一个属性的访问,无论是否能找到。
- 如果类同时定义了__getattribute__()和 __getattr__() 方法,除非明确从__getattribute__()调用,或__getattribute__()引发了AttributeError异常,否则后者不会被调用。
- Python核心编程笔记 - 第13章 面向对象编程 (一)
- Python核心编程笔记 - 第13章 面向对象编程(二)
- 《Python核心编程》第13章 面向对象编程 练习
- Python核心编程---读书笔记:第13章 面向对象编程
- 《Python核心编程》 面向对象编程学习笔记
- Python核心编程读书笔记--面向对象编程
- Python核心编程(第十三章)--面向对象编程
- python核心编程学习笔记(一)
- Python核心编程学习笔记(一)
- Python核心编程学习笔记(一)
- <Python核心编程>笔记(一)
- Python 面向对象编程(一)
- Python 面向对象编程(一)
- Python 面向对象编程(一)基础
- Python 面向对象编程(一)
- Python 面向对象编程(一)
- Python 面向对象编程(一)
- Python 面向对象编程(一)
- SCU - 4444 别样最短路径-大数据完全图
- Linux下安装pyspider的详细过程和相关指令【无总结版】
- Android 数据存取之SQLite浅析
- composer安装
- 如何去掉drwxr-xr-x@中的@符号Linux文件扩展信息
- Python核心编程笔记 - 第13章 面向对象编程 (一)
- 1018. Public Bike Management (30) 最短路问题
- JLable动态更新
- laravel框架安装
- 写在前面
- EffectiveC++
- #LeetCode# #C++# Symmetric Tree
- 10.1做题——洛谷P1433 吃奶酪
- JAVA基础--db18_javaSystem&Math&Date&IO流