9. 类

来源:互联网 发布:西安财经行知特点 编辑:程序博客网 时间:2024/06/05 15:56
python 类中的 self 即指代  当前类的命名空间, 私以为和 C++ 中的 this 关键字同义.
python 类 中的数据属性 和 局部变量一样, 无需声明, 第一次使用即可生成.

sample:
class M:    str = 'hello'    def __init__(self):        str = 'zhangpzh5'x = M()x.count = 5print x.count

当然咯, 初始化类的对象, 如果要使之具有初始状态, 则可以在 __init__ 函数的参数列表中扩展参数列表.


sample:
class M:    str = 'hello'    count = 5def __init__ (self , cnt):    self.count = cntdef f(self):    return 'hello world'x = M(10)print x.count

输出5


注意到,实例对象x作为一个参数传给了函数. x= M(10)相当于 M.__init__(x,10)

x.f()相当于 M.f(x)

这就是所谓的 方法对象


数据属性会覆盖同名的方法属性, 为了避免意外的名称冲突,这在大型程序中是极难发现的 Bug,使用一些约定来减少冲突的机会是明智的。

函数定义代码不一定非得定义在类中:也可以将一个函数对象赋值给类中的一个局部变量。 例如:


# Function defined outside the classdef f1(self, x, y):    return min(x, x+y)class C:    f = f1    def g(self):        return 'hello world'    h = g

每个值都是一个对象,因此每个值都有一个 类( class ) (也称为它的 类型( type ) ),它存储为 object.__class__

继承:

class DerivedClassName(BaseClassName):    <statement-1>    .    .    .    <statement-N>

若基类定义在另一个模块中, 则使用表达式继承
class DerivedClassName(modname.BaseClassName):

对于一个子类, 如果在类中找不到对应的属性, 就搜索基类, 在找到对应属性之前, 这个集合会按 基类链 递归上去.

isinstance() 用于检查实例类型: isinstance(obj, int) 只有在obj.__class__int 或其它从 int 继承的类型

issubclass() 用于检查类继承:    issubclass(bool, int)True ,因为bool 是 int 的子类。但是, issubclass(unicode,str)False ,因为 unicode 不是str 的子类(它们只是共享一个通用祖先类basestring ).

在继承的时候,要注意命名空间的问题:
如下例:  knife 也是student类对象s的一个属性, 但是age不是. 因为在people类中, age定义在方法中.


class people:    knife = 5     def __init__(self):        age = 20.0        heigh = 175    def f(self):        return 'hello people'    def great(self):        return 'I love this world !'class student(people):    def __init__(self):        ID = 12348157    def f(self):        return 'hello student's = student()print s.knifeprint s.great();# print s.age

多继承:
class DerivedClassName(Base1, Base2, Base3):    <statement-1>    .    .    .    <statement-N>

  若派生类 中找不到某属性, 那么在自然情况下:  python会先从Base1 开始 dfs搜索它 的基类链, 若找不到, 则从Base2 开始dfs搜索它的基类链.

实际上, super()可以动态改变解析顺序


私有变量:

        只能从对像内部访问的“私有”实例变量,在 Python 中不存在。然而,也有一个变通的访问用于大多数 Python 代码:以一个下划线开头的命名(例如_spam )会被处理为 API 的非公开部分(无论它是一个函数、方法或数据成员)。它会被视为一个实现细节,无需公开。
        因为有一个正当的类私有成员用途(即避免子类里定义的命名与之冲突),Python 提供了对这种结构的有限支持,称为name mangling (命名编码) 。任何形如 __spam 的标识(前面至少两个下划线,后面至多一个),被替代为 _classname__spam ,去掉前导下划线的 classname 即当前的类名。此语法不关注标识的位置,只要求在类定义内。

举例说明:

class father:    def __init__(self,iterable):        self.myList = []        self.__update(iterable)    def update(self , iterable):            self.myList.append("This is father's update method !")        __update = updateclass son(father):    def update(self, iterable):        self.myList.append("This is son's update method !")list = []s = son(list)for string in s.myList:    print string,

如上图所示, son类的对象s在初始化的时候, 调用 父类father的__init__方法,  方法最后调用了__update, 由于__update只在类father中有效,  python会在father类中寻找__update的定义 , 发现 __update = update, 因此 python断定, 应当调用当前类中的update函数, 因此 程序的输出 为 "This is father' s update method !"
      但是,若将__init__方法中的最后一行改为:  "self.update(iterable)" , 则son类中的update方法会覆盖父类中的update方法, 程序的输出为 "This is son's update method !"
    
      说到这里,突然想起override和overload

① override(重写)指的是子类的方法覆盖父类的方法,且方法名相同, 参数列表相同
② overload(重载)指的是两个方法的名字相同,但是参数列表不相同.   两方法可以在一个类中,也可以不在一个类中.


Pascal中的record 和 C中的struct 都可以将特定数据类型 捆绑在一起 , 构成一个新的数据结构:

python中直接使用类可以达到此目的:

代码如下:

class Employment:passJohn = Employment()John.name = 'John.J.Rambo'John.words = 'You won\'t beat me !'

异常也是类:

两种异常抛出形式:

① raise Class
② raise Instance

解释:
① raise Class 是 raise Class()的简写
② Instance 必须是Class或其派生类的一个实例

发生的异常类型如果是 except子句中列出的类或其派生类, 那么它们就是相符的
但是如果发生的异常类型是except子句中列出的类的基类,那么它们就是不相符的

一个例子:

class A(Exception):    passclass B(A):    passclass C(B):    passlist = [C,B,A]for l in list:    try:        raise l()    except C:        print 'C'    except B:        print 'B'    except A:        print 'A'

屏幕将输出 C B A

迭代器:
大多数容器对象都可以使用for遍历
在后台, for语句在容器对象中调用iter(). 该函数返回一个定义了 next() 方法的迭代器对象,它在容器中逐一访问元素。
没有后续的元素时, next() 抛出一个 StopIteration 异常通知for 语句循环结束.

在了解了迭代器协议的后台机制后, 定义一个 __iter__ 方法, 定义一个 __iter__() 方法,使其返回一个带有next() 方法的对象。如果这个类已经定义了next() ,那么 __iter__() 只需要返回 self:

一个例子:

class Reverse:    def __init__(self,Str):        self.Str = Str        self.index = len(Str)    def __iter__(self):        return self        def __next__(self):        if(self.index == 0):            raise StopIteration        self.index -= 1        return self.Str[self.index]    next = __next__rev = Reverse("zhangpzh")for char in rev:    print char,


生成器:

生成器(generator) 是一种可以很简单地实现迭代器的方式, 比写一个类(基于类的迭代器)更方便些.  需要返回数据时使用yield语句. 生成器会自动创建 __iter__方法 和 next 方法. 关键是, 在两次执行之间, 局部变量和执行状态都会被保存下来. 终结时, 它也会抛出 StopIteration 异常

一个例子:

def forward(data):    for index in range(0,len(data),1):        yield data[index]for char in forward('Coke Cola'):    print char,


此例将 正向输出  Coke Cola

生成器表达式:

这将在我的博文  "推导式与生成器表达式" 中和推导式一起介绍.

0 0
原创粉丝点击